libMesh::InfElemBuilder Class Reference

#include <inf_elem_builder.h>

Public Types

typedef std::pair< bool, double > InfElemOriginValue
 

Public Member Functions

 InfElemBuilder (MeshBase &mesh)
 
const Point build_inf_elem (const bool be_verbose=false)
 
const Point build_inf_elem (const InfElemOriginValue &origin_x, const InfElemOriginValue &origin_y, const InfElemOriginValue &origin_z, const bool x_sym=false, const bool y_sym=false, const bool z_sym=false, const bool be_verbose=false, std::vector< const Node * > *inner_boundary_nodes=libmesh_nullptr)
 

Private Member Functions

void build_inf_elem (const Point &origin, const bool x_sym=false, const bool y_sym=false, const bool z_sym=false, const bool be_verbose=false, std::set< std::pair< dof_id_type, unsigned int > > *inner_faces=libmesh_nullptr)
 

Private Attributes

MeshBase_mesh
 

Detailed Description

This class is used to build infinite elements on top of an existing mesh. It only makes sense to use this if LIBMESH_ENABLE_INFINITE_ELEMENTS is true.

Author
Daniel Dreyer
John W. Peterson
Date
2004

Definition at line 53 of file inf_elem_builder.h.

Member Typedef Documentation

typedef std::pair<bool, double> libMesh::InfElemBuilder::InfElemOriginValue

Useful typedef

Definition at line 65 of file inf_elem_builder.h.

Constructor & Destructor Documentation

libMesh::InfElemBuilder::InfElemBuilder ( MeshBase mesh)
inlineexplicit

Constructor.

Definition at line 60 of file inf_elem_builder.h.

60 : _mesh(mesh) {}
MeshBase & mesh

Member Function Documentation

const Point libMesh::InfElemBuilder::build_inf_elem ( const bool  be_verbose = false)

Build infinite elements atop a volume-based mesh, determine origin automatically. Also returns the origin as a const Point to make it more obvious that the origin should not change after the infinite elements have been built. When symmetry planes are present, use the version with optional symmetry switches. The flag be_verbose enables some diagnostic output.

Definition at line 40 of file inf_elem_builder.C.

References _mesh, libMesh::MeshTools::bounding_box(), libMesh::out, libMesh::MeshBase::prepare_for_use(), libMesh::ParallelObject::processor_id(), and libMesh::TypeVector< T >::write_unformatted().

Referenced by build_inf_elem().

41 {
42  // determine origin automatically,
43  // works only if the mesh has no symmetry planes.
44  const MeshTools::BoundingBox b_box = MeshTools::bounding_box(_mesh);
45  Point origin = (b_box.first + b_box.second) / 2;
46 
47  if (be_verbose && _mesh.processor_id() == 0)
48  {
49 #ifdef DEBUG
50  libMesh::out << " Determined origin for Infinite Elements:"
51  << std::endl
52  << " ";
53  origin.write_unformatted(libMesh::out);
54  libMesh::out << std::endl;
55 #endif
56  }
57 
58  // Call the protected implementation function with the
59  // automatically determined origin.
60  this->build_inf_elem(origin, false, false, false, be_verbose);
61 
62  // when finished with building the Ifems,
63  // it remains to prepare the mesh for use:
64  // find neighbors (again), partition (if needed)...
65  this->_mesh.prepare_for_use (/*skip_renumber =*/ false);
66 
67  return origin;
68 }
BoundingBox bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:358
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Definition: mesh_base.C:174
const Point build_inf_elem(const bool be_verbose=false)
OStreamProxy out(std::cout)
processor_id_type processor_id() const
const Point libMesh::InfElemBuilder::build_inf_elem ( const InfElemOriginValue origin_x,
const InfElemOriginValue origin_y,
const InfElemOriginValue origin_z,
const bool  x_sym = false,
const bool  y_sym = false,
const bool  z_sym = false,
const bool  be_verbose = false,
std::vector< const Node * > *  inner_boundary_nodes = libmesh_nullptr 
)
Returns
the origin of the infinite elements. Builds infinite elements atop a volume-based mesh. Finds all faces on the outer boundary and build infinite elements on them. Using the InfElemOriginValue the user can prescribe only selected origin coordinates. The remaining coordinates are computed from the center of the bounding box of the mesh.

During the search for faces on which infinite elements are built, interior faces that are not on symmetry planes are found, too. When an (optional) pointer to inner_boundary_nodes is provided, then this vector will be filled with the nodes that lie on the inner boundary.

Faces which lie in at least one symmetry plane are skipped. The three optional booleans x_sym, y_sym, z_sym indicate symmetry planes (through the origin, obviously) perpendicular to the x, y and z direction, respectively. The flag be_verbose enables some diagnostic output.

Definition at line 81 of file inf_elem_builder.C.

References _mesh, libMesh::MeshTools::bounding_box(), build_inf_elem(), libMesh::Elem::build_side_ptr(), libMesh::MeshBase::elem_ref(), libmesh_nullptr, libMesh::MeshBase::node_ptr(), libMesh::out, libMesh::MeshBase::prepare_for_use(), libMesh::MeshBase::print_info(), side, and libMesh::TypeVector< T >::write_unformatted().

89 {
90  START_LOG("build_inf_elem()", "InfElemBuilder");
91 
92  // first determine the origin of the
93  // infinite elements. For this, the
94  // origin defaults to the given values,
95  // and may be overridden when the user
96  // provided values
97  Point origin(origin_x.second, origin_y.second, origin_z.second);
98 
99  // when only _one_ of the origin coordinates is _not_
100  // given, we have to determine it on our own
101  if ( !origin_x.first || !origin_y.first || !origin_z.first)
102  {
103  // determine origin
104  const MeshTools::BoundingBox b_box = MeshTools::bounding_box(_mesh);
105  const Point auto_origin = (b_box.first+b_box.second)/2;
106 
107  // override default values, if necessary
108  if (!origin_x.first)
109  origin(0) = auto_origin(0);
110  if (!origin_y.first)
111  origin(1) = auto_origin(1);
112  if (!origin_z.first)
113  origin(2) = auto_origin(2);
114 
115  if (be_verbose)
116  {
117  libMesh::out << " Origin for Infinite Elements:" << std::endl;
118 
119  if (!origin_x.first)
120  libMesh::out << " determined x-coordinate" << std::endl;
121  if (!origin_y.first)
122  libMesh::out << " determined y-coordinate" << std::endl;
123  if (!origin_z.first)
124  libMesh::out << " determined z-coordinate" << std::endl;
125 
126  libMesh::out << " coordinates: ";
127  origin.write_unformatted(libMesh::out);
128  libMesh::out << std::endl;
129  }
130  }
131 
132  else if (be_verbose)
133 
134  {
135  libMesh::out << " Origin for Infinite Elements:" << std::endl;
136  libMesh::out << " coordinates: ";
137  origin.write_unformatted(libMesh::out);
138  libMesh::out << std::endl;
139  }
140 
141 
142 
143  // Now that we have the origin, check if the user provided an \p
144  // inner_boundary_nodes. If so, we pass a std::set to the actual
145  // implementation of the build_inf_elem(), so that we can convert
146  // this to the Node * vector
147  if (inner_boundary_nodes != libmesh_nullptr)
148  {
149  // note that the std::set that we will get
150  // from build_inf_elem() uses the index of
151  // the element in this->_elements vector,
152  // and the second entry is the side index
153  // for this element. Therefore, we do _not_
154  // need to renumber nodes and elements
155  // prior to building the infinite elements.
156  //
157  // However, note that this method here uses
158  // node id's... Do we need to renumber?
159 
160 
161  // Form the list of faces of elements which finally
162  // will tell us which nodes should receive boundary
163  // conditions (to form the std::vector<const Node *>)
164  std::set< std::pair<dof_id_type,
165  unsigned int> > inner_faces;
166 
167 
168  // build infinite elements
169  this->build_inf_elem(origin,
170  x_sym, y_sym, z_sym,
171  be_verbose,
172  &inner_faces);
173 
174  if (be_verbose)
175  {
176  this->_mesh.print_info();
177  libMesh::out << "Data pre-processing:" << std::endl
178  << " convert the <int,int> list to a Node * list..."
179  << std::endl;
180  }
181 
182  // First use a std::vector<dof_id_type> that holds
183  // the global node numbers. Then sort this vector,
184  // so that it can be made unique (no multiple occurence
185  // of a node), and then finally insert the Node * in
186  // the vector inner_boundary_nodes.
187  //
188  // Reserve memory for the vector<> with
189  // 4 times the size of the number of elements in the
190  // std::set. This is a good bet for Quad4 face elements.
191  // For higher-order elements, this probably _has_ to lead
192  // to additional allocations...
193  // Practice has to show how this affects performance.
194  std::vector<dof_id_type> inner_boundary_node_numbers;
195  inner_boundary_node_numbers.reserve(4*inner_faces.size());
196 
197  // Now transform the set of pairs to a list of (possibly
198  // duplicate) global node numbers.
199  std::set< std::pair<dof_id_type,unsigned int> >::iterator face_it = inner_faces.begin();
200  const std::set< std::pair<dof_id_type,unsigned int> >::iterator face_end = inner_faces.end();
201  for(; face_it!=face_end; ++face_it)
202  {
203  std::pair<dof_id_type,unsigned int> p = *face_it;
204 
205  // build a full-ordered side element to get _all_ the base nodes
206  UniquePtr<Elem> side(this->_mesh.elem_ref(p.first).build_side_ptr(p.second));
207 
208  // insert all the node numbers in inner_boundary_node_numbers
209  for (unsigned int n=0; n< side->n_nodes(); n++)
210  inner_boundary_node_numbers.push_back(side->node_id(n));
211  }
212 
213 
214  // inner_boundary_node_numbers now still holds multiple entries of
215  // node numbers. So first sort, then unique the vector.
216  // Note that \p std::unique only puts the new ones in
217  // front, while to leftovers are @e not deleted. Instead,
218  // it returns a pointer to the end of the unique range.
219  //TODO:[BSK] int_ibn_size_before is not the same type as unique_size!
220 #ifndef NDEBUG
221  const std::size_t ibn_size_before = inner_boundary_node_numbers.size();
222 #endif
223  std::sort (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
224  std::vector<dof_id_type>::iterator unique_end =
225  std::unique (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
226 
227  std::size_t unique_size = std::distance(inner_boundary_node_numbers.begin(), unique_end);
228  libmesh_assert_less_equal (unique_size, ibn_size_before);
229 
230  // Finally, create const Node * in the inner_boundary_nodes
231  // vector. Reserve, not resize (otherwise, the push_back
232  // would append the interesting nodes, while NULL-nodes
233  // live in the resize'd area...
234  inner_boundary_nodes->reserve (unique_size);
235  inner_boundary_nodes->clear();
236 
237 
238  std::vector<dof_id_type>::iterator pos_it = inner_boundary_node_numbers.begin();
239  for (; pos_it != unique_end; ++pos_it)
240  {
241  const Node * node = this->_mesh.node_ptr(*pos_it);
242  inner_boundary_nodes->push_back(node);
243  }
244 
245  if (be_verbose)
246  libMesh::out << " finished identifying " << unique_size
247  << " target nodes." << std::endl;
248  }
249 
250  else
251 
252  {
253  // There are no inner boundary nodes, so simply build the infinite elements
254  this->build_inf_elem(origin, x_sym, y_sym, z_sym, be_verbose);
255  }
256 
257 
258  STOP_LOG("build_inf_elem()", "InfElemBuilder");
259 
260  // when finished with building the Ifems,
261  // it remains to prepare the mesh for use:
262  // find neighbors again, partition (if needed)...
263  this->_mesh.prepare_for_use (/*skip_renumber =*/ false);
264 
265  return origin;
266 }
virtual UniquePtr< Elem > build_side_ptr(const unsigned int i, bool proxy=true)=0
unsigned short int side
Definition: xdr_io.C:49
const class libmesh_nullptr_t libmesh_nullptr
virtual const Node * node_ptr(const dof_id_type i) const =0
BoundingBox bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:358
void prepare_for_use(const bool skip_renumber_nodes_and_elements=false, const bool skip_find_neighbors=false)
Definition: mesh_base.C:174
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:453
const Point build_inf_elem(const bool be_verbose=false)
OStreamProxy out(std::cout)
void print_info(std::ostream &os=libMesh::out) const
Definition: mesh_base.C:446
uint8_t dof_id_type
Definition: id_types.h:64
void libMesh::InfElemBuilder::build_inf_elem ( const Point origin,
const bool  x_sym = false,
const bool  y_sym = false,
const bool  z_sym = false,
const bool  be_verbose = false,
std::set< std::pair< dof_id_type, unsigned int > > *  inner_faces = libmesh_nullptr 
)
private

Build infinite elements atop a volume-based mesh. Actual implementation.

Definition at line 277 of file inf_elem_builder.C.

References _mesh, std::abs(), libMesh::MeshBase::active_elements_begin(), libMesh::MeshBase::active_elements_end(), libMesh::MeshBase::add_elem(), libMesh::MeshBase::add_point(), libMesh::Elem::build_side_ptr(), libMesh::EDGE2, libMesh::EDGE3, libMesh::MeshBase::elem_ref(), end, libMesh::MeshBase::find_neighbors(), libMesh::DofObject::id(), libMesh::MeshBase::is_serial(), libMesh::MeshBase::libmesh_assert_valid_parallel_ids(), libmesh_nullptr, libMesh::MeshBase::max_elem_id(), libMesh::MeshBase::max_node_id(), libMesh::MeshBase::n_elem(), libMesh::Elem::n_neighbors(), libMesh::Elem::n_vertices(), libMesh::Elem::neighbor(), libMesh::MeshBase::node_ref(), libMesh::TypeVector< T >::norm(), libMesh::out, libMesh::MeshBase::point(), libMesh::DofObject::processor_id(), libMesh::QUAD4, libMesh::QUAD8, libMesh::QUAD9, libMesh::Real, libMesh::DofObject::set_id(), libMesh::Elem::set_node(), side, libMesh::TRI3, and libMesh::TRI6.

284 {
285  if (be_verbose)
286  {
287 #ifdef DEBUG
288  libMesh::out << " Building Infinite Elements:" << std::endl;
289  libMesh::out << " updating element neighbor tables..." << std::endl;
290 #else
291  libMesh::out << " Verbose mode disabled in non-debug mode." << std::endl;
292 #endif
293  }
294 
295 
296  // update element neighbors
297  this->_mesh.find_neighbors();
298 
299  LOG_SCOPE("build_inf_elem()", "InfElemBuilder");
300 
301  // A set for storing element number, side number pairs.
302  // pair.first == element number, pair.second == side number
303  std::set< std::pair<dof_id_type,unsigned int> > faces;
304  std::set< std::pair<dof_id_type,unsigned int> > ofaces;
305 
306  // A set for storing node numbers on the outer faces.
307  std::set<dof_id_type> onodes;
308 
309  // The distance to the farthest point in the mesh from the origin
310  Real max_r=0.;
311 
312  // The index of the farthest point in the mesh from the origin
313  int max_r_node = -1;
314 
315 #ifdef DEBUG
316  if (be_verbose)
317  {
318  libMesh::out << " collecting boundary sides";
319  if (x_sym || y_sym || z_sym)
320  libMesh::out << ", skipping sides in symmetry planes..." << std::endl;
321  else
322  libMesh::out << "..." << std::endl;
323  }
324 #endif
325 
326  // Iterate through all elements and sides, collect indices of all active
327  // boundary sides in the faces set. Skip sides which lie in symmetry planes.
328  // Later, sides of the inner boundary will be sorted out.
329  {
330  MeshBase::element_iterator it = this->_mesh.active_elements_begin();
331  const MeshBase::element_iterator end = this->_mesh.active_elements_end();
332 
333  for(; it != end; ++it)
334  {
335  Elem * elem = *it;
336 
337  for (unsigned int s=0; s<elem->n_neighbors(); s++)
338  {
339  // check if element e is on the boundary
340  if (elem->neighbor(s) == libmesh_nullptr)
341  {
342  // note that it is safe to use the Elem::side() method,
343  // which gives a non-full-ordered element
344  UniquePtr<Elem> side(elem->build_side_ptr(s));
345 
346  // bool flags for symmetry detection
347  bool sym_side=false;
348  bool on_x_sym=true;
349  bool on_y_sym=true;
350  bool on_z_sym=true;
351 
352 
353  // Loop over the nodes to check whether they are on the symmetry planes,
354  // and therefore sufficient to use a non-full-ordered side element
355  for(unsigned int n=0; n<side->n_nodes(); n++)
356  {
357  const Point dist_from_origin =
358  this->_mesh.point(side->node_id(n)) - origin;
359 
360  if(x_sym)
361  if( std::abs(dist_from_origin(0)) > 1.e-3 )
362  on_x_sym=false;
363 
364  if(y_sym)
365  if( std::abs(dist_from_origin(1)) > 1.e-3 )
366  on_y_sym=false;
367 
368  if(z_sym)
369  if( std::abs(dist_from_origin(2)) > 1.e-3 )
370  on_z_sym=false;
371 
372  // if(x_sym)
373  // if( std::abs(dist_from_origin(0)) > 1.e-6 )
374  // on_x_sym=false;
375 
376  // if(y_sym)
377  // if( std::abs(dist_from_origin(1)) > 1.e-6 )
378  // on_y_sym=false;
379 
380  // if(z_sym)
381  // if( std::abs(dist_from_origin(2)) > 1.e-6 )
382  // on_z_sym=false;
383 
384  //find the node most distant from origin
385 
386  Real r = dist_from_origin.norm();
387  if (r > max_r)
388  {
389  max_r = r;
390  max_r_node=side->node_id(n);
391  }
392 
393  }
394 
395  sym_side = (x_sym && on_x_sym) || (y_sym && on_y_sym) || (z_sym && on_z_sym);
396 
397  if (!sym_side)
398  faces.insert( std::make_pair(elem->id(), s) );
399 
400  } // neighbor(s) == libmesh_nullptr
401  } // sides
402  } // elems
403  }
404 
405 
406 
407 
408 
409 
410  // If a boundary side has one node on the outer boundary,
411  // all points of this side are on the outer boundary.
412  // Start with the node most distant from origin, which has
413  // to be on the outer boundary, then recursively find all
414  // sides and nodes connected to it. Found sides are moved
415  // from faces to ofaces, nodes are collected in onodes.
416  // Here, the search is done iteratively, because, depending on
417  // the mesh, a very high level of recursion might be necessary.
418  if (max_r_node >= 0)
419  // include the possibility of the 1st element being most far away.
420  // Only the case of no outer boundary is to be excluded.
421  onodes.insert(max_r_node);
422 
423 
424  {
425  std::set< std::pair<dof_id_type,unsigned int> >::iterator face_it = faces.begin();
426  unsigned int facesfound=0;
427  while (face_it != faces.end()) {
428 
429  std::pair<dof_id_type, unsigned int> p;
430  p = *face_it;
431 
432  // This has to be a full-ordered side element,
433  // since we need the correct n_nodes,
434  UniquePtr<Elem> side(this->_mesh.elem_ref(p.first).build_side_ptr(p.second));
435 
436  bool found=false;
437  for(unsigned int sn=0; sn<side->n_nodes(); sn++)
438  if(onodes.count(side->node_id(sn)))
439  {
440  found=true;
441  break;
442  }
443 
444 
445  // If a new oface is found, include its nodes in onodes
446  if(found)
447  {
448  for(unsigned int sn=0; sn<side->n_nodes(); sn++)
449  onodes.insert(side->node_id(sn));
450 
451  ofaces.insert(p);
452  ++face_it; // iteration is done here
453  faces.erase(p);
454 
455  facesfound++;
456  }
457 
458  else
459  ++face_it; // iteration is done here
460 
461  // If at least one new oface was found in this cycle,
462  // do another search cycle.
463  if(facesfound>0 && face_it == faces.end())
464  {
465  facesfound = 0;
466  face_it = faces.begin();
467  }
468 
469  }
470  }
471 
472 
473 #ifdef DEBUG
474  if (be_verbose)
475  libMesh::out << " found "
476  << faces.size()
477  << " inner and "
478  << ofaces.size()
479  << " outer boundary faces"
480  << std::endl;
481 #endif
482 
483  // When the user provided a non-null pointer to
484  // inner_faces, that implies he wants to have
485  // this std::set. For now, simply copy the data.
486  if (inner_faces != libmesh_nullptr)
487  *inner_faces = faces;
488 
489  // free memory, clear our local variable, no need
490  // for it any more.
491  faces.clear();
492 
493 
494  // outer_nodes maps onodes to their duplicates
495  std::map<dof_id_type, Node *> outer_nodes;
496 
497  // We may need to pick our own object ids in parallel
498  dof_id_type old_max_node_id = _mesh.max_node_id();
499  dof_id_type old_max_elem_id = _mesh.max_elem_id();
500 
501  // for each boundary node, add an outer_node with
502  // double distance from origin.
503  std::set<dof_id_type>::iterator on_it = onodes.begin();
504  for( ; on_it != onodes.end(); ++on_it)
505  {
506  Point p = (Point(this->_mesh.point(*on_it)) * 2) - origin;
507  if (_mesh.is_serial())
508  {
509  // Add with a default id in serial
510  outer_nodes[*on_it]=this->_mesh.add_point(p);
511  }
512  else
513  {
514  // Pick a unique id in parallel
515  Node & bnode = _mesh.node_ref(*on_it);
516  dof_id_type new_id = bnode.id() + old_max_node_id;
517  outer_nodes[*on_it] =
518  this->_mesh.add_point(p, new_id,
519  bnode.processor_id());
520  }
521  }
522 
523 
524 #ifdef DEBUG
525  // for verbose, remember n_elem
526  dof_id_type n_conventional_elem = this->_mesh.n_elem();
527 #endif
528 
529 
530  // build Elems based on boundary side type
531  std::set< std::pair<dof_id_type,unsigned int> >::iterator face_it = ofaces.begin();
532  for( ; face_it != ofaces.end(); ++face_it)
533  {
534  // Shortcut to the pair being iterated over
535  std::pair<dof_id_type,unsigned int> p = *face_it;
536 
537  // build a full-ordered side element to get the base nodes
538  UniquePtr<Elem> side(this->_mesh.elem_ref(p.first).build_side_ptr(p.second));
539 
540  // create cell depending on side type, assign nodes,
541  // use braces to force scope.
542  bool is_higher_order_elem = false;
543 
544  Elem * el;
545  switch(side->type())
546  {
547  // 3D infinite elements
548  // TRIs
549  case TRI3:
550  el=new InfPrism6;
551  break;
552 
553  case TRI6:
554  el=new InfPrism12;
555  is_higher_order_elem = true;
556  break;
557 
558  // QUADs
559  case QUAD4:
560  el=new InfHex8;
561  break;
562 
563  case QUAD8:
564  el=new InfHex16;
565  is_higher_order_elem = true;
566  break;
567 
568  case QUAD9:
569  el=new InfHex18;
570 
571  // the method of assigning nodes (which follows below)
572  // omits in the case of QUAD9 the bubble node; therefore
573  // we assign these first by hand here.
574  el->set_node(16) = side->node_ptr(8);
575  el->set_node(17) = outer_nodes[side->node_id(8)];
576  is_higher_order_elem=true;
577  break;
578 
579  // 2D infinite elements
580  case EDGE2:
581  el=new InfQuad4;
582  break;
583 
584  case EDGE3:
585  el=new InfQuad6;
586  el->set_node(4) = side->node_ptr(2);
587  break;
588 
589  // 1D infinite elements not supported
590  default:
591  libMesh::out << "InfElemBuilder::build_inf_elem(Point, bool, bool, bool, bool): "
592  << "invalid face element "
593  << std::endl;
594  continue;
595  }
596 
597  // In parallel, assign unique ids to the new element
598  if (!_mesh.is_serial())
599  {
600  Elem & belem = _mesh.elem_ref(p.first);
601  el->processor_id() = belem.processor_id();
602  // We'd better not have elements with more than 6 sides
603  el->set_id (belem.id() * 6 + p.second + old_max_elem_id);
604  }
605 
606  // assign vertices to the new infinite element
607  const unsigned int n_base_vertices = side->n_vertices();
608  for(unsigned int i=0; i<n_base_vertices; i++)
609  {
610  el->set_node(i ) = side->node_ptr(i);
611  el->set_node(i+n_base_vertices) = outer_nodes[side->node_id(i)];
612  }
613 
614 
615  // when this is a higher order element,
616  // assign also the nodes in between
617  if (is_higher_order_elem)
618  {
619  // n_safe_base_nodes is the number of nodes in \p side
620  // that may be safely assigned using below for loop.
621  // Actually, n_safe_base_nodes is _identical_ with el->n_vertices(),
622  // since for QUAD9, the 9th node was already assigned above
623  const unsigned int n_safe_base_nodes = el->n_vertices();
624 
625  for(unsigned int i=n_base_vertices; i<n_safe_base_nodes; i++)
626  {
627  el->set_node(i+n_base_vertices) = side->node_ptr(i);
628  el->set_node(i+n_safe_base_nodes) =
629  outer_nodes[side->node_id(i)];
630  }
631  }
632 
633 
634  // add infinite element to mesh
635  this->_mesh.add_elem(el);
636  } // for
637 
638 
639 #ifdef DEBUG
641 
642  if (be_verbose)
643  libMesh::out << " added "
644  << this->_mesh.n_elem() - n_conventional_elem
645  << " infinite elements and "
646  << onodes.size()
647  << " nodes to the mesh"
648  << std::endl
649  << std::endl;
650 #endif
651 }
double abs(double a)
virtual UniquePtr< Elem > build_side_ptr(const unsigned int i, bool proxy=true)=0
virtual void libmesh_assert_valid_parallel_ids() const
Definition: mesh_base.h:916
virtual bool is_serial() const
Definition: mesh_base.h:134
virtual const Point & point(const dof_id_type i) const =0
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:385
unsigned short int side
Definition: xdr_io.C:49
virtual dof_id_type max_node_id() const =0
const class libmesh_nullptr_t libmesh_nullptr
IterBase * end
virtual Node * add_point(const Point &p, const dof_id_type id=DofObject::invalid_id, const processor_id_type proc_id=DofObject::invalid_processor_id)=0
virtual dof_id_type max_elem_id() const =0
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true)=0
virtual Elem * add_elem(Elem *e)=0
virtual element_iterator active_elements_begin()=0
virtual element_iterator active_elements_end()=0
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:453
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual dof_id_type n_elem() const =0
OStreamProxy out(std::cout)
uint8_t dof_id_type
Definition: id_types.h:64
processor_id_type processor_id() const
Definition: dof_object.h:686

Member Data Documentation

MeshBase& libMesh::InfElemBuilder::_mesh
private

Reference to the mesh we're building infinite elements for.

Definition at line 127 of file inf_elem_builder.h.

Referenced by build_inf_elem().


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