oomph::XdaTetMesh< ELEMENT > Class Template Reference

Tet mesh made of quadratic (ten node) tets built from xda input file. More...

#include <xda_tet_mesh.template.h>

+ Inheritance diagram for oomph::XdaTetMesh< ELEMENT >:

Public Member Functions

 XdaTetMesh (const std::string xda_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
 
void setup_boundary_coordinates (const unsigned &b, const bool &switch_normal)
 
void setup_boundary_coordinates (const unsigned &b, const bool &switch_normal, std::ofstream &outfile)
 
unsigned nxda_boundary ()
 
Vector< unsignedoomph_lib_boundary_ids (const unsigned &xda_boundary_id)
 
- Public Member Functions inherited from oomph::TetMeshBase
 TetMeshBase ()
 Constructor. More...
 
 TetMeshBase (const TetMeshBase &node)=delete
 Broken copy constructor. More...
 
void operator= (const TetMeshBase &)=delete
 Broken assignment operator. More...
 
virtual ~TetMeshBase ()
 Destructor (empty) More...
 
void assess_mesh_quality (std::ofstream &some_file)
 
template<class ELEMENT >
void setup_boundary_coordinates (const unsigned &b)
 
template<class ELEMENT >
void setup_boundary_coordinates (const unsigned &b, const bool &switch_normal)
 
template<class ELEMENT >
void setup_boundary_coordinates (const unsigned &b, const bool &switch_normal, std::ofstream &outfile)
 
template<class ELEMENT >
void setup_boundary_coordinates (const unsigned &b, std::ofstream &outfile)
 
unsigned nboundary_element_in_region (const unsigned &b, const unsigned &r) const
 Return the number of elements adjacent to boundary b in region r. More...
 
FiniteElementboundary_element_in_region_pt (const unsigned &b, const unsigned &r, const unsigned &e) const
 Return pointer to the e-th element adjacent to boundary b in region r. More...
 
int face_index_at_boundary_in_region (const unsigned &b, const unsigned &r, const unsigned &e) const
 Return face index of the e-th element adjacent to boundary b in region r. More...
 
unsigned nregion ()
 Return the number of regions specified by attributes. More...
 
unsigned nregion_element (const unsigned &r)
 Return the number of elements in region r. More...
 
double region_attribute (const unsigned &i)
 
FiniteElementregion_element_pt (const unsigned &r, const unsigned &e)
 Return the e-th element in the r-th region. More...
 
template<class ELEMENT >
void snap_to_quadratic_surface (const Vector< unsigned > &boundary_id, const std::string &quadratic_surface_file_name, const bool &switch_normal, DocInfo &doc_info)
 
template<class ELEMENT >
void snap_to_quadratic_surface (const Vector< unsigned > &boundary_id, const std::string &quadratic_surface_file_name, const bool &switch_normal)
 
void snap_nodes_onto_geometric_objects ()
 
template<class ELEMENT >
void split_elements_in_corners (TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
 
void setup_boundary_element_info ()
 
void setup_boundary_element_info (std::ostream &outfile)
 
- Public Member Functions inherited from oomph::Mesh
 Mesh ()
 Default constructor. More...
 
 Mesh (const Vector< Mesh * > &sub_mesh_pt)
 
void merge_meshes (const Vector< Mesh * > &sub_mesh_pt)
 
virtual void reset_boundary_element_info (Vector< unsigned > &ntmp_boundary_elements, Vector< Vector< unsigned >> &ntmp_boundary_elements_in_region, Vector< FiniteElement * > &deleted_elements)
 Virtual function to perform the reset boundary elements info rutines. More...
 
template<class BULK_ELEMENT >
void doc_boundary_coordinates (const unsigned &b, std::ofstream &the_file)
 
virtual void scale_mesh (const double &factor)
 
 Mesh (const Mesh &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const Mesh &)=delete
 Broken assignment operator. More...
 
virtual ~Mesh ()
 Virtual Destructor to clean up all memory. More...
 
void flush_element_and_node_storage ()
 
void flush_element_storage ()
 
void flush_node_storage ()
 
Node *& node_pt (const unsigned long &n)
 Return pointer to global node n. More...
 
Nodenode_pt (const unsigned long &n) const
 Return pointer to global node n (const version) More...
 
GeneralisedElement *& element_pt (const unsigned long &e)
 Return pointer to element e. More...
 
GeneralisedElementelement_pt (const unsigned long &e) const
 Return pointer to element e (const version) More...
 
const Vector< GeneralisedElement * > & element_pt () const
 Return reference to the Vector of elements. More...
 
Vector< GeneralisedElement * > & element_pt ()
 Return reference to the Vector of elements. More...
 
FiniteElementfinite_element_pt (const unsigned &e) const
 
Node *& boundary_node_pt (const unsigned &b, const unsigned &n)
 Return pointer to node n on boundary b. More...
 
Nodeboundary_node_pt (const unsigned &b, const unsigned &n) const
 Return pointer to node n on boundary b. More...
 
void set_nboundary (const unsigned &nbound)
 Set the number of boundaries in the mesh. More...
 
void remove_boundary_nodes ()
 Clear all pointers to boundary nodes. More...
 
void remove_boundary_nodes (const unsigned &b)
 
void remove_boundary_node (const unsigned &b, Node *const &node_pt)
 Remove a node from the boundary b. More...
 
void add_boundary_node (const unsigned &b, Node *const &node_pt)
 Add a (pointer to) a node to the b-th boundary. More...
 
void copy_boundary_node_data_from_nodes ()
 
bool boundary_coordinate_exists (const unsigned &i) const
 Indicate whether the i-th boundary has an intrinsic coordinate. More...
 
unsigned long nelement () const
 Return number of elements in the mesh. More...
 
unsigned long nnode () const
 Return number of nodes in the mesh. More...
 
unsigned ndof_types () const
 Return number of dof types in mesh. More...
 
unsigned elemental_dimension () const
 Return number of elemental dimension in mesh. More...
 
unsigned nodal_dimension () const
 Return number of nodal dimension in mesh. More...
 
void add_node_pt (Node *const &node_pt)
 Add a (pointer to a) node to the mesh. More...
 
void add_element_pt (GeneralisedElement *const &element_pt)
 Add a (pointer to) an element to the mesh. More...
 
virtual void node_update (const bool &update_all_solid_nodes=false)
 
virtual void reorder_nodes (const bool &use_old_ordering=true)
 
virtual void get_node_reordering (Vector< Node * > &reordering, const bool &use_old_ordering=true) const
 
template<class BULK_ELEMENT , template< class > class FACE_ELEMENT>
void build_face_mesh (const unsigned &b, Mesh *const &face_mesh_pt)
 
unsigned self_test ()
 Self-test: Check elements and nodes. Return 0 for OK. More...
 
void max_and_min_element_size (double &max_size, double &min_size)
 
double total_size ()
 
void check_inverted_elements (bool &mesh_has_inverted_elements, std::ofstream &inverted_element_file)
 
void check_inverted_elements (bool &mesh_has_inverted_elements)
 
unsigned check_for_repeated_nodes (const double &epsilon=1.0e-12)
 
Vector< Node * > prune_dead_nodes ()
 
unsigned nboundary () const
 Return number of boundaries. More...
 
unsigned long nboundary_node (const unsigned &ibound) const
 Return number of nodes on a particular boundary. More...
 
FiniteElementboundary_element_pt (const unsigned &b, const unsigned &e) const
 Return pointer to e-th finite element on boundary b. More...
 
Nodeget_some_non_boundary_node () const
 
unsigned nboundary_element (const unsigned &b) const
 Return number of finite elements that are adjacent to boundary b. More...
 
int face_index_at_boundary (const unsigned &b, const unsigned &e) const
 
virtual void dump (std::ofstream &dump_file, const bool &use_old_ordering=true) const
 Dump the data in the mesh into a file for restart. More...
 
void dump (const std::string &dump_file_name, const bool &use_old_ordering=true) const
 Dump the data in the mesh into a file for restart. More...
 
virtual void read (std::ifstream &restart_file)
 Read solution from restart file. More...
 
void output_paraview (std::ofstream &file_out, const unsigned &nplot) const
 
void output_fct_paraview (std::ofstream &file_out, const unsigned &nplot, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt) const
 
void output_fct_paraview (std::ofstream &file_out, const unsigned &nplot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt) const
 
void output (std::ostream &outfile)
 Output for all elements. More...
 
void output (std::ostream &outfile, const unsigned &n_plot)
 Output at f(n_plot) points in each element. More...
 
void output (FILE *file_pt)
 Output for all elements (C-style output) More...
 
void output (FILE *file_pt, const unsigned &nplot)
 Output at f(n_plot) points in each element (C-style output) More...
 
void output (const std::string &output_filename)
 Output for all elements. More...
 
void output (const std::string &output_filename, const unsigned &n_plot)
 Output at f(n_plot) points in each element. More...
 
void output_fct (std::ostream &outfile, const unsigned &n_plot, FiniteElement::SteadyExactSolutionFctPt)
 Output a given Vector function at f(n_plot) points in each element. More...
 
void output_fct (std::ostream &outfile, const unsigned &n_plot, const double &time, FiniteElement::UnsteadyExactSolutionFctPt)
 
void output_boundaries (std::ostream &outfile)
 Output the nodes on the boundaries (into separate tecplot zones) More...
 
void output_boundaries (const std::string &output_filename)
 
void assign_initial_values_impulsive ()
 Assign initial values for an impulsive start. More...
 
void shift_time_values ()
 
void calculate_predictions ()
 
void set_nodal_and_elemental_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 
virtual void set_mesh_level_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 
void set_consistent_pinned_values_for_continuation (ContinuationStorageScheme *const &continuation_stepper_pt)
 Set consistent values for pinned data in continuation. More...
 
bool does_pointer_correspond_to_mesh_data (double *const &parameter_pt)
 Does the double pointer correspond to any mesh data. More...
 
void set_nodal_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 Set the timestepper associated with the nodal data in the mesh. More...
 
void set_elemental_internal_time_stepper (TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
 
virtual void compute_norm (double &norm)
 
virtual void compute_norm (Vector< double > &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
 
virtual void compute_error (FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, double &error, double &norm)
 
virtual void compute_error (FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
 
virtual void compute_error (std::ostream &outfile, FiniteElement::SteadyExactSolutionFctPt exact_soln_pt, Vector< double > &error, Vector< double > &norm)
 
virtual void compute_error (FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, double &error, double &norm)
 Returns the norm of the error and that of the exact solution. More...
 
virtual void compute_error (FiniteElement::UnsteadyExactSolutionFctPt exact_soln_pt, const double &time, Vector< double > &error, Vector< double > &norm)
 
bool is_mesh_distributed () const
 Boolean to indicate if Mesh has been distributed. More...
 
OomphCommunicatorcommunicator_pt () const
 
void delete_all_external_storage ()
 Wipe the storage for all externally-based elements. More...
 

Private Attributes

Vector< Vector< unsigned > > Boundary_id
 

Additional Inherited Members

- Public Types inherited from oomph::Mesh
typedef void(FiniteElement::* SteadyExactSolutionFctPt) (const Vector< double > &x, Vector< double > &soln)
 
typedef void(FiniteElement::* UnsteadyExactSolutionFctPt) (const double &time, const Vector< double > &x, Vector< double > &soln)
 
- Static Public Attributes inherited from oomph::TetMeshBase
static double Tolerance_for_boundary_finding = 1.0e-5
 
- Static Public Attributes inherited from oomph::Mesh
static Steady< 0 > Default_TimeStepper
 The Steady Timestepper. More...
 
static bool Suppress_warning_about_empty_mesh_level_time_stepper_function
 Static boolean flag to control warning about mesh level timesteppers. More...
 
- Protected Member Functions inherited from oomph::Mesh
unsigned long assign_global_eqn_numbers (Vector< double * > &Dof_pt)
 Assign (global) equation numbers to the nodes. More...
 
void describe_dofs (std::ostream &out, const std::string &current_string) const
 
void describe_local_dofs (std::ostream &out, const std::string &current_string) const
 
void assign_local_eqn_numbers (const bool &store_local_dof_pt)
 Assign local equation numbers in all elements. More...
 
void convert_to_boundary_node (Node *&node_pt, const Vector< FiniteElement * > &finite_element_pt)
 
void convert_to_boundary_node (Node *&node_pt)
 
- Protected Attributes inherited from oomph::TetMeshBase
Vector< Vector< FiniteElement * > > Region_element_pt
 
Vector< doubleRegion_attribute
 
Vector< std::map< unsigned, Vector< FiniteElement * > > > Boundary_region_element_pt
 Storage for elements adjacent to a boundary in a particular region. More...
 
Vector< std::map< unsigned, Vector< int > > > Face_index_region_at_boundary
 
TetMeshFacetedClosedSurfaceOuter_boundary_pt
 Faceted surface that defines outer boundaries. More...
 
Vector< TetMeshFacetedSurface * > Internal_surface_pt
 Vector to faceted surfaces that define internal boundaries. More...
 
std::map< unsigned, TetMeshFacetedSurface * > Tet_mesh_faceted_surface_pt
 
std::map< unsigned, TetMeshFacet * > Tet_mesh_facet_pt
 
std::map< unsigned, Vector< Vector< double > > > Triangular_facet_vertex_boundary_coordinate
 
TimeStepperTime_stepper_pt
 Timestepper used to build nodes. More...
 
- Protected Attributes inherited from oomph::Mesh
Vector< Vector< Node * > > Boundary_node_pt
 
bool Lookup_for_elements_next_boundary_is_setup
 
Vector< Vector< FiniteElement * > > Boundary_element_pt
 
Vector< Vector< int > > Face_index_at_boundary
 
Vector< Node * > Node_pt
 Vector of pointers to nodes. More...
 
Vector< GeneralisedElement * > Element_pt
 Vector of pointers to generalised elements. More...
 
std::vector< boolBoundary_coordinate_exists
 

Detailed Description

template<class ELEMENT>
class oomph::XdaTetMesh< ELEMENT >

Tet mesh made of quadratic (ten node) tets built from xda input file.

Constructor & Destructor Documentation

◆ XdaTetMesh()

template<class ELEMENT >
oomph::XdaTetMesh< ELEMENT >::XdaTetMesh ( const std::string  xda_file_name,
TimeStepper time_stepper_pt = &Mesh::Default_TimeStepper 
)

Constructor: Pass name of xda file. Note that all boundary elements get their own ID – this is required for FSI problems. In this case; the vector containing the oomph-lib boundary IDs of all oomph-lib boundaries that collectively form a given boundary as specified in the xda input file can be obtained from the access function oomph_lib_boundary_ids(...). Timestepper defaults to steady pseudo-timestepper.

Constructor: Pass name of xda file. Note that all boundary elements get their own ID – this is required for FSI problems. The vector containing the oomph-lib boundary IDs of all oomph-lib boundaries that collectively form a given boundary as specified in the xda input file can be obtained from the access function oomph_lib_boundary_ids(...). Timestepper defaults to steady pseudo-timestepper.

48  {
49  // Mesh can only be built with 3D Telements.
50  MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
51 
52  // Open and process xda input file
53  std::ifstream infile(xda_file_name.c_str(), std::ios_base::in);
54  unsigned n_node;
55  unsigned n_element;
56  unsigned n_bound_face;
57 
58  if (!infile.is_open())
59  {
60  std::ostringstream error_stream;
61  error_stream << "Failed to open " << xda_file_name << "\n";
62  throw OomphLibError(
64  }
65 
66  // Dummy storage to jump lines
67  char dummy[101];
68 
69  // Ignore file format
70  infile.getline(dummy, 100);
71 
72  // Get number of elements
73  infile >> n_element;
74 
75  // Ignore rest of line
76  infile.getline(dummy, 100);
77 
78  // Get number of nodes
79  infile >> n_node;
80 
81  // Ignore rest of line
82  infile.getline(dummy, 100);
83 
84  // Ignore sum of element weights (whatever that is...)
85  infile.getline(dummy, 100);
86 
87  // Get number of enumerated boundary faces on which boundary conditions
88  // are applied.
89  infile >> n_bound_face;
90 
91  // Keep reading until "Title String"
92  while (dummy[0] != 'T')
93  {
94  infile.getline(dummy, 100);
95  }
96 
97  // Make space for nodes and elements
98  Node_pt.resize(n_node);
99  Element_pt.resize(n_element);
100 
101  // Read first line with node labels and count them
103  std::getline(infile, line);
104  std::istringstream ostr(line);
105  std::istream_iterator<std::string> it(ostr);
106  std::istream_iterator<std::string> end;
107  unsigned nnod_el = 0;
108  Vector<unsigned> first_node;
109  while (it != end)
110  {
111  first_node.push_back(atoi((*it).c_str()));
112  it++;
113  nnod_el++;
114  }
115 
116  // Check
117  if (nnod_el != 10)
118  {
119  std::ostringstream error_stream;
120  error_stream
121  << "XdaTetMesh can currently only be built with quadratic tets "
122  << "with 10 nodes. The specified mesh file has " << nnod_el
123  << "nodes per element.\n";
124  throw OomphLibError(
125  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
126  }
127 
128  // Storage for the global node numbers listed element-by-element
129  Vector<unsigned> global_node(n_element * nnod_el);
130 
131  // Read in nodes
132  unsigned k = 0;
133 
134  // Copy across first nodes
135  for (unsigned j = 0; j < nnod_el; j++)
136  {
137  global_node[k] = first_node[k];
138  k++;
139  }
140 
141  // Read the other ones
142  for (unsigned i = 1; i < n_element; i++)
143  {
144  for (unsigned j = 0; j < nnod_el; j++)
145  {
146  infile >> global_node[k];
147  k++;
148  }
149  infile.getline(dummy, 100);
150  }
151 
152 
153  // Create storage for coordinates
154  Vector<double> x_node(n_node);
155  Vector<double> y_node(n_node);
156  Vector<double> z_node(n_node);
157 
158  // Get nodal coordinates
159  for (unsigned i = 0; i < n_node; i++)
160  {
161  infile >> x_node[i];
162  infile >> y_node[i];
163  infile >> z_node[i];
164  }
165 
166 
167  // Read in boundaries for faces
168  unsigned element_nmbr;
169  unsigned bound_id;
170  unsigned side_nmbr;
171  unsigned max_bound = 0;
172 
173  // Make space for enumeration of sub-boundaries
174  Boundary_id.resize(n_bound_face + 1);
175 
176  // Counter for number of separate boundary faces
177  unsigned count = 0;
178  Vector<std::set<unsigned>> boundary_id(n_node);
179  for (unsigned i = 0; i < n_bound_face; i++)
180  {
181  // Number of the element
182  infile >> element_nmbr;
183 
184  // Which side/face on the tet are we dealing with (xda enumeratation)?
185  infile >> side_nmbr;
186 
187  // What's the boundary ID?
188  infile >> bound_id;
189 
190  // Turn into zero-based oomph-lib mesh boundary id
191  unsigned oomph_lib_bound_id = bound_id - 1;
192  oomph_lib_bound_id = count;
193  Boundary_id[bound_id].push_back(count);
194 
195  // Increment number of separate boundary faces
196  count++;
197 
198  // Get ready for allocation of total number of boundaries
199  if (oomph_lib_bound_id > max_bound) max_bound = oomph_lib_bound_id;
200 
201  // Identify the "side nodes" (i.e. the nodes on the faces of
202  // the bulk tet) according to the
203  // conventions in '.xda' mesh files so that orientation of the
204  // faces is always the same (required for computation of
205  // outer unit normals
206  Vector<unsigned> side_node(6);
207  switch (side_nmbr)
208  {
209  case 0:
210  side_node[0] = global_node[nnod_el * element_nmbr + 1];
211  side_node[1] = global_node[nnod_el * element_nmbr];
212  side_node[2] = global_node[nnod_el * element_nmbr + 2];
213  side_node[3] = global_node[nnod_el * element_nmbr + 4];
214  side_node[4] = global_node[nnod_el * element_nmbr + 6];
215  side_node[5] = global_node[nnod_el * element_nmbr + 5];
216  break;
217 
218  case 1:
219  side_node[0] = global_node[nnod_el * element_nmbr];
220  side_node[1] = global_node[nnod_el * element_nmbr + 1];
221  side_node[2] = global_node[nnod_el * element_nmbr + 3];
222  side_node[3] = global_node[nnod_el * element_nmbr + 4];
223  side_node[4] = global_node[nnod_el * element_nmbr + 8];
224  side_node[5] = global_node[nnod_el * element_nmbr + 7];
225  break;
226 
227  case 2:
228  side_node[0] = global_node[nnod_el * element_nmbr + 1];
229  side_node[1] = global_node[nnod_el * element_nmbr + 2];
230  side_node[2] = global_node[nnod_el * element_nmbr + 3];
231  side_node[3] = global_node[nnod_el * element_nmbr + 5];
232  side_node[4] = global_node[nnod_el * element_nmbr + 9];
233  side_node[5] = global_node[nnod_el * element_nmbr + 8];
234  break;
235 
236  case 3:
237  side_node[0] = global_node[nnod_el * element_nmbr + 2];
238  side_node[1] = global_node[nnod_el * element_nmbr];
239  side_node[2] = global_node[nnod_el * element_nmbr + 3];
240  side_node[3] = global_node[nnod_el * element_nmbr + 6];
241  side_node[4] = global_node[nnod_el * element_nmbr + 7];
242  side_node[5] = global_node[nnod_el * element_nmbr + 9];
243  break;
244 
245  default:
246  throw OomphLibError(
247  "Unexcpected side number in your '.xda' input file\n",
250  }
251 
252  // Associate boundaries with nodes
253  for (unsigned j = 0; j < 6; j++)
254  {
255  boundary_id[side_node[j]].insert(oomph_lib_bound_id);
256  }
257  }
258 
259  // Set number of boundaries
260  set_nboundary(max_bound + 1);
261 
262  // Vector of bools, will tell us if we already visited a node
263  std::vector<bool> done(n_node, false);
264 
265  Vector<unsigned> translate(n_node);
266  translate[0] = 0;
267  translate[1] = 2;
268  translate[2] = 1;
269  translate[3] = 3;
270  translate[4] = 5;
271  translate[5] = 7;
272  translate[6] = 4;
273  translate[7] = 6;
274  translate[8] = 8;
275  translate[9] = 9;
276 
277  // Create the elements
278  unsigned node_count = 0;
279  for (unsigned e = 0; e < n_element; e++)
280  {
281  Element_pt[e] = new ELEMENT;
282 
283  // Loop over all nodes
284  for (unsigned j = 0; j < nnod_el; j++)
285  {
286  unsigned j_global = global_node[node_count];
287  if (done[j_global] == false)
288  {
289  if (boundary_id[j_global].size() == 0)
290  {
292  translate[j], time_stepper_pt);
293  }
294  else
295  {
297  translate[j], time_stepper_pt);
298  for (std::set<unsigned>::iterator it =
299  boundary_id[j_global].begin();
300  it != boundary_id[j_global].end();
301  it++)
302  {
303  add_boundary_node(*it, Node_pt[j_global]);
304  }
305  }
306  done[j_global] = true;
307  Node_pt[j_global]->x(0) = x_node[j_global];
308  Node_pt[j_global]->x(1) = y_node[j_global];
309  Node_pt[j_global]->x(2) = z_node[j_global];
310  }
311  else
312  {
313  finite_element_pt(e)->node_pt(translate[j]) = Node_pt[j_global];
314  }
315  node_count++;
316  }
317  }
318 
319  // Figure out which elements are next to the boundaries.
321 
322 
323  // Setup boundary coordinates
324  unsigned nb = nboundary();
325  for (unsigned b = 0; b < nb; b++)
326  {
327  bool switch_normal = false;
328  setup_boundary_coordinates(b, switch_normal);
329  }
330  }
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
Scalar * b
Definition: benchVecAdd.cpp:17
virtual Node * construct_node(const unsigned &n)
Definition: elements.h:2509
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
virtual Node * construct_boundary_node(const unsigned &n)
Definition: elements.h:2538
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
Definition: mesh.cc:243
Vector< Node * > Node_pt
Vector of pointers to nodes.
Definition: mesh.h:183
FiniteElement * finite_element_pt(const unsigned &e) const
Definition: mesh.h:473
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
Definition: mesh.h:505
unsigned nboundary() const
Return number of boundaries.
Definition: mesh.h:827
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
Definition: mesh.h:186
void setup_boundary_element_info()
Definition: tet_mesh.h:1007
Vector< Vector< unsigned > > Boundary_id
Definition: xda_tet_mesh.template.h:113
void setup_boundary_coordinates(const unsigned &b, const bool &switch_normal)
Definition: xda_tet_mesh.template.h:75
static constexpr lastp1_t end
Definition: IndexedViewHelper.h:79
int nb
Definition: level2_impl.h:286
char char char int int * k
Definition: level2_impl.h:374
line
Definition: calibrate.py:103
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References b, e(), Eigen::placeholders::end, i, j, k, calibrate::line, nb, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, size, and oomph::Global_string_for_annotation::string().

Member Function Documentation

◆ nxda_boundary()

template<class ELEMENT >
unsigned oomph::XdaTetMesh< ELEMENT >::nxda_boundary ( )
inline

Access function to the number of distinct boundaries specified in the original xda enumeration.

99  {
100  return Boundary_id.size();
101  }

References oomph::XdaTetMesh< ELEMENT >::Boundary_id.

◆ oomph_lib_boundary_ids()

template<class ELEMENT >
Vector<unsigned> oomph::XdaTetMesh< ELEMENT >::oomph_lib_boundary_ids ( const unsigned xda_boundary_id)
inline

Access functions to the Vector of oomph-lib boundary ids that make up boundary b in the original xda enumeration

106  {
107  return Boundary_id[xda_boundary_id];
108  }

References oomph::XdaTetMesh< ELEMENT >::Boundary_id.

◆ setup_boundary_coordinates() [1/2]

template<class ELEMENT >
void oomph::XdaTetMesh< ELEMENT >::setup_boundary_coordinates ( const unsigned b,
const bool switch_normal 
)
inline

Setup boundary coordinate on boundary b while is temporarily flattened to simplex faces. Boundary coordinates are the x-y coordinates in the plane of that boundary with the x-axis along the line from the (lexicographically) "lower left" to the "upper right" node. The y axis is obtained by taking the cross-product of the positive x direction with the outer unit normal computed by the face elements (or its negative if switch_normal is set to true).

77  {
78  std::ofstream outfile;
79  setup_boundary_coordinates(b, switch_normal, outfile);
80  }

References b.

◆ setup_boundary_coordinates() [2/2]

template<class ELEMENT >
void oomph::XdaTetMesh< ELEMENT >::setup_boundary_coordinates ( const unsigned b,
const bool switch_normal,
std::ofstream &  outfile 
)

Setup boundary coordinate on boundary b while is temporarily flattened to simplex faces. Boundary coordinates are the x-y coordinates in the plane of that boundary with the x-axis along the line from the (lexicographically) "lower left" to the "upper right" node. The y axis is obtained by taking the cross-product of the positive x direction with the outer unit normal computed by the face elements (or its negative if switch_normal is set to true). Doc faces in output file.

347  {
348  // Temporary storage for face elements
349  Vector<FiniteElement*> face_el_pt;
350 
351  // Backup for nodal positions
352  std::map<Node*, Vector<double>> backup_position;
353 
354  // Loop over all elements on boundaries
355  unsigned nel = this->nboundary_element(b);
356  if (nel > 0)
357  {
358  // Loop over the bulk elements adjacent to boundary b
359  for (unsigned e = 0; e < nel; e++)
360  {
361  // Get pointer to the bulk element that is adjacent to boundary b
362  FiniteElement* bulk_elem_pt = this->boundary_element_pt(b, e);
363 
364  // Find the index of the face of element e along boundary b
365  int face_index = this->face_index_at_boundary(b, e);
366 
367  // Create new face element
368  DummyFaceElement<ELEMENT>* el_pt =
369  new DummyFaceElement<ELEMENT>(bulk_elem_pt, face_index);
370  face_el_pt.push_back(el_pt);
371 
372  // Backup nodal position
373  Vector<double> pos(3);
374  for (unsigned j = 3; j < 6; j++)
375  {
376  if (backup_position[el_pt->node_pt(j)].size() == 0)
377  {
378  el_pt->node_pt(j)->position(pos);
379  backup_position[el_pt->node_pt(j)] = pos;
380  }
381  }
382 
383  // Temporarily flatten the element to a simplex
384  for (unsigned i = 0; i < 3; i++)
385  {
386  // Node 3 is between vertex nodes 0 and 1
387  el_pt->node_pt(3)->x(i) =
388  0.5 * (el_pt->node_pt(0)->x(i) + el_pt->node_pt(1)->x(i));
389 
390  // Node 4 is between vertex nodes 1 and 2
391  el_pt->node_pt(4)->x(i) =
392  0.5 * (el_pt->node_pt(1)->x(i) + el_pt->node_pt(2)->x(i));
393 
394  // Node 5 is between vertex nodes 2 and 0
395  el_pt->node_pt(5)->x(i) =
396  0.5 * (el_pt->node_pt(2)->x(i) + el_pt->node_pt(0)->x(i));
397  }
398 
399 
400  // Output faces?
401  if (outfile.is_open())
402  {
403  face_el_pt[face_el_pt.size() - 1]->output(outfile);
404  }
405  }
406 
407 
408  // Loop over all nodes to find the lower left and upper right ones
409  Node* lower_left_node_pt = this->boundary_node_pt(b, 0);
410  Node* upper_right_node_pt = this->boundary_node_pt(b, 0);
411 
412  // Loop over all nodes on the boundary
413  unsigned nnod = this->nboundary_node(b);
414  for (unsigned j = 0; j < nnod; j++)
415  {
416  // Get node
417  Node* nod_pt = this->boundary_node_pt(b, j);
418 
419  // Primary criterion for lower left: Does it have a lower z-coordinate?
420  if (nod_pt->x(2) < lower_left_node_pt->x(2))
421  {
422  lower_left_node_pt = nod_pt;
423  }
424  // ...or is it a draw?
425  else if (nod_pt->x(2) == lower_left_node_pt->x(2))
426  {
427  // If it's a draw: Does it have a lower y-coordinate?
428  if (nod_pt->x(1) < lower_left_node_pt->x(1))
429  {
430  lower_left_node_pt = nod_pt;
431  }
432  // ...or is it a draw?
433  else if (nod_pt->x(1) == lower_left_node_pt->x(1))
434  {
435  // If it's a draw: Does it have a lower x-coordinate?
436  if (nod_pt->x(0) < lower_left_node_pt->x(0))
437  {
438  lower_left_node_pt = nod_pt;
439  }
440  }
441  }
442 
443  // Primary criterion for upper right: Does it have a higher
444  // z-coordinate?
445  if (nod_pt->x(2) > upper_right_node_pt->x(2))
446  {
447  upper_right_node_pt = nod_pt;
448  }
449  // ...or is it a draw?
450  else if (nod_pt->x(2) == upper_right_node_pt->x(2))
451  {
452  // If it's a draw: Does it have a higher y-coordinate?
453  if (nod_pt->x(1) > upper_right_node_pt->x(1))
454  {
455  upper_right_node_pt = nod_pt;
456  }
457  // ...or is it a draw?
458  else if (nod_pt->x(1) == upper_right_node_pt->x(1))
459  {
460  // If it's a draw: Does it have a higher x-coordinate?
461  if (nod_pt->x(0) > upper_right_node_pt->x(0))
462  {
463  upper_right_node_pt = nod_pt;
464  }
465  }
466  }
467  }
468 
469  // Prepare storage for boundary coordinates
470  Vector<double> zeta(2);
471 
472  // Unit vector connecting lower left and upper right nodes
473  Vector<double> b0(3);
474  b0[0] = upper_right_node_pt->x(0) - lower_left_node_pt->x(0);
475  b0[1] = upper_right_node_pt->x(1) - lower_left_node_pt->x(1);
476  b0[2] = upper_right_node_pt->x(2) - lower_left_node_pt->x(2);
477 
478  // Normalise
479  double inv_length =
480  1.0 / sqrt(b0[0] * b0[0] + b0[1] * b0[1] + b0[2] * b0[2]);
481  b0[0] *= inv_length;
482  b0[1] *= inv_length;
483  b0[2] *= inv_length;
484 
485  // Get (outer) unit normal to first face element
486  Vector<double> normal(3);
487  Vector<double> s(2, 0.0);
488  dynamic_cast<DummyFaceElement<ELEMENT>*>(face_el_pt[0])
489  ->outer_unit_normal(s, normal);
490 
491  if (switch_normal)
492  {
493  normal[0] = -normal[0];
494  normal[1] = -normal[1];
495  normal[2] = -normal[2];
496  }
497 
498 #ifdef PARANOID
499 
500  // Check that all elements have the same normal
501  for (unsigned e = 0; e < nel; e++)
502  {
503  // Get (outer) unit normal to face element
504  Vector<double> my_normal(3);
505  dynamic_cast<DummyFaceElement<ELEMENT>*>(face_el_pt[0])
506  ->outer_unit_normal(s, my_normal);
507 
508  // Dot product should be one!
509  double error = normal[0] * my_normal[0] + normal[1] * my_normal[1] +
510  normal[2] * my_normal[2];
511 
512  error -= 1.0;
513  if (switch_normal) error += 1.0;
514 
516  {
517  std::ostringstream error_message;
518  error_message
519  << "Error in alingment of normals (dot product-1) " << error
520  << " for element " << e << std::endl
521  << "exceeds tolerance specified by the static member data\n"
522  << "TetMeshBase::Tolerance_for_boundary_finding = "
523  << Tolerance_for_boundary_finding << std::endl
524  << "This usually means that the boundary is not planar.\n\n"
525  << "You can suppress this error message by recompiling \n"
526  << "recompiling without PARANOID or by changing the tolerance.\n";
527  throw OomphLibError(error_message.str(),
530  }
531  }
532 #endif
533 
534  // Cross-product to get second in-plane vector, normal to b0
535  Vector<double> b1(3);
536  b1[0] = b0[1] * normal[2] - b0[2] * normal[1];
537  b1[1] = b0[2] * normal[0] - b0[0] * normal[2];
538  b1[2] = b0[0] * normal[1] - b0[1] * normal[0];
539 
540  // Assign boundary coordinates: projection onto the axes
541  for (unsigned j = 0; j < nnod; j++)
542  {
543  // Get node
544  Node* nod_pt = this->boundary_node_pt(b, j);
545 
546  // Difference vector to lower left corner
547  Vector<double> delta(3);
548  delta[0] = nod_pt->x(0) - lower_left_node_pt->x(0);
549  delta[1] = nod_pt->x(1) - lower_left_node_pt->x(1);
550  delta[2] = nod_pt->x(2) - lower_left_node_pt->x(2);
551 
552  // Project
553  zeta[0] = delta[0] * b0[0] + delta[1] * b0[1] + delta[2] * b0[2];
554  zeta[1] = delta[0] * b1[0] + delta[1] * b1[1] + delta[2] * b1[2];
555 
556 #ifdef PARANOID
557 
558  // Check:
559  double error = pow(lower_left_node_pt->x(0) + zeta[0] * b0[0] +
560  zeta[1] * b1[0] - nod_pt->x(0),
561  2) +
562  pow(lower_left_node_pt->x(1) + zeta[0] * b0[1] +
563  zeta[1] * b1[1] - nod_pt->x(1),
564  2) +
565  pow(lower_left_node_pt->x(2) + zeta[0] * b0[2] +
566  zeta[1] * b1[2] - nod_pt->x(2),
567  2);
568 
570  {
571  std::ostringstream error_message;
572  error_message
573  << "Error in setup of boundary coordinate " << sqrt(error)
574  << std::endl
575  << "exceeds tolerance specified by the static member data\n"
576  << "TetMeshBase::Tolerance_for_boundary_finding = "
577  << Tolerance_for_boundary_finding << std::endl
578  << "This usually means that the boundary is not planar.\n\n"
579  << "You can suppress this error message by recompiling \n"
580  << "recompiling without PARANOID or by changing the tolerance.\n";
581  throw OomphLibError(error_message.str(),
584  }
585 #endif
586 
587  // Set boundary coordinate
588  nod_pt->set_coordinates_on_boundary(b, zeta);
589  }
590  }
591 
592  // Indicate that boundary coordinate has been set up
594 
595  // Cleanup
596  unsigned n = face_el_pt.size();
597  for (unsigned e = 0; e < n; e++)
598  {
599  delete face_el_pt[e];
600  }
601 
602 
603  // Reset nodal position
604  for (std::map<Node*, Vector<double>>::iterator it = backup_position.begin();
605  it != backup_position.end();
606  it++)
607  {
608  Node* nod_pt = (*it).first;
609  Vector<double> pos((*it).second);
610  for (unsigned i = 0; i < 3; i++)
611  {
612  nod_pt->x(i) = pos[i];
613  }
614  }
615  }
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
Definition: mesh.h:833
std::vector< bool > Boundary_coordinate_exists
Definition: mesh.h:190
int face_index_at_boundary(const unsigned &b, const unsigned &e) const
Definition: mesh.h:896
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
Definition: mesh.h:878
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
Definition: mesh.h:840
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
Definition: mesh.h:493
static double Tolerance_for_boundary_finding
Definition: tet_mesh.h:677
RealScalar s
Definition: level1_cplx_impl.h:130
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
EIGEN_STRONG_INLINE const Eigen::CwiseBinaryOp< Eigen::internal::scalar_zeta_op< typename DerivedX::Scalar >, const DerivedX, const DerivedQ > zeta(const Eigen::ArrayBase< DerivedX > &x, const Eigen::ArrayBase< DerivedQ > &q)
Definition: SpecialFunctionsArrayAPI.h:152
int delta
Definition: MultiOpt.py:96
void normal(const Vector< double > &x, Vector< double > &normal)
Definition: free_surface_rotation.cc:65
int error
Definition: calibrate.py:297

References b, MultiOpt::delta, e(), calibrate::error, i, j, n, oomph::FiniteElement::node_pt(), WallFunction::normal(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::Node::position(), Eigen::bfloat16_impl::pow(), s, oomph::Node::set_coordinates_on_boundary(), sqrt(), oomph::Node::x(), and Eigen::zeta().

Member Data Documentation

◆ Boundary_id

template<class ELEMENT >
Vector<Vector<unsigned> > oomph::XdaTetMesh< ELEMENT >::Boundary_id
private

Vector of vectors containing the boundary IDs of the overall boundary specified in the xda file.

Referenced by oomph::XdaTetMesh< ELEMENT >::nxda_boundary(), and oomph::XdaTetMesh< ELEMENT >::oomph_lib_boundary_ids().


The documentation for this class was generated from the following files: