libMesh
Loading...
Searching...
No Matches
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
24namespace libMesh
25{
26
27// Forward declarations
28class PointLocatorBase;
29class PeriodicBoundaries;
30
36namespace ElemInternal
37{
38
39template<class T>
40void
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
65template<class T>
66void
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
88template<class T>
89void
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
115template <class T>
116void
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
147template <class T>
148void
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
176template <class T>
177void
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
209template <class T>
210void
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
238template <class T>
239void
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
264template <class T>
265void
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
307template <class T>
308void
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
347template <class T>
348void
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
383template <class T>
384void
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
427template <class T>
428void
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
499template <class T>
500void
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
unsigned int dim
This is the MeshBase class.
Definition mesh_base.h:81
We're using a class instead of a typedef to allow forward declarations and future flexibility.
This is the base class for point locators.
MeshBase & mesh
void family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
void find_interior_neighbors(T this_elem, std::set< T > &neighbor_set)
void total_family_tree_by_side(T elem, std::vector< T > &family, unsigned int s, bool reset)
void family_tree(T elem, std::vector< T > &family, 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)
void active_family_tree(T elem, std::vector< T > &active_family, bool reset=true)
void find_point_neighbors(T this_elem, std::set< T > &neighbor_set, T start_elem)
void family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
void total_family_tree(T elem, std::vector< T > &family, bool reset)
void total_family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
void total_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
void active_family_tree_by_side(T elem, std::vector< T > &family, unsigned int side, bool reset=true)
void active_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
void family_tree_by_side(T elem, std::vector< T > &family, unsigned int s, bool reset)
The libMesh namespace provides an interface to certain functionality in the library.
libmesh_assert(ctx)