libMesh
inf_elem_builder.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 #include "libmesh/libmesh_config.h"
19 
20 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
21 
22 // C++ includes
23 
24 // Local includes
25 #include "libmesh/inf_elem_builder.h"
26 #include "libmesh/libmesh_logging.h"
27 #include "libmesh/mesh_tools.h"
28 #include "libmesh/face_inf_quad4.h"
29 #include "libmesh/face_inf_quad6.h"
30 #include "libmesh/cell_inf_prism6.h"
31 #include "libmesh/cell_inf_prism12.h"
32 #include "libmesh/cell_inf_hex8.h"
33 #include "libmesh/cell_inf_hex16.h"
34 #include "libmesh/cell_inf_hex18.h"
35 #include "libmesh/mesh_base.h"
36 #include "libmesh/remote_elem.h"
37 
39 
40 namespace libMesh
41 {
42 
43 const Point InfElemBuilder::build_inf_elem(bool be_verbose)
44 {
45  // determine origin automatically,
46  // works only if the mesh has no symmetry planes.
48  Point origin = (b_box.first + b_box.second) / 2;
49 
50  if (be_verbose && _mesh.processor_id() == 0)
51  {
52 #ifdef DEBUG
53  libMesh::out << " Determined origin for Infinite Elements:"
54  << std::endl
55  << " ";
57  libMesh::out << std::endl;
58 #endif
59  }
60 
61  // Call the protected implementation function with the
62  // automatically determined origin.
63  this->build_inf_elem(origin, false, false, false, be_verbose);
64 
65  // when finished with building the Ifems,
66  // it remains to prepare the mesh for use:
67  // find neighbors (again), partition (if needed)...
68  this->_mesh.prepare_for_use ();
69 
70  return origin;
71 }
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
85  const InfElemOriginValue & origin_y,
86  const InfElemOriginValue & origin_z,
87  const bool x_sym,
88  const bool y_sym,
89  const bool z_sym,
90  const bool be_verbose,
91  std::vector<const Node *> * inner_boundary_nodes)
92 {
93  LOG_SCOPE("build_inf_elem()", "InfElemBuilder");
94 
95  // first determine the origin of the
96  // infinite elements. For this, the
97  // origin defaults to the given values,
98  // and may be overridden when the user
99  // provided values
100  Point origin(origin_x.second, origin_y.second, origin_z.second);
101 
102  // when only _one_ of the origin coordinates is _not_
103  // given, we have to determine it on our own
104  if ( !origin_x.first || !origin_y.first || !origin_z.first)
105  {
106  // determine origin
108  const Point auto_origin = (b_box.first+b_box.second)/2;
109 
110  // override default values, if necessary
111  if (!origin_x.first)
112  origin(0) = auto_origin(0);
113 #if LIBMESH_DIM > 1
114  if (!origin_y.first)
115  origin(1) = auto_origin(1);
116 #endif
117 #if LIBMESH_DIM > 2
118  if (!origin_z.first)
119  origin(2) = auto_origin(2);
120 #endif
121 
122  if (be_verbose)
123  {
124  libMesh::out << " Origin for Infinite Elements:" << std::endl;
125 
126  if (!origin_x.first)
127  libMesh::out << " determined x-coordinate" << std::endl;
128  if (!origin_y.first)
129  libMesh::out << " determined y-coordinate" << std::endl;
130  if (!origin_z.first)
131  libMesh::out << " determined z-coordinate" << std::endl;
132 
133  libMesh::out << " coordinates: ";
135  libMesh::out << std::endl;
136  }
137  }
138 
139  else if (be_verbose)
140 
141  {
142  libMesh::out << " Origin for Infinite Elements:" << std::endl;
143  libMesh::out << " coordinates: ";
145  libMesh::out << std::endl;
146  }
147 
148 
149 
150  // Now that we have the origin, check if the user provided an \p
151  // inner_boundary_nodes. If so, we pass a std::set to the actual
152  // implementation of the build_inf_elem(), so that we can convert
153  // this to the Node * vector
154  if (inner_boundary_nodes != nullptr)
155  {
156  // note that the std::set that we will get
157  // from build_inf_elem() uses the index of
158  // the element in this->_elements vector,
159  // and the second entry is the side index
160  // for this element. Therefore, we do _not_
161  // need to renumber nodes and elements
162  // prior to building the infinite elements.
163  //
164  // However, note that this method here uses
165  // node id's... Do we need to renumber?
166 
167 
168  // Form the list of faces of elements which finally
169  // will tell us which nodes should receive boundary
170  // conditions (to form the std::vector<const Node *>)
171  std::set<std::pair<dof_id_type,
172  unsigned int>> inner_faces;
173 
174 
175  // build infinite elements
176  this->build_inf_elem(origin,
177  x_sym, y_sym, z_sym,
178  be_verbose,
179  &inner_faces);
180 
181  if (be_verbose)
182  {
183  this->_mesh.print_info();
184  libMesh::out << "Data pre-processing:" << std::endl
185  << " convert the <int,int> list to a Node * list..."
186  << std::endl;
187  }
188 
189  // First use a std::vector<dof_id_type> that holds
190  // the global node numbers. Then sort this vector,
191  // so that it can be made unique (no multiple occurrence
192  // of a node), and then finally insert the Node * in
193  // the vector inner_boundary_nodes.
194  //
195  // Reserve memory for the vector<> with
196  // 4 times the size of the number of elements in the
197  // std::set. This is a good bet for Quad4 face elements.
198  // For higher-order elements, this probably _has_ to lead
199  // to additional allocations...
200  // Practice has to show how this affects performance.
201  std::vector<dof_id_type> inner_boundary_node_numbers;
202  inner_boundary_node_numbers.reserve(4*inner_faces.size());
203 
204  // Now transform the set of pairs to a list of (possibly
205  // duplicate) global node numbers.
206  for (const auto & p : inner_faces)
207  {
208  // build a full-ordered side element to get _all_ the base nodes
209  std::unique_ptr<Elem> side(this->_mesh.elem_ref(p.first).build_side_ptr(p.second));
210 
211  // insert all the node numbers in inner_boundary_node_numbers
212  for (const Node & node : side->node_ref_range())
213  inner_boundary_node_numbers.push_back(node.id());
214  }
215 
216 
217  // inner_boundary_node_numbers now still holds multiple entries of
218  // node numbers. So first sort, then unique the vector.
219  // Note that \p std::unique only puts the new ones in
220  // front, while to leftovers are not deleted. Instead,
221  // it returns a pointer to the end of the unique range.
222  //TODO:[BSK] int_ibn_size_before is not the same type as unique_size!
223 #ifndef NDEBUG
224  const std::size_t ibn_size_before = inner_boundary_node_numbers.size();
225 #endif
226  std::sort (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
227  auto unique_end =
228  std::unique (inner_boundary_node_numbers.begin(), inner_boundary_node_numbers.end());
229 
230  std::size_t unique_size = std::distance(inner_boundary_node_numbers.begin(), unique_end);
231  libmesh_assert_less_equal (unique_size, ibn_size_before);
232 
233  // Finally, create const Node * in the inner_boundary_nodes
234  // vector. Reserve, not resize (otherwise, the push_back
235  // would append the interesting nodes, while nullptr-nodes
236  // live in the resize'd area...
237  inner_boundary_nodes->reserve (unique_size);
238  inner_boundary_nodes->clear();
239 
240  for (const auto & dof : as_range(inner_boundary_node_numbers.begin(), unique_end))
241  {
242  const Node * node = this->_mesh.node_ptr(dof);
243  inner_boundary_nodes->push_back(node);
244  }
245 
246  if (be_verbose)
247  libMesh::out << " finished identifying " << unique_size
248  << " target nodes." << std::endl;
249  }
250 
251  else
252 
253  {
254  // There are no inner boundary nodes, so simply build the infinite elements
255  this->build_inf_elem(origin, x_sym, y_sym, z_sym, be_verbose);
256  }
257 
258  // when finished with building the Ifems,
259  // it remains to prepare the mesh for use:
260  // find neighbors again, partition (if needed)...
261  this->_mesh.prepare_for_use ();
262 
263  return origin;
264 }
265 
266 
267 
268 
269 
270 
271 
272 
273 
274 // The actual implementation of building elements.
276  const bool x_sym,
277  const bool y_sym,
278  const bool z_sym,
279  const bool be_verbose,
280  std::set<std::pair<dof_id_type,
281  unsigned int>> * inner_faces)
282 {
283  if (be_verbose)
284  {
285 #ifdef DEBUG
286  libMesh::out << " Building Infinite Elements:" << std::endl;
287  libMesh::out << " updating element neighbor tables..." << std::endl;
288 #else
289  libMesh::out << " Verbose mode disabled in non-debug mode." << std::endl;
290 #endif
291  }
292 
293 
294  // update element neighbors
295  this->_mesh.find_neighbors();
296 
297  LOG_SCOPE("build_inf_elem()", "InfElemBuilder");
298 
299  // A set for storing element number, side number pairs.
300  // pair.first == element number, pair.second == side number
301  std::set<std::pair<dof_id_type,unsigned int>> faces;
302  std::set<std::pair<dof_id_type,unsigned int>> ofaces;
303 
304  // A set for storing node numbers on the outer faces.
305  std::set<dof_id_type> onodes;
306 
307  // The distance to the farthest point in the mesh from the origin
308  Real max_r=0.;
309 
310  // The index of the farthest point in the mesh from the origin
311  int max_r_node = -1;
312 
313 #ifdef DEBUG
314  if (be_verbose)
315  {
316  libMesh::out << " collecting boundary sides";
317  if (x_sym || y_sym || z_sym)
318  libMesh::out << ", skipping sides in symmetry planes..." << std::endl;
319  else
320  libMesh::out << "..." << std::endl;
321  }
322 #endif
323 
324  // Iterate through all elements and sides, collect indices of all active
325  // boundary sides in the faces set. Skip sides which lie in symmetry planes.
326  // Later, sides of the inner boundary will be sorted out.
327  for (const auto & elem : _mesh.active_element_ptr_range())
328  for (auto s : elem->side_index_range())
329  if (elem->neighbor_ptr(s) == nullptr)
330  {
331  // note that it is safe to use the Elem::side() method,
332  // which gives a non-full-ordered element
333  std::unique_ptr<Elem> side(elem->build_side_ptr(s));
334 
335  // bool flags for symmetry detection
336  bool sym_side=false;
337  bool on_x_sym=true;
338  bool on_y_sym=true;
339  bool on_z_sym=true;
340 
341 
342  // Loop over the nodes to check whether they are on the symmetry planes,
343  // and therefore sufficient to use a non-full-ordered side element
344  for (const Node & node : side->node_ref_range())
345  {
346  const dof_id_type node_id = node.id();
347  const Point dist_from_origin =
348  this->_mesh.point(node_id) - origin;
349 
350  if (x_sym)
351  if (std::abs(dist_from_origin(0)) > 1.e-3)
352  on_x_sym=false;
353 
354  if (y_sym)
355  if (std::abs(dist_from_origin(1)) > 1.e-3)
356  on_y_sym=false;
357 
358  if (z_sym)
359  if (std::abs(dist_from_origin(2)) > 1.e-3)
360  on_z_sym=false;
361 
362  // if (x_sym)
363  // if (std::abs(dist_from_origin(0)) > 1.e-6)
364  // on_x_sym=false;
365 
366  // if (y_sym)
367  // if (std::abs(dist_from_origin(1)) > 1.e-6)
368  // on_y_sym=false;
369 
370  // if (z_sym)
371  // if (std::abs(dist_from_origin(2)) > 1.e-6)
372  // on_z_sym=false;
373 
374  //find the node most distant from origin
375 
376  Real r = dist_from_origin.norm();
377  if (r > max_r)
378  {
379  max_r = r;
380  max_r_node=node_id;
381  }
382 
383  }
384 
385  sym_side = (x_sym && on_x_sym) || (y_sym && on_y_sym) || (z_sym && on_z_sym);
386 
387  if (!sym_side)
388  faces.emplace(elem->id(), s);
389 
390  } // neighbor(s) == nullptr
391 
392  // On a distributed mesh it might be some other processor who sees
393  // the farthest node.
394  if (!this->_mesh.is_serial())
395  {
396  unsigned int rank;
397  this->_mesh.comm().maxloc(max_r, rank);
398  this->_mesh.comm().broadcast(max_r_node, rank);
399  }
400 
401  // If a boundary side has one node on the outer boundary,
402  // all points of this side are on the outer boundary.
403  // Start with the node most distant from origin, which has
404  // to be on the outer boundary, then recursively find all
405  // sides and nodes connected to it. Found sides are moved
406  // from faces to ofaces, nodes are collected in onodes.
407  // Here, the search is done iteratively, because, depending on
408  // the mesh, a very high level of recursion might be necessary.
409  if (max_r_node >= 0)
410  // include the possibility of the 1st element being most far away.
411  // Only the case of no outer boundary is to be excluded.
412  onodes.insert(max_r_node);
413 
414  // If we're not on a serial mesh, we'll need to synchronize that
415  // onodes list too.
416  bool did_parallel_update;
417 
418  do
419  {
420  did_parallel_update = false;
421 
422  auto face_it = faces.begin();
423  auto face_end = faces.end();
424  unsigned int facesfound=0;
425  while (face_it != face_end) {
426  std::pair<dof_id_type, unsigned int> p = *face_it;
427 
428  // This has to be a full-ordered side element,
429  // since we need the correct n_nodes,
430  std::unique_ptr<Elem> side(this->_mesh.elem_ref(p.first).build_side_ptr(p.second));
431 
432  bool found=false;
433  for (const Node & node : side->node_ref_range())
434  if (onodes.count(node.id()))
435  {
436  found=true;
437  break;
438  }
439 
440  // If a new oface is found, include its nodes in onodes
441  if (found)
442  {
443  for (const Node & node : side->node_ref_range())
444  onodes.insert(node.id());
445 
446  ofaces.insert(p);
447  face_it = faces.erase(face_it); // increment is done here
448 
449  facesfound++;
450  }
451 
452  else
453  ++face_it; // increment is done here
454 
455  // If at least one new oface was found in this cycle,
456  // do another search cycle.
457  if (facesfound>0 && face_it == faces.end())
458  {
459  facesfound = 0;
460  face_it = faces.begin();
461  }
462  }
463 
464  if (!this->_mesh.is_serial())
465  {
466  auto my_onodes_size = onodes.size();
467  this->_mesh.comm().set_union(onodes);
468  did_parallel_update = (onodes.size() > my_onodes_size);
469  this->_mesh.comm().max(did_parallel_update);
470  }
471  }
472  while (did_parallel_update);
473 
474 
475 #ifdef DEBUG
476  if (be_verbose)
477  libMesh::out << " found "
478  << faces.size()
479  << " inner and "
480  << ofaces.size()
481  << " outer boundary faces"
482  << std::endl;
483 #endif
484 
485  // When the user provided a non-null pointer to
486  // inner_faces, that implies he wants to have
487  // this std::set. For now, simply copy the data.
488  if (inner_faces != nullptr)
489  *inner_faces = faces;
490 
491  // free memory, clear our local variable, no need
492  // for it any more.
493  faces.clear();
494 
495 
496  // outer_nodes maps onodes to their duplicates
497  std::map<dof_id_type, Node *> outer_nodes;
498 
499  // We may need to pick our own object ids in parallel
500  dof_id_type old_max_node_id = _mesh.max_node_id();
501  dof_id_type old_max_elem_id = _mesh.max_elem_id();
502 
503  // Likewise with our unique_ids
504 #ifdef LIBMESH_ENABLE_UNIQUE_ID
505  unique_id_type old_max_unique_id = _mesh.parallel_max_unique_id();
506 #endif
507 
508  // for each boundary node, add an outer_node with
509  // double distance from origin.
510  for (const auto & n : onodes)
511  {
512  if (!this->_mesh.query_node_ptr(n))
513  {
515  continue;
516  }
517 
518  Point p = (Point(this->_mesh.point(n)) * 2) - origin;
519  if (_mesh.is_serial())
520  {
521  // Add with a default id in serial
522  outer_nodes[n]=this->_mesh.add_point(p);
523  }
524  else
525  {
526  // Pick a unique id in parallel
527  Node & bnode = _mesh.node_ref(n);
528  dof_id_type new_id = bnode.id() + old_max_node_id;
529  std::unique_ptr<Node> new_node = Node::build(p, new_id);
530  new_node->processor_id() = bnode.processor_id();
531 #ifdef LIBMESH_ENABLE_UNIQUE_ID
532  new_node->set_unique_id(old_max_unique_id + bnode.id());
533 #endif
534 
535  outer_nodes[n] =
536  this->_mesh.add_node(std::move(new_node));
537  }
538  }
539 
540 
541 #ifdef DEBUG
542  // for verbose, remember n_elem
543  dof_id_type n_conventional_elem = this->_mesh.n_elem();
544 #endif
545 
546 
547  // build Elems based on boundary side type
548  for (auto & p : ofaces)
549  {
550  Elem & belem = this->_mesh.elem_ref(p.first);
551 
552  // build a full-ordered side element to get the base nodes
553  std::unique_ptr<Elem> side(belem.build_side_ptr(p.second));
554 
555  // create cell depending on side type, assign nodes,
556  // use braces to force scope.
557  bool is_higher_order_elem = false;
558 
559  std::unique_ptr<Elem> el;
560  switch(side->type())
561  {
562  // 3D infinite elements
563  // TRIs
564  case TRI3:
565  el = Elem::build(INFPRISM6);
566  break;
567 
568  case TRI6:
569  el = Elem::build(INFPRISM12);
570  is_higher_order_elem = true;
571  break;
572 
573  // QUADs
574  case QUAD4:
575  el = Elem::build(INFHEX8);
576  break;
577 
578  case QUAD8:
579  el = Elem::build(INFHEX16);
580  is_higher_order_elem = true;
581  break;
582 
583  case QUAD9:
584  el = Elem::build(INFHEX18);
585 
586  // the method of assigning nodes (which follows below)
587  // omits in the case of QUAD9 the bubble node; therefore
588  // we assign these first by hand here.
589  el->set_node(16, side->node_ptr(8));
590  el->set_node(17, outer_nodes[side->node_id(8)]);
591  is_higher_order_elem=true;
592  break;
593 
594  // 2D infinite elements
595  case EDGE2:
596  el = Elem::build(INFQUAD4);
597  break;
598 
599  case EDGE3:
600  el = Elem::build(INFQUAD6);
601  el->set_node(4, side->node_ptr(2));
602  break;
603 
604  // 1D infinite elements not supported
605  default:
606  libMesh::out << "InfElemBuilder::build_inf_elem(Point, bool, bool, bool, bool): "
607  << "invalid face element "
608  << std::endl;
609  continue;
610  }
611 
612  const unsigned int n_base_vertices = side->n_vertices();
613 
614  // On a distributed mesh, manually assign unique ids to the new
615  // element, and make sure any RemoteElem neighbor links are set.
616  if (!_mesh.is_serial())
617  {
618  el->processor_id() = belem.processor_id();
619 
620  // We'd better not have elements with more than 6 sides
621  const unsigned int max_sides = 6;
622  libmesh_assert_less_equal(el->n_sides(), max_sides);
623  el->set_id (belem.id() * max_sides + p.second + old_max_elem_id);
624 
625 #ifdef LIBMESH_ENABLE_UNIQUE_ID
626  el->set_unique_id(old_max_unique_id + old_max_node_id +
627  belem.id() * max_sides + p.second);
628 #endif
629 
630  // If we have a remote neighbor on a boundary element side
631  if (belem.dim() > 1)
632  for (auto s : belem.side_index_range())
633  if (belem.neighbor_ptr(s) == remote_elem)
634  {
635  // Find any corresponding infinite element side
636  std::unique_ptr<const Elem> remote_side(belem.build_side_ptr(s));
637 
638  for (auto inf_s : el->side_index_range())
639  {
640  // The base side 0 shares all vertices but isn't
641  // remote
642  if (!inf_s)
643  continue;
644 
645  // But another side, one which shares enough
646  // vertices to show it's the same side, is.
647  unsigned int n_shared_vertices = 0;
648  for (unsigned int i = 0; i != n_base_vertices; ++i)
649  for (auto & node : remote_side->node_ref_range())
650  if (side->node_ptr(i) == &node &&
651  el->is_node_on_side(i,inf_s))
652  ++n_shared_vertices;
653 
654  if (n_shared_vertices + 1 >= belem.dim())
655  {
656  el->set_neighbor
657  (inf_s, const_cast<RemoteElem *>(remote_elem));
658  break;
659  }
660  }
661  }
662  }
663 
664  // assign vertices to the new infinite element
665  for (unsigned int i=0; i<n_base_vertices; i++)
666  {
667  el->set_node(i , side->node_ptr(i));
668  el->set_node(i+n_base_vertices, outer_nodes[side->node_id(i)]);
669  }
670 
671 
672  // when this is a higher order element,
673  // assign also the nodes in between
674  if (is_higher_order_elem)
675  {
676  // n_safe_base_nodes is the number of nodes in \p side
677  // that may be safely assigned using below for loop.
678  // Actually, n_safe_base_nodes is _identical_ with el->n_vertices(),
679  // since for QUAD9, the 9th node was already assigned above
680  const unsigned int n_safe_base_nodes = el->n_vertices();
681 
682  for (unsigned int i=n_base_vertices; i<n_safe_base_nodes; i++)
683  {
684  el->set_node(i+n_base_vertices, side->node_ptr(i));
685  el->set_node(i+n_safe_base_nodes,
686  outer_nodes[side->node_id(i)]);
687  }
688  }
689 
690 
691  // add infinite element to mesh
692  this->_mesh.add_elem(std::move(el));
693  } // for
694 
695  // If we're not in serial, we might not have all our remote_elem
696  // neighbors set up properly on the new elements: two new infinite
697  // elements which should be neighbors may not be rooted in finite
698  // elmeents which are neighbors, and we were only looking for
699  // remote_elem links on each root finite element. We'll fix the
700  // problem by first finding all the neighbors we can and then
701  // recognizing that any missing neighbors on infinite elements must
702  // be remote.
703  if (!_mesh.is_serial())
704  {
705  _mesh.find_neighbors(/*reset_remote_elements=*/ false,
706  /*reset_current_list=*/ true,
707  /*assert_valid=*/ false);
708 
709  for (auto & p : ofaces)
710  {
711  Elem & belem = this->_mesh.elem_ref(p.first);
712  Elem * inf_elem = belem.neighbor_ptr(p.second);
713  libmesh_assert(inf_elem);
714 
715  for (auto s : make_range(inf_elem->n_sides()))
716  if (!inf_elem->neighbor_ptr(s))
717  inf_elem->set_neighbor
718  (s, const_cast<RemoteElem *>(remote_elem));
719  }
720  }
721 
722 #ifdef DEBUG
724 
725  if (be_verbose)
726  libMesh::out << " added "
727  << this->_mesh.n_elem() - n_conventional_elem
728  << " infinite elements and "
729  << onodes.size()
730  << " nodes to the mesh"
731  << std::endl
732  << std::endl;
733 #endif
734 }
735 
736 } // namespace libMesh
737 
738 
739 
740 
741 
742 #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS
A Node is like a Point, but with more information.
Definition: node.h:52
virtual unique_id_type parallel_max_unique_id() const =0
auto norm() const
Definition: type_vector.h:908
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2724
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
libMesh::BoundingBox create_bounding_box(const MeshBase &mesh)
Definition: mesh_tools.C:566
void prepare_for_use(const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors)
Prepare a newly created (or read) mesh for use.
Definition: mesh_base.C:824
virtual void find_neighbors(const bool reset_remote_elements=false, const bool reset_current_list=true, const bool assert_valid=true)=0
Locate element face (edge in 2D) neighbors.
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
const Parallel::Communicator & comm() const
The libMesh namespace provides an interface to certain functionality in the library.
Real distance(const Point &p)
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
Add a new Node at Point p to the end of the vertex array, with processor_id procid.
virtual bool is_serial() const
Definition: mesh_base.h:347
std::pair< bool, double > InfElemOriginValue
Useful typedef.
dof_id_type id() const
Definition: dof_object.h:819
virtual Elem * add_elem(Elem *e)=0
Add elem e to the end of the element array.
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:442
void print_info(std::ostream &os=libMesh::out, const unsigned int verbosity=0, const bool global=true) const
Prints relevant information about the mesh.
Definition: mesh_base.C:1748
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
virtual const Node * query_node_ptr(const dof_id_type i) const =0
virtual dof_id_type max_elem_id() const =0
libmesh_assert(ctx)
void maxloc(T &r, unsigned int &max_id) const
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition: elem.h:2632
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
virtual Node * add_node(Node *n)=0
Add Node n to the end of the vertex array.
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
virtual unsigned int n_sides() const =0
static std::unique_ptr< Node > build(const Node &n)
Definition: node.h:315
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2612
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Point build_inf_elem(const bool be_verbose=false)
Build infinite elements atop a volume-based mesh, determine origin automatically. ...
void max(const T &r, T &o, Request &req) const
virtual unsigned short dim() const =0
OStreamProxy out
virtual const Elem & elem_ref(const dof_id_type i) const
Definition: mesh_base.h:778
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:176
virtual void libmesh_assert_valid_parallel_ids() const
Verify id and processor_id consistency of our elements and nodes containers.
Definition: mesh_base.h:1688
virtual const Node & node_ref(const dof_id_type i) const
Definition: mesh_base.h:735
virtual const Point & point(const dof_id_type i) const =0
void write_unformatted(std::ostream &out_stream, const bool newline=true) const
Unformatted print to the stream out.
Definition: type_vector.C:51
virtual dof_id_type max_node_id() const =0
virtual dof_id_type n_elem() const =0
virtual const Node * node_ptr(const dof_id_type i) const =0
processor_id_type processor_id() const
MeshBase & _mesh
Reference to the mesh we&#39;re building infinite elements for.
processor_id_type processor_id() const
Definition: dof_object.h:881
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
uint8_t unique_id_type
Definition: id_types.h:86
uint8_t dof_id_type
Definition: id_types.h:67
void set_union(T &data, const unsigned int root_id) const
const RemoteElem * remote_elem
Definition: remote_elem.C:57