libMesh
elem_internal.h
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 #ifndef LIBMESH_ELEM_INTERNAL_H
19 #define LIBMESH_ELEM_INTERNAL_H
20 
21 // libMesh includes
22 #include "libmesh/elem.h"
23 
24 namespace libMesh
25 {
26 
27 // Forward declarations
28 class PointLocatorBase;
29 class PeriodicBoundaries;
30 
36 namespace ElemInternal
37 {
38 
39 template<class T>
40 void
41 family_tree (T elem,
42  std::vector<T> & family,
43  bool reset = true)
44 {
45  // The "family tree" doesn't include subactive elements
46  libmesh_assert(!elem->subactive());
47 
48  // Clear the vector if the flag reset tells us to.
49  if (reset)
50  family.clear();
51 
52  // Add this element to the family tree.
53  family.push_back(elem);
54 
55  // Recurse into the elements children, if it has them.
56  // Do not clear the vector any more.
57  if (!elem->active())
58  for (auto & c : elem->child_ref_range())
59  if (!c.is_remote())
60  ElemInternal::family_tree (&c, family, false);
61 }
62 
63 
64 
65 template<class T>
66 void
68  std::vector<T> & family,
69  bool reset)
70 {
71  // Clear the vector if the flag reset tells us to.
72  if (reset)
73  family.clear();
74 
75  // Add this element to the family tree.
76  family.push_back(elem);
77 
78  // Recurse into the elements children, if it has them.
79  // Do not clear the vector any more.
80  if (elem->has_children())
81  for (auto & c : elem->child_ref_range())
82  if (!c.is_remote())
83  ElemInternal::total_family_tree (&c, family, false);
84 }
85 
86 
87 
88 template<class T>
89 void
91  std::vector<T> & active_family,
92  bool reset = true)
93 {
94  // The "family tree" doesn't include subactive elements
95  libmesh_assert(!elem->subactive());
96 
97  // Clear the vector if the flag reset tells us to.
98  if (reset)
99  active_family.clear();
100 
101  // Add this element to the family tree if it is active
102  if (elem->active())
103  active_family.push_back(elem);
104 
105  // Otherwise recurse into the element's children.
106  // Do not clear the vector any more.
107  else
108  for (auto & c : elem->child_ref_range())
109  if (!c.is_remote())
110  ElemInternal::active_family_tree (&c, active_family, false);
111 }
112 
113 
114 
115 template <class T>
116 void
118  std::vector<T> & family,
119  unsigned int s,
120  bool reset)
121 {
122  // The "family tree" doesn't include subactive elements
123  libmesh_assert(!elem->subactive());
124 
125  // Clear the vector if the flag reset tells us to.
126  if (reset)
127  family.clear();
128 
129  libmesh_assert_less (s, elem->n_sides());
130 
131  // Add this element to the family tree.
132  family.push_back(elem);
133 
134  // Recurse into the elements children, if it has them.
135  // Do not clear the vector any more.
136  if (!elem->active())
137  {
138  const unsigned int nc = elem->n_children();
139  for (unsigned int c = 0; c != nc; c++)
140  if (!elem->child_ptr(c)->is_remote() && elem->is_child_on_side(c, s))
141  ElemInternal::family_tree_by_side (elem->child_ptr(c), family, s, false);
142  }
143 }
144 
145 
146 
147 template <class T>
148 void
150  std::vector<T> & family,
151  unsigned int s,
152  bool reset)
153 {
154  // Clear the vector if the flag reset tells us to.
155  if (reset)
156  family.clear();
157 
158  libmesh_assert_less (s, elem->n_sides());
159 
160  // Add this element to the family tree.
161  family.push_back(elem);
162 
163  // Recurse into the elements children, if it has them.
164  // Do not clear the vector any more.
165  if (elem->has_children())
166  {
167  const unsigned int nc = elem->n_children();
168  for (unsigned int c = 0; c != nc; c++)
169  if (!elem->child_ptr(c)->is_remote() && elem->is_child_on_side(c, s))
170  ElemInternal::total_family_tree_by_side (elem->child_ptr(c), family, s, false);
171  }
172 }
173 
174 
175 
176 template <class T>
177 void
179  std::vector<T> & family,
180  unsigned int side,
181  bool reset = true)
182 {
183  // The "family tree" doesn't include subactive or remote elements
184  libmesh_assert(!elem->subactive());
185  libmesh_assert(!elem->is_remote());
186 
187  // Clear the vector if the flag reset tells us to.
188  if (reset)
189  family.clear();
190 
191  libmesh_assert_less (side, elem->n_sides());
192 
193  // Add an active element to the family tree.
194  if (elem->active())
195  family.push_back(elem);
196 
197  // Or recurse into an ancestor element's children.
198  // Do not clear the vector any more.
199  else
200  {
201  const unsigned int nc = elem->n_children();
202  for (unsigned int c = 0; c != nc; c++)
203  if (!elem->child_ptr(c)->is_remote() && elem->is_child_on_side(c, side))
204  ElemInternal::active_family_tree_by_side(elem->child_ptr(c), family, side, false);
205  }
206 }
207 
208 
209 template <class T>
210 void
212  std::vector<T> & family,
213  T neighbor_in,
214  bool reset = true)
215 {
216  // The "family tree" doesn't include subactive elements
217  libmesh_assert(!elem->subactive());
218 
219  // Clear the vector if the flag reset tells us to.
220  if (reset)
221  family.clear();
222 
223  // This only makes sense if we're already a neighbor
224  libmesh_assert (elem->has_neighbor(neighbor_in));
225 
226  // Add this element to the family tree.
227  family.push_back(elem);
228 
229  // Recurse into the elements children, if it's not active.
230  // Do not clear the vector any more.
231  if (!elem->active())
232  for (auto & c : elem->child_ref_range())
233  if (!c.is_remote() && c.has_neighbor(neighbor_in))
234  ElemInternal::family_tree_by_neighbor (&c, family, neighbor_in, false);
235 }
236 
237 
238 template <class T>
239 void
241  std::vector<T> & family,
242  T neighbor_in,
243  bool reset = true)
244 {
245  // Clear the vector if the flag reset tells us to.
246  if (reset)
247  family.clear();
248 
249  // This only makes sense if we're already a neighbor
250  libmesh_assert (elem->has_neighbor(neighbor_in));
251 
252  // Add this element to the family tree.
253  family.push_back(elem);
254 
255  // Recurse into the elements children, if it has any.
256  // Do not clear the vector any more.
257  if (elem->has_children())
258  for (auto & c : elem->child_ref_range())
259  if (!c.is_remote() && c.has_neighbor(neighbor_in))
260  ElemInternal::total_family_tree_by_neighbor (&c, family, neighbor_in, false);
261 }
262 
263 
264 template <class T>
265 void
267  std::vector<T> & family,
268  T neighbor_in,
269  T subneighbor,
270  bool reset = true)
271 {
272  // The "family tree" doesn't include subactive elements
273  libmesh_assert(!elem->subactive());
274 
275  // Clear the vector if the flag reset tells us to.
276  if (reset)
277  family.clear();
278 
279  // To simplify this function we need an existing neighbor
280  libmesh_assert (neighbor_in);
281  libmesh_assert (!neighbor_in->is_remote());
282  libmesh_assert (elem->has_neighbor(neighbor_in));
283 
284  // This only makes sense if subneighbor descends from neighbor
285  libmesh_assert (subneighbor);
286  libmesh_assert (!subneighbor->is_remote());
287  libmesh_assert (neighbor_in->is_ancestor_of(subneighbor));
288 
289  // Add this element to the family tree if applicable.
290  if (neighbor_in == subneighbor)
291  family.push_back(elem);
292 
293  // Recurse into the elements children, if it's not active.
294  // Do not clear the vector any more.
295  if (!elem->active())
296  for (auto & c : elem->child_ref_range())
297  if (!c.is_remote())
298  for (auto child_neigh : c.neighbor_ptr_range())
299  if (child_neigh &&
300  (child_neigh == neighbor_in || (child_neigh->parent() == neighbor_in &&
301  child_neigh->is_ancestor_of(subneighbor))))
302  ElemInternal::family_tree_by_subneighbor (&c, family, child_neigh, subneighbor, false);
303 }
304 
305 
306 
307 template <class T>
308 void
310  std::vector<T> & family,
311  T neighbor_in,
312  T subneighbor,
313  bool reset = true)
314 {
315  // Clear the vector if the flag reset tells us to.
316  if (reset)
317  family.clear();
318 
319  // To simplify this function we need an existing neighbor
320  libmesh_assert (neighbor_in);
321  libmesh_assert (!neighbor_in->is_remote());
322  libmesh_assert (elem->has_neighbor(neighbor_in));
323 
324  // This only makes sense if subneighbor descends from neighbor
325  libmesh_assert (subneighbor);
326  libmesh_assert (!subneighbor->is_remote());
327  libmesh_assert (neighbor_in->is_ancestor_of(subneighbor));
328 
329  // Add this element to the family tree if applicable.
330  if (neighbor_in == subneighbor)
331  family.push_back(elem);
332 
333  // Recurse into the elements children, if it has any.
334  // Do not clear the vector any more.
335  if (elem->has_children())
336  for (auto & c : elem->child_ref_range())
337  if (!c.is_remote())
338  for (auto child_neigh : c.neighbor_ptr_range())
339  if (child_neigh &&
340  (child_neigh == neighbor_in ||
341  (child_neigh->parent() == neighbor_in && child_neigh->is_ancestor_of(subneighbor))))
342  c.total_family_tree_by_subneighbor(family, child_neigh, subneighbor, false);
343 }
344 
345 
346 
347 template <class T>
348 void
350  std::vector<T> & family,
351  T neighbor_in,
352  bool reset = true)
353 {
354  // The "family tree" doesn't include subactive elements or
355  // remote_elements
356  libmesh_assert(!elem->subactive());
357  libmesh_assert(!elem->is_remote());
358 
359  // Clear the vector if the flag reset tells us to.
360  if (reset)
361  family.clear();
362 
363  // This only makes sense if we're already a neighbor
364 #ifndef NDEBUG
365  if (elem->level() >= neighbor_in->level())
366  libmesh_assert (elem->has_neighbor(neighbor_in));
367 #endif
368 
369  // Add an active element to the family tree.
370  if (elem->active())
371  family.push_back(elem);
372 
373  // Or recurse into an ancestor element's children.
374  // Do not clear the vector any more.
375  else if (!elem->active())
376  for (auto & c : elem->child_ref_range())
377  if (!c.is_remote() && c.has_neighbor(neighbor_in))
378  ElemInternal::active_family_tree_by_neighbor (&c, family, neighbor_in, false);
379 }
380 
381 
382 
383 template <class T>
384 void
386  std::vector<T> & family,
387  T neighbor_in,
388  const MeshBase & mesh,
389  const PointLocatorBase & point_locator,
390  const PeriodicBoundaries * pb,
391  bool reset = true)
392 {
393  // The "family tree" doesn't include subactive elements or
394  // remote_elements
395  libmesh_assert(!elem->subactive());
396  libmesh_assert(!elem->is_remote());
397 
398  // Clear the vector if the flag reset tells us to.
399  if (reset)
400  family.clear();
401 
402  // This only makes sense if we're already a topological neighbor
403 #ifndef NDEBUG
404  if (elem->level() >= neighbor_in->level())
405  libmesh_assert (elem->has_topological_neighbor(neighbor_in,
406  mesh,
407  point_locator,
408  pb));
409 #endif
410 
411  // Add an active element to the family tree.
412  if (elem->active())
413  family.push_back(elem);
414 
415  // Or recurse into an ancestor element's children.
416  // Do not clear the vector any more.
417  else if (!elem->active())
418  for (auto & c : elem->child_ref_range())
419  if (!c.is_remote() &&
420  c.has_topological_neighbor(neighbor_in, mesh, point_locator, pb))
421  c.active_family_tree_by_topological_neighbor
422  (family, neighbor_in, mesh, point_locator, pb, false);
423 }
424 
425 
426 
427 template <class T>
428 void
430  std::set<T> & neighbor_set,
431  T start_elem)
432 {
433  libmesh_assert(start_elem);
434  libmesh_assert(start_elem->active());
435  libmesh_assert(start_elem->contains_vertex_of(this_elem, true) ||
436  this_elem->contains_vertex_of(start_elem, true));
437 
438  neighbor_set.clear();
439  neighbor_set.insert(start_elem);
440 
441  std::set<T> untested_set, next_untested_set;
442  untested_set.insert(start_elem);
443 
444  while (!untested_set.empty())
445  {
446  // Loop over all the elements in the patch that haven't already
447  // been tested
448  for (const auto & elem : untested_set)
449  for (auto current_neighbor : elem->neighbor_ptr_range())
450  {
451  if (current_neighbor &&
452  !current_neighbor->is_remote()) // we have a real neighbor on this side
453  {
454  if (current_neighbor->active()) // ... if it is active
455  {
456  if (this_elem->contains_vertex_of(current_neighbor, true) // ... and touches us
457  || current_neighbor->contains_vertex_of(this_elem, true))
458  {
459  // Make sure we'll test it
460  if (!neighbor_set.count(current_neighbor))
461  next_untested_set.insert (current_neighbor);
462 
463  // And add it
464  neighbor_set.insert (current_neighbor);
465  }
466  }
467 #ifdef LIBMESH_ENABLE_AMR
468  else // ... the neighbor is *not* active,
469  { // ... so add *all* neighboring
470  // active children
471  std::vector<T> active_neighbor_children;
472 
473  current_neighbor->active_family_tree_by_neighbor
474  (active_neighbor_children, elem);
475 
476  for (const auto & current_child : active_neighbor_children)
477  {
478  if (this_elem->contains_vertex_of(current_child, true) ||
479  current_child->contains_vertex_of(this_elem, true))
480  {
481  // Make sure we'll test it
482  if (!neighbor_set.count(current_child))
483  next_untested_set.insert (current_child);
484 
485  neighbor_set.insert (current_child);
486  }
487  }
488  }
489 #endif // #ifdef LIBMESH_ENABLE_AMR
490  }
491  }
492  untested_set.swap(next_untested_set);
493  next_untested_set.clear();
494  }
495 }
496 
497 
498 
499 template <class T>
500 void
502  std::set<T> & neighbor_set)
503 {
504  neighbor_set.clear();
505 
506  if ((this_elem->dim() >= LIBMESH_DIM) ||
507  !this_elem->interior_parent())
508  return;
509 
510  T ip = this_elem->interior_parent();
511  libmesh_assert (ip->contains_vertex_of(this_elem, true) ||
512  this_elem->contains_vertex_of(ip, true));
513 
514  libmesh_assert (!ip->subactive());
515 
516 #ifdef LIBMESH_ENABLE_AMR
517  while (!ip->active()) // only possible with AMR, be careful because
518  { // ip->child_ptr(c) is only good with AMR.
519  for (auto & child : ip->child_ref_range())
520  {
521  if (child.contains_vertex_of(this_elem, true) ||
522  this_elem->contains_vertex_of(&child, true))
523  {
524  ip = &child;
525  break;
526  }
527  }
528  }
529 #endif
530 
531  ElemInternal::find_point_neighbors(this_elem, neighbor_set, ip);
532 
533  // Now we have all point neighbors from the interior manifold, but
534  // we need to weed out any neighbors that *only* intersect us at one
535  // point (or at one edge, if we're a 1-D element in 3D).
536  //
537  // The refinement hierarchy helps us here: if the interior element
538  // has a lower or equal refinement level then we can discard it iff
539  // it doesn't contain all our vertices. If it has a higher
540  // refinement level then we can discard it iff we don't contain at
541  // least dim()+1 of its vertices
542  auto it = neighbor_set.begin();
543  const auto end = neighbor_set.end();
544 
545  while (it != end)
546  {
547  auto current = it++;
548  T current_elem = *current;
549 
550  // This won't invalidate iterator it, because it is already
551  // pointing to the next element
552  if (current_elem->level() > this_elem->level())
553  {
554  unsigned int vertices_contained = 0;
555  for (auto & n : current_elem->node_ref_range())
556  if (this_elem->contains_point(n))
557  vertices_contained++;
558 
559  if (vertices_contained <= this_elem->dim())
560  {
561  neighbor_set.erase(current);
562  continue;
563  }
564  }
565  else
566  {
567  for (auto & n : this_elem->node_ref_range())
568  {
569  if (!current_elem->contains_point(n))
570  {
571  neighbor_set.erase(current);
572  break;
573  }
574  }
575  }
576  }
577 }
578 
579 } // namespace ElemInternal
580 } // namespace libMesh
581 
582 #endif
void total_family_tree(T elem, std::vector< T > &family, bool reset)
Definition: elem_internal.h:67
void find_interior_neighbors(T this_elem, std::set< T > &neighbor_set)
void total_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
void active_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
unsigned int dim
void active_family_tree(T elem, std::vector< T > &active_family, bool reset=true)
Definition: elem_internal.h:90
We&#39;re using a class instead of a typedef to allow forward declarations and future flexibility...
void total_family_tree_by_side(T elem, std::vector< T > &family, unsigned int s, bool reset)
void active_family_tree_by_side(T elem, std::vector< T > &family, unsigned int side, bool reset=true)
MeshBase & mesh
The libMesh namespace provides an interface to certain functionality in the library.
This is the MeshBase class.
Definition: mesh_base.h:80
void family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
void family_tree(T elem, std::vector< T > &family, bool reset=true)
Definition: elem_internal.h:41
libmesh_assert(ctx)
This is the base class for point locators.
void family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
void find_point_neighbors(T this_elem, std::set< T > &neighbor_set, T start_elem)
void family_tree_by_side(T elem, std::vector< T > &family, unsigned int s, bool reset)
void total_family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
void active_family_tree_by_topological_neighbor(T elem, std::vector< T > &family, T neighbor_in, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb, bool reset=true)