Loading [MathJax]/extensions/tex2jax.js
libMesh
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
elem_internal.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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 side,
152  bool reset = true)
153 {
154  // The "family tree" doesn't include subactive or remote elements
155  libmesh_assert(!elem->subactive());
156  libmesh_assert(!elem->is_remote());
157 
158  // Clear the vector if the flag reset tells us to.
159  if (reset)
160  family.clear();
161 
162  libmesh_assert_less (side, elem->n_sides());
163 
164  // Add an active element to the family tree.
165  if (elem->active())
166  family.push_back(elem);
167 
168  // Or recurse into an ancestor element's children.
169  // Do not clear the vector any more.
170  else
171  {
172  const unsigned int nc = elem->n_children();
173  for (unsigned int c = 0; c != nc; c++)
174  if (!elem->child_ptr(c)->is_remote() && elem->is_child_on_side(c, side))
175  ElemInternal::active_family_tree_by_side(elem->child_ptr(c), family, side, false);
176  }
177 }
178 
179 
180 template <class T>
181 void
183  std::vector<T> & family,
184  T neighbor_in,
185  bool reset = true)
186 {
187  // The "family tree" doesn't include subactive elements
188  libmesh_assert(!elem->subactive());
189 
190  // Clear the vector if the flag reset tells us to.
191  if (reset)
192  family.clear();
193 
194  // This only makes sense if we're already a neighbor
195  libmesh_assert (elem->has_neighbor(neighbor_in));
196 
197  // Add this element to the family tree.
198  family.push_back(elem);
199 
200  // Recurse into the elements children, if it's not active.
201  // Do not clear the vector any more.
202  if (!elem->active())
203  for (auto & c : elem->child_ref_range())
204  if (!c.is_remote() && c.has_neighbor(neighbor_in))
205  ElemInternal::family_tree_by_neighbor (&c, family, neighbor_in, false);
206 }
207 
208 
209 template <class T>
210 void
212  std::vector<T> & family,
213  T neighbor_in,
214  bool reset = true)
215 {
216  // Clear the vector if the flag reset tells us to.
217  if (reset)
218  family.clear();
219 
220  // This only makes sense if we're already a neighbor
221  libmesh_assert (elem->has_neighbor(neighbor_in));
222 
223  // Add this element to the family tree.
224  family.push_back(elem);
225 
226  // Recurse into the elements children, if it has any.
227  // Do not clear the vector any more.
228  if (elem->has_children())
229  for (auto & c : elem->child_ref_range())
230  if (!c.is_remote() && c.has_neighbor(neighbor_in))
231  ElemInternal::total_family_tree_by_neighbor (&c, family, neighbor_in, false);
232 }
233 
234 
235 template <class T>
236 void
238  std::vector<T> & family,
239  T neighbor_in,
240  T subneighbor,
241  bool reset = true)
242 {
243  // The "family tree" doesn't include subactive elements
244  libmesh_assert(!elem->subactive());
245 
246  // Clear the vector if the flag reset tells us to.
247  if (reset)
248  family.clear();
249 
250  // To simplify this function we need an existing neighbor
251  libmesh_assert (neighbor_in);
252  libmesh_assert (!neighbor_in->is_remote());
253  libmesh_assert (elem->has_neighbor(neighbor_in));
254 
255  // This only makes sense if subneighbor descends from neighbor
256  libmesh_assert (subneighbor);
257  libmesh_assert (!subneighbor->is_remote());
258  libmesh_assert (neighbor_in->is_ancestor_of(subneighbor));
259 
260  // Add this element to the family tree if applicable.
261  if (neighbor_in == subneighbor)
262  family.push_back(elem);
263 
264  // Recurse into the elements children, if it's not active.
265  // Do not clear the vector any more.
266  if (!elem->active())
267  for (auto & c : elem->child_ref_range())
268  if (!c.is_remote())
269  for (auto child_neigh : c.neighbor_ptr_range())
270  if (child_neigh &&
271  (child_neigh == neighbor_in || (child_neigh->parent() == neighbor_in &&
272  child_neigh->is_ancestor_of(subneighbor))))
273  ElemInternal::family_tree_by_subneighbor (&c, family, child_neigh, subneighbor, false);
274 }
275 
276 
277 
278 template <class T>
279 void
281  std::vector<T> & family,
282  T neighbor_in,
283  T subneighbor,
284  bool reset = true)
285 {
286  // Clear the vector if the flag reset tells us to.
287  if (reset)
288  family.clear();
289 
290  // To simplify this function we need an existing neighbor
291  libmesh_assert (neighbor_in);
292  libmesh_assert (!neighbor_in->is_remote());
293  libmesh_assert (elem->has_neighbor(neighbor_in));
294 
295  // This only makes sense if subneighbor descends from neighbor
296  libmesh_assert (subneighbor);
297  libmesh_assert (!subneighbor->is_remote());
298  libmesh_assert (neighbor_in->is_ancestor_of(subneighbor));
299 
300  // Add this element to the family tree if applicable.
301  if (neighbor_in == subneighbor)
302  family.push_back(elem);
303 
304  // Recurse into the elements children, if it has any.
305  // Do not clear the vector any more.
306  if (elem->has_children())
307  for (auto & c : elem->child_ref_range())
308  if (!c.is_remote())
309  for (auto child_neigh : c.neighbor_ptr_range())
310  if (child_neigh &&
311  (child_neigh == neighbor_in ||
312  (child_neigh->parent() == neighbor_in && child_neigh->is_ancestor_of(subneighbor))))
313  c.total_family_tree_by_subneighbor(family, child_neigh, subneighbor, false);
314 }
315 
316 
317 
318 template <class T>
319 void
321  std::vector<T> & family,
322  T neighbor_in,
323  bool reset = true)
324 {
325  // The "family tree" doesn't include subactive elements or
326  // remote_elements
327  libmesh_assert(!elem->subactive());
328  libmesh_assert(!elem->is_remote());
329 
330  // Clear the vector if the flag reset tells us to.
331  if (reset)
332  family.clear();
333 
334  // This only makes sense if we're already a neighbor
335 #ifndef NDEBUG
336  if (elem->level() >= neighbor_in->level())
337  libmesh_assert (elem->has_neighbor(neighbor_in));
338 #endif
339 
340  // Add an active element to the family tree.
341  if (elem->active())
342  family.push_back(elem);
343 
344  // Or recurse into an ancestor element's children.
345  // Do not clear the vector any more.
346  else if (!elem->active())
347  for (auto & c : elem->child_ref_range())
348  if (!c.is_remote() && c.has_neighbor(neighbor_in))
349  ElemInternal::active_family_tree_by_neighbor (&c, family, neighbor_in, false);
350 }
351 
352 
353 
354 template <class T>
355 void
357  std::vector<T> & family,
358  T neighbor_in,
359  const MeshBase & mesh,
360  const PointLocatorBase & point_locator,
361  const PeriodicBoundaries * pb,
362  bool reset = true)
363 {
364  // The "family tree" doesn't include subactive elements or
365  // remote_elements
366  libmesh_assert(!elem->subactive());
367  libmesh_assert(!elem->is_remote());
368 
369  // Clear the vector if the flag reset tells us to.
370  if (reset)
371  family.clear();
372 
373  // This only makes sense if we're already a topological neighbor
374 #ifndef NDEBUG
375  if (elem->level() >= neighbor_in->level())
376  libmesh_assert (elem->has_topological_neighbor(neighbor_in,
377  mesh,
378  point_locator,
379  pb));
380 #endif
381 
382  // Add an active element to the family tree.
383  if (elem->active())
384  family.push_back(elem);
385 
386  // Or recurse into an ancestor element's children.
387  // Do not clear the vector any more.
388  else if (!elem->active())
389  for (auto & c : elem->child_ref_range())
390  if (!c.is_remote() &&
391  c.has_topological_neighbor(neighbor_in, mesh, point_locator, pb))
392  c.active_family_tree_by_topological_neighbor
393  (family, neighbor_in, mesh, point_locator, pb, false);
394 }
395 
396 
397 
398 template <class T>
399 void
401  std::set<T> & neighbor_set,
402  T start_elem)
403 {
404  libmesh_assert(start_elem);
405  libmesh_assert(start_elem->active());
406  libmesh_assert(start_elem->contains_vertex_of(this_elem, true) ||
407  this_elem->contains_vertex_of(start_elem, true));
408 
409  neighbor_set.clear();
410  neighbor_set.insert(start_elem);
411 
412  std::set<T> untested_set, next_untested_set;
413  untested_set.insert(start_elem);
414 
415  while (!untested_set.empty())
416  {
417  // Loop over all the elements in the patch that haven't already
418  // been tested
419  for (const auto & elem : untested_set)
420  for (auto current_neighbor : elem->neighbor_ptr_range())
421  {
422  if (current_neighbor &&
423  !current_neighbor->is_remote()) // we have a real neighbor on this side
424  {
425  if (current_neighbor->active()) // ... if it is active
426  {
427  if (this_elem->contains_vertex_of(current_neighbor, true) // ... and touches us
428  || current_neighbor->contains_vertex_of(this_elem, true))
429  {
430  // Make sure we'll test it
431  if (!neighbor_set.count(current_neighbor))
432  next_untested_set.insert (current_neighbor);
433 
434  // And add it
435  neighbor_set.insert (current_neighbor);
436  }
437  }
438 #ifdef LIBMESH_ENABLE_AMR
439  else // ... the neighbor is *not* active,
440  { // ... so add *all* neighboring
441  // active children
442  std::vector<T> active_neighbor_children;
443 
444  current_neighbor->active_family_tree_by_neighbor
445  (active_neighbor_children, elem);
446 
447  for (const auto & current_child : active_neighbor_children)
448  {
449  if (this_elem->contains_vertex_of(current_child, true) ||
450  current_child->contains_vertex_of(this_elem, true))
451  {
452  // Make sure we'll test it
453  if (!neighbor_set.count(current_child))
454  next_untested_set.insert (current_child);
455 
456  neighbor_set.insert (current_child);
457  }
458  }
459  }
460 #endif // #ifdef LIBMESH_ENABLE_AMR
461  }
462  }
463  untested_set.swap(next_untested_set);
464  next_untested_set.clear();
465  }
466 }
467 
468 
469 
470 template <class T>
471 void
473  std::set<T> & neighbor_set)
474 {
475  neighbor_set.clear();
476 
477  if ((this_elem->dim() >= LIBMESH_DIM) ||
478  !this_elem->interior_parent())
479  return;
480 
481  T ip = this_elem->interior_parent();
482  libmesh_assert (ip->contains_vertex_of(this_elem, true) ||
483  this_elem->contains_vertex_of(ip, true));
484 
485  libmesh_assert (!ip->subactive());
486 
487 #ifdef LIBMESH_ENABLE_AMR
488  while (!ip->active()) // only possible with AMR, be careful because
489  { // ip->child_ptr(c) is only good with AMR.
490  for (auto & child : ip->child_ref_range())
491  {
492  if (child.contains_vertex_of(this_elem, true) ||
493  this_elem->contains_vertex_of(&child, true))
494  {
495  ip = &child;
496  break;
497  }
498  }
499  }
500 #endif
501 
502  ElemInternal::find_point_neighbors(this_elem, neighbor_set, ip);
503 
504  // Now we have all point neighbors from the interior manifold, but
505  // we need to weed out any neighbors that *only* intersect us at one
506  // point (or at one edge, if we're a 1-D element in 3D).
507  //
508  // The refinement hierarchy helps us here: if the interior element
509  // has a lower or equal refinement level then we can discard it iff
510  // it doesn't contain all our vertices. If it has a higher
511  // refinement level then we can discard it iff we don't contain at
512  // least dim()+1 of its vertices
513  auto it = neighbor_set.begin();
514  const auto end = neighbor_set.end();
515 
516  while (it != end)
517  {
518  auto current = it++;
519  T current_elem = *current;
520 
521  // This won't invalidate iterator it, because it is already
522  // pointing to the next element
523  if (current_elem->level() > this_elem->level())
524  {
525  unsigned int vertices_contained = 0;
526  for (auto & n : current_elem->node_ref_range())
527  if (this_elem->contains_point(n))
528  vertices_contained++;
529 
530  if (vertices_contained <= this_elem->dim())
531  {
532  neighbor_set.erase(current);
533  continue;
534  }
535  }
536  else
537  {
538  for (auto & n : this_elem->node_ref_range())
539  {
540  if (!current_elem->contains_point(n))
541  {
542  neighbor_set.erase(current);
543  break;
544  }
545  }
546  }
547  }
548 }
549 
550 } // namespace ElemInternal
551 } // namespace libMesh
552 
553 #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 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:75
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)