elem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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 
19 
20 // C++ includes
21 #include <algorithm> // for std::sort
22 #include <array>
23 #include <iterator> // for std::ostream_iterator
24 #include <sstream>
25 #include <limits> // for std::numeric_limits<>
26 #include <cmath> // for std::sqrt()
27 
28 // Local includes
29 #include "libmesh/auto_ptr.h" // libmesh_make_unique
30 #include "libmesh/elem.h"
31 #include "libmesh/fe_type.h"
32 #include "libmesh/fe_interface.h"
33 #include "libmesh/node_elem.h"
34 #include "libmesh/edge_edge2.h"
35 #include "libmesh/edge_edge3.h"
36 #include "libmesh/edge_edge4.h"
37 #include "libmesh/edge_inf_edge2.h"
38 #include "libmesh/face_tri3.h"
41 #include "libmesh/face_tri6.h"
42 #include "libmesh/face_quad4.h"
44 #include "libmesh/face_quad8.h"
46 #include "libmesh/face_quad9.h"
47 #include "libmesh/face_inf_quad4.h"
48 #include "libmesh/face_inf_quad6.h"
49 #include "libmesh/cell_tet4.h"
50 #include "libmesh/cell_tet10.h"
51 #include "libmesh/cell_hex8.h"
52 #include "libmesh/cell_hex20.h"
53 #include "libmesh/cell_hex27.h"
54 #include "libmesh/cell_inf_hex8.h"
55 #include "libmesh/cell_inf_hex16.h"
56 #include "libmesh/cell_inf_hex18.h"
57 #include "libmesh/cell_prism6.h"
58 #include "libmesh/cell_prism15.h"
59 #include "libmesh/cell_prism18.h"
62 #include "libmesh/cell_pyramid5.h"
63 #include "libmesh/cell_pyramid13.h"
64 #include "libmesh/cell_pyramid14.h"
65 #include "libmesh/fe_base.h"
66 #include "libmesh/mesh_base.h"
68 #include "libmesh/remote_elem.h"
69 #include "libmesh/reference_elem.h"
70 #include "libmesh/string_to_enum.h"
71 #include "libmesh/threads.h"
74 #include "libmesh/enum_order.h"
75 
76 #ifdef LIBMESH_ENABLE_PERIODIC
77 #include "libmesh/mesh.h"
79 #include "libmesh/boundary_info.h"
80 #endif
81 
82 namespace libMesh
83 {
84 
87 
89 
90 // Initialize static member variables
91 const unsigned int Elem::max_n_nodes;
92 
93 const unsigned int Elem::type_to_n_nodes_map [] =
94  {
95  2, // EDGE2
96  3, // EDGE3
97  4, // EDGE4
98 
99  3, // TRI3
100  6, // TRI6
101 
102  4, // QUAD4
103  8, // QUAD8
104  9, // QUAD9
105 
106  4, // TET4
107  10, // TET10
108 
109  8, // HEX8
110  20, // HEX20
111  27, // HEX27
112 
113  6, // PRISM6
114  15, // PRISM15
115  18, // PRISM18
116 
117  5, // PYRAMID5
118  13, // PYRAMID13
119  14, // PYRAMID14
120 
121  2, // INFEDGE2
122 
123  4, // INFQUAD4
124  6, // INFQUAD6
125 
126  8, // INFHEX8
127  16, // INFHEX16
128  18, // INFHEX18
129 
130  6, // INFPRISM6
131  16, // INFPRISM12
132 
133  1, // NODEELEM
134 
135  0, // REMOTEELEM
136 
137  3, // TRI3SUBDIVISION
138  3, // TRISHELL3
139  4, // QUADSHELL4
140  8, // QUADSHELL8
141  };
142 
143 const unsigned int Elem::type_to_n_sides_map [] =
144  {
145  2, // EDGE2
146  2, // EDGE3
147  2, // EDGE4
148 
149  3, // TRI3
150  3, // TRI6
151 
152  4, // QUAD4
153  4, // QUAD8
154  4, // QUAD9
155 
156  4, // TET4
157  4, // TET10
158 
159  6, // HEX8
160  6, // HEX20
161  6, // HEX27
162 
163  5, // PRISM6
164  5, // PRISM15
165  5, // PRISM18
166 
167  5, // PYRAMID5
168  5, // PYRAMID13
169  5, // PYRAMID14
170 
171  2, // INFEDGE2
172 
173  3, // INFQUAD4
174  3, // INFQUAD6
175 
176  5, // INFHEX8
177  5, // INFHEX16
178  5, // INFHEX18
179 
180  4, // INFPRISM6
181  4, // INFPRISM12
182 
183  0, // NODEELEM
184 
185  0, // REMOTEELEM
186 
187  3, // TRI3SUBDIVISION
188  3, // TRISHELL3
189  4, // QUADSHELL4
190  4, // QUADSHELL8
191  };
192 
193 const unsigned int Elem::type_to_n_edges_map [] =
194  {
195  0, // EDGE2
196  0, // EDGE3
197  0, // EDGE4
198 
199  3, // TRI3
200  3, // TRI6
201 
202  4, // QUAD4
203  4, // QUAD8
204  4, // QUAD9
205 
206  6, // TET4
207  6, // TET10
208 
209  12, // HEX8
210  12, // HEX20
211  12, // HEX27
212 
213  9, // PRISM6
214  9, // PRISM15
215  9, // PRISM18
216 
217  8, // PYRAMID5
218  8, // PYRAMID13
219  8, // PYRAMID14
220 
221  0, // INFEDGE2
222 
223  4, // INFQUAD4
224  4, // INFQUAD6
225 
226  8, // INFHEX8
227  8, // INFHEX16
228  8, // INFHEX18
229 
230  6, // INFPRISM6
231  6, // INFPRISM12
232 
233  0, // NODEELEM
234 
235  0, // REMOTEELEM
236 
237  3, // TRI3SUBDIVISION
238  3, // TRISHELL3
239  4, // QUADSHELL4
240  4, // QUADSHELL8
241  };
242 
243 // ------------------------------------------------------------
244 // Elem class member functions
245 std::unique_ptr<Elem> Elem::build(const ElemType type,
246  Elem * p)
247 {
248  switch (type)
249  {
250  // 0D elements
251  case NODEELEM:
252  return libmesh_make_unique<NodeElem>(p);
253 
254  // 1D elements
255  case EDGE2:
256  return libmesh_make_unique<Edge2>(p);
257  case EDGE3:
258  return libmesh_make_unique<Edge3>(p);
259  case EDGE4:
260  return libmesh_make_unique<Edge4>(p);
261 
262  // 2D elements
263  case TRI3:
264  return libmesh_make_unique<Tri3>(p);
265  case TRISHELL3:
266  return libmesh_make_unique<TriShell3>(p);
267  case TRI3SUBDIVISION:
268  return libmesh_make_unique<Tri3Subdivision>(p);
269  case TRI6:
270  return libmesh_make_unique<Tri6>(p);
271  case QUAD4:
272  return libmesh_make_unique<Quad4>(p);
273  case QUADSHELL4:
274  return libmesh_make_unique<QuadShell4>(p);
275  case QUAD8:
276  return libmesh_make_unique<Quad8>(p);
277  case QUADSHELL8:
278  return libmesh_make_unique<QuadShell8>(p);
279  case QUAD9:
280  return libmesh_make_unique<Quad9>(p);
281 
282  // 3D elements
283  case TET4:
284  return libmesh_make_unique<Tet4>(p);
285  case TET10:
286  return libmesh_make_unique<Tet10>(p);
287  case HEX8:
288  return libmesh_make_unique<Hex8>(p);
289  case HEX20:
290  return libmesh_make_unique<Hex20>(p);
291  case HEX27:
292  return libmesh_make_unique<Hex27>(p);
293  case PRISM6:
294  return libmesh_make_unique<Prism6>(p);
295  case PRISM15:
296  return libmesh_make_unique<Prism15>(p);
297  case PRISM18:
298  return libmesh_make_unique<Prism18>(p);
299  case PYRAMID5:
300  return libmesh_make_unique<Pyramid5>(p);
301  case PYRAMID13:
302  return libmesh_make_unique<Pyramid13>(p);
303  case PYRAMID14:
304  return libmesh_make_unique<Pyramid14>(p);
305 
306 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
307  // 1D infinite elements
308  case INFEDGE2:
309  return libmesh_make_unique<InfEdge2>(p);
310 
311  // 2D infinite elements
312  case INFQUAD4:
313  return libmesh_make_unique<InfQuad4>(p);
314  case INFQUAD6:
315  return libmesh_make_unique<InfQuad6>(p);
316 
317  // 3D infinite elements
318  case INFHEX8:
319  return libmesh_make_unique<InfHex8>(p);
320  case INFHEX16:
321  return libmesh_make_unique<InfHex16>(p);
322  case INFHEX18:
323  return libmesh_make_unique<InfHex18>(p);
324  case INFPRISM6:
325  return libmesh_make_unique<InfPrism6>(p);
326  case INFPRISM12:
327  return libmesh_make_unique<InfPrism12>(p);
328 #endif
329 
330  default:
331  libmesh_error_msg("ERROR: Undefined element type!");
332  }
333 }
334 
335 
336 
337 const Elem * Elem::reference_elem () const
338 {
339  return &(ReferenceElem::get(this->type()));
340 }
341 
342 
343 
345 {
346  Point cp;
347 
348  for (unsigned int n=0; n<this->n_vertices(); n++)
349  cp.add (this->point(n));
350 
351  return (cp /= static_cast<Real>(this->n_vertices()));
352 }
353 
354 
355 
357 {
359 
360  for (unsigned int n_outer=0; n_outer<this->n_vertices(); n_outer++)
361  for (unsigned int n_inner=n_outer+1; n_inner<this->n_vertices(); n_inner++)
362  {
363  const Point diff = (this->point(n_outer) - this->point(n_inner));
364 
365  h_min = std::min(h_min, diff.norm_sq());
366  }
367 
368  return std::sqrt(h_min);
369 }
370 
371 
372 
374 {
375  Real h_max=0;
376 
377  for (unsigned int n_outer=0; n_outer<this->n_vertices(); n_outer++)
378  for (unsigned int n_inner=n_outer+1; n_inner<this->n_vertices(); n_inner++)
379  {
380  const Point diff = (this->point(n_outer) - this->point(n_inner));
381 
382  h_max = std::max(h_max, diff.norm_sq());
383  }
384 
385  return std::sqrt(h_max);
386 }
387 
388 
389 
390 Real Elem::length(const unsigned int n1,
391  const unsigned int n2) const
392 {
393  libmesh_assert_less ( n1, this->n_vertices() );
394  libmesh_assert_less ( n2, this->n_vertices() );
395 
396  return (this->point(n1) - this->point(n2)).norm();
397 }
398 
399 
400 
402 {
403  const unsigned short n_n = this->n_nodes();
404 
405  std::array<dof_id_type, Elem::max_n_nodes> node_ids;
406 
407  for (unsigned short n=0; n != n_n; ++n)
408  node_ids[n] = this->node_id(n);
409 
410  // Always sort, so that different local node numberings hash to the
411  // same value.
412  std::sort (node_ids.begin(), node_ids.begin()+n_n);
413 
414  return Utility::hashword(node_ids.data(), n_n);
415 }
416 
417 
418 
419 bool Elem::operator == (const Elem & rhs) const
420 {
421  // If the elements aren't the same type, they aren't equal
422  if (this->type() != rhs.type())
423  return false;
424 
425  const unsigned short n_n = this->n_nodes();
426  libmesh_assert_equal_to(n_n, rhs.n_nodes());
427 
428  // Make two sorted arrays of global node ids and compare them for
429  // equality.
430  std::array<dof_id_type, Elem::max_n_nodes> this_ids, rhs_ids;
431 
432  for (unsigned short n = 0; n != n_n; n++)
433  {
434  this_ids[n] = this->node_id(n);
435  rhs_ids[n] = rhs.node_id(n);
436  }
437 
438  // Sort the vectors to rule out different local node numberings.
439  std::sort(this_ids.begin(), this_ids.begin()+n_n);
440  std::sort(rhs_ids.begin(), rhs_ids.begin()+n_n);
441 
442  // If the node ids match, the elements are equal!
443  for (unsigned short n = 0; n != n_n; ++n)
444  if (this_ids[n] != rhs_ids[n])
445  return false;
446  return true;
447 }
448 
449 
450 
451 bool Elem::is_semilocal(const processor_id_type my_pid) const
452 {
453  std::set<const Elem *> point_neighbors;
454 
455  this->find_point_neighbors(point_neighbors);
456 
457  for (const auto & elem : point_neighbors)
458  if (elem->processor_id() == my_pid)
459  return true;
460 
461  return false;
462 }
463 
464 
465 
466 bool Elem::contains_vertex_of(const Elem * e) const
467 {
468  // Our vertices are the first numbered nodes
469  for (unsigned int n = 0; n != e->n_vertices(); ++n)
470  if (this->contains_point(e->point(n)))
471  return true;
472  return false;
473 }
474 
475 
476 
477 bool Elem::contains_edge_of(const Elem * e) const
478 {
479  unsigned int num_contained_edges = 0;
480 
481  // Our vertices are the first numbered nodes
482  for (unsigned int n = 0; n != e->n_vertices(); ++n)
483  {
484  if (this->contains_point(e->point(n)))
485  {
486  num_contained_edges++;
487  if (num_contained_edges>=2)
488  {
489  return true;
490  }
491  }
492  }
493  return false;
494 }
495 
496 
497 
499  std::set<const Elem *> & neighbor_set) const
500 {
501  libmesh_assert(this->contains_point(p));
502  libmesh_assert(this->active());
503 
504  neighbor_set.clear();
505  neighbor_set.insert(this);
506 
507  std::set<const Elem *> untested_set, next_untested_set;
508  untested_set.insert(this);
509 
510  while (!untested_set.empty())
511  {
512  // Loop over all the elements in the patch that haven't already
513  // been tested
514  for (const auto & elem : untested_set)
515  for (auto current_neighbor : elem->neighbor_ptr_range())
516  {
517  if (current_neighbor &&
518  current_neighbor != remote_elem) // we have a real neighbor on this side
519  {
520  if (current_neighbor->active()) // ... if it is active
521  {
522  if (current_neighbor->contains_point(p)) // ... and touches p
523  {
524  // Make sure we'll test it
525  if (!neighbor_set.count(current_neighbor))
526  next_untested_set.insert (current_neighbor);
527 
528  // And add it
529  neighbor_set.insert (current_neighbor);
530  }
531  }
532 #ifdef LIBMESH_ENABLE_AMR
533  else // ... the neighbor is *not* active,
534  { // ... so add *all* neighboring
535  // active children that touch p
536  std::vector<const Elem *> active_neighbor_children;
537 
538  current_neighbor->active_family_tree_by_neighbor
539  (active_neighbor_children, elem);
540 
541  for (const auto & current_child : active_neighbor_children)
542  if (current_child->contains_point(p))
543  {
544  // Make sure we'll test it
545  if (!neighbor_set.count(current_child))
546  next_untested_set.insert (current_child);
547 
548  neighbor_set.insert (current_child);
549  }
550  }
551 #endif // #ifdef LIBMESH_ENABLE_AMR
552  }
553  }
554  untested_set.swap(next_untested_set);
555  next_untested_set.clear();
556  }
557 }
558 
559 
560 
561 void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set) const
562 {
563  this->find_point_neighbors(neighbor_set, this);
564 }
565 
566 
567 
568 void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set,
569  const Elem * start_elem) const
570 {
571  libmesh_assert(start_elem);
572  libmesh_assert(start_elem->active());
573  libmesh_assert(start_elem->contains_vertex_of(this) ||
574  this->contains_vertex_of(start_elem));
575 
576  neighbor_set.clear();
577  neighbor_set.insert(start_elem);
578 
579  std::set<const Elem *> untested_set, next_untested_set;
580  untested_set.insert(start_elem);
581 
582  while (!untested_set.empty())
583  {
584  // Loop over all the elements in the patch that haven't already
585  // been tested
586  for (const auto & elem : untested_set)
587  for (auto current_neighbor : elem->neighbor_ptr_range())
588  {
589  if (current_neighbor &&
590  current_neighbor != remote_elem) // we have a real neighbor on this side
591  {
592  if (current_neighbor->active()) // ... if it is active
593  {
594  if (this->contains_vertex_of(current_neighbor) // ... and touches us
595  || current_neighbor->contains_vertex_of(this))
596  {
597  // Make sure we'll test it
598  if (!neighbor_set.count(current_neighbor))
599  next_untested_set.insert (current_neighbor);
600 
601  // And add it
602  neighbor_set.insert (current_neighbor);
603  }
604  }
605 #ifdef LIBMESH_ENABLE_AMR
606  else // ... the neighbor is *not* active,
607  { // ... so add *all* neighboring
608  // active children
609  std::vector<const Elem *> active_neighbor_children;
610 
611  current_neighbor->active_family_tree_by_neighbor
612  (active_neighbor_children, elem);
613 
614  for (const auto & current_child : active_neighbor_children)
615  {
616  if (this->contains_vertex_of(current_child) ||
617  (current_child)->contains_vertex_of(this))
618  {
619  // Make sure we'll test it
620  if (!neighbor_set.count(current_child))
621  next_untested_set.insert (current_child);
622 
623  neighbor_set.insert (current_child);
624  }
625  }
626  }
627 #endif // #ifdef LIBMESH_ENABLE_AMR
628  }
629  }
630  untested_set.swap(next_untested_set);
631  next_untested_set.clear();
632  }
633 }
634 
635 
636 
638  const Point & p2,
639  std::set<const Elem *> & neighbor_set) const
640 {
641  // Simple but perhaps suboptimal code: find elements containing the
642  // first point, then winnow this set down by removing elements which
643  // don't also contain the second point
644 
645  libmesh_assert(this->contains_point(p2));
646  this->find_point_neighbors(p1, neighbor_set);
647 
648  std::set<const Elem *>::iterator it = neighbor_set.begin();
649  const std::set<const Elem *>::iterator end = neighbor_set.end();
650 
651  while (it != end)
652  {
653  // As of C++11, set::erase returns an iterator to the element
654  // following the erased element, or end.
655  if (!(*it)->contains_point(p2))
656  it = neighbor_set.erase(it);
657  else
658  ++it;
659  }
660 }
661 
662 
663 
664 void Elem::find_edge_neighbors(std::set<const Elem *> & neighbor_set) const
665 {
666  neighbor_set.clear();
667  neighbor_set.insert(this);
668 
669  std::set<const Elem *> untested_set, next_untested_set;
670  untested_set.insert(this);
671 
672  while (!untested_set.empty())
673  {
674  // Loop over all the elements in the patch that haven't already
675  // been tested
676  for (const auto & elem : untested_set)
677  {
678  for (auto current_neighbor : elem->neighbor_ptr_range())
679  {
680  if (current_neighbor &&
681  current_neighbor != remote_elem) // we have a real neighbor on this side
682  {
683  if (current_neighbor->active()) // ... if it is active
684  {
685  if (this->contains_edge_of(current_neighbor) // ... and touches us
686  || current_neighbor->contains_edge_of(this))
687  {
688  // Make sure we'll test it
689  if (!neighbor_set.count(current_neighbor))
690  next_untested_set.insert (current_neighbor);
691 
692  // And add it
693  neighbor_set.insert (current_neighbor);
694  }
695  }
696 #ifdef LIBMESH_ENABLE_AMR
697  else // ... the neighbor is *not* active,
698  { // ... so add *all* neighboring
699  // active children
700  std::vector<const Elem *> active_neighbor_children;
701 
702  current_neighbor->active_family_tree_by_neighbor
703  (active_neighbor_children, elem);
704 
705  for (const auto & current_child : active_neighbor_children)
706  if (this->contains_edge_of(current_child) || current_child->contains_edge_of(this))
707  {
708  // Make sure we'll test it
709  if (!neighbor_set.count(current_child))
710  next_untested_set.insert (current_child);
711 
712  neighbor_set.insert (current_child);
713  }
714  }
715 #endif // #ifdef LIBMESH_ENABLE_AMR
716  }
717  }
718  }
719  untested_set.swap(next_untested_set);
720  next_untested_set.clear();
721  }
722 }
723 
724 
725 void Elem::find_interior_neighbors(std::set<const Elem *> & neighbor_set) const
726 {
727  neighbor_set.clear();
728 
729  if ((this->dim() >= LIBMESH_DIM) ||
730  !this->interior_parent())
731  return;
732 
733  const Elem * ip = this->interior_parent();
734  libmesh_assert (ip->contains_vertex_of(this) ||
735  this->contains_vertex_of(ip));
736 
737  libmesh_assert (!ip->subactive());
738 
739 #ifdef LIBMESH_ENABLE_AMR
740  while (!ip->active()) // only possible with AMR, be careful because
741  { // ip->child_ptr(c) is only good with AMR.
742  for (auto & child : ip->child_ref_range())
743  {
744  if (child.contains_vertex_of(this) ||
745  this->contains_vertex_of(&child))
746  {
747  ip = &child;
748  break;
749  }
750  }
751  }
752 #endif
753 
754  this->find_point_neighbors(neighbor_set, ip);
755 
756  // Now we have all point neighbors from the interior manifold, but
757  // we need to weed out any neighbors that *only* intersect us at one
758  // point (or at one edge, if we're a 1-D element in 3D).
759  //
760  // The refinement hierarchy helps us here: if the interior element
761  // has a lower or equal refinement level then we can discard it iff
762  // it doesn't contain all our vertices. If it has a higher
763  // refinement level then we can discard it iff we don't contain at
764  // least dim()+1 of its vertices
765  std::set<const Elem *>::iterator it = neighbor_set.begin();
766  const std::set<const Elem *>::iterator end = neighbor_set.end();
767 
768  while (it != end)
769  {
770  std::set<const Elem *>::iterator current = it++;
771  const Elem * elem = *current;
772 
773  // This won't invalidate iterator it, because it is already
774  // pointing to the next element
775  if (elem->level() > this->level())
776  {
777  unsigned int vertices_contained = 0;
778  for (auto & n : elem->node_ref_range())
779  if (this->contains_point(n))
780  vertices_contained++;
781 
782  if (vertices_contained <= this->dim())
783  {
784  neighbor_set.erase(current);
785  continue;
786  }
787  }
788  else
789  {
790  for (auto & n : this->node_ref_range())
791  {
792  if (!elem->contains_point(n))
793  {
794  neighbor_set.erase(current);
795  break;
796  }
797  }
798  }
799  }
800 }
801 
802 
803 
804 const Elem * Elem::interior_parent () const
805 {
806  // interior parents make no sense for full-dimensional elements.
807  libmesh_assert_less (this->dim(), LIBMESH_DIM);
808 
809  // they USED TO BE only good for level-0 elements, but we now
810  // support keeping interior_parent() valid on refined boundary
811  // elements.
812  // if (this->level() != 0)
813  // return this->parent()->interior_parent();
814 
815  // We store the interior_parent pointer after both the parent
816  // neighbor and neighbor pointers
817  Elem * interior_p = _elemlinks[1+this->n_sides()];
818 
819  // If we have an interior_parent, we USED TO assume it was a
820  // one-higher-dimensional interior element, but we now allow e.g.
821  // edge elements to have a 3D interior_parent with no
822  // intermediate 2D element.
823  // libmesh_assert (!interior_p ||
824  // interior_p->dim() == (this->dim()+1));
825  libmesh_assert (!interior_p ||
826  (interior_p == remote_elem) ||
827  (interior_p->dim() > this->dim()));
828 
829  // We require consistency between AMR of interior and of boundary
830  // elements
831  if (interior_p && (interior_p != remote_elem))
832  libmesh_assert_less_equal (interior_p->level(), this->level());
833 
834  return interior_p;
835 }
836 
837 
838 
840 {
841  // See the const version for comments
842  libmesh_assert_less (this->dim(), LIBMESH_DIM);
843  Elem * interior_p = _elemlinks[1+this->n_sides()];
844 
845  libmesh_assert (!interior_p ||
846  (interior_p == remote_elem) ||
847  (interior_p->dim() > this->dim()));
848  if (interior_p && (interior_p != remote_elem))
849  libmesh_assert_less_equal (interior_p->level(), this->level());
850 
851  return interior_p;
852 }
853 
854 
855 
857 {
858  // interior parents make no sense for full-dimensional elements.
859  libmesh_assert_less (this->dim(), LIBMESH_DIM);
860 
861  // If we have an interior_parent, we USED TO assume it was a
862  // one-higher-dimensional interior element, but we now allow e.g.
863  // edge elements to have a 3D interior_parent with no
864  // intermediate 2D element.
865  // libmesh_assert (!p ||
866  // p->dim() == (this->dim()+1));
867  libmesh_assert (!p ||
868  (p == remote_elem) ||
869  (p->dim() > this->dim()));
870 
871  _elemlinks[1+this->n_sides()] = p;
872 }
873 
874 
875 
876 #ifdef LIBMESH_ENABLE_PERIODIC
877 
878 Elem * Elem::topological_neighbor (const unsigned int i,
879  MeshBase & mesh,
880  const PointLocatorBase & point_locator,
881  const PeriodicBoundaries * pb)
882 {
883  libmesh_assert_less (i, this->n_neighbors());
884 
885  Elem * neighbor_i = this->neighbor_ptr(i);
886  if (neighbor_i != nullptr)
887  return neighbor_i;
888 
889  if (pb)
890  {
891  // Since the neighbor is nullptr it must be on a boundary. We need
892  // see if this is a periodic boundary in which case it will have a
893  // topological neighbor
894  std::vector<boundary_id_type> bc_ids;
895  mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
896  for (const auto & id : bc_ids)
897  if (pb->boundary(id))
898  {
899  // Since the point locator inside of periodic boundaries
900  // returns a const pointer we will retrieve the proper
901  // pointer directly from the mesh object.
902  const Elem * const cn = pb->neighbor(id, point_locator, this, i);
903  neighbor_i = const_cast<Elem *>(cn);
904 
905  // Since coarse elements do not have more refined
906  // neighbors we need to make sure that we don't return one
907  // of these types of neighbors.
908  if (neighbor_i)
909  while (level() < neighbor_i->level())
910  neighbor_i = neighbor_i->parent();
911  return neighbor_i;
912  }
913  }
914 
915  return nullptr;
916 }
917 
918 
919 
920 const Elem * Elem::topological_neighbor (const unsigned int i,
921  const MeshBase & mesh,
922  const PointLocatorBase & point_locator,
923  const PeriodicBoundaries * pb) const
924 {
925  libmesh_assert_less (i, this->n_neighbors());
926 
927  const Elem * neighbor_i = this->neighbor_ptr(i);
928  if (neighbor_i != nullptr)
929  return neighbor_i;
930 
931  if (pb)
932  {
933  // Since the neighbor is nullptr it must be on a boundary. We need
934  // see if this is a periodic boundary in which case it will have a
935  // topological neighbor
936  std::vector<boundary_id_type> bc_ids;
937  mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
938  for (const auto & id : bc_ids)
939  if (pb->boundary(id))
940  {
941  neighbor_i = pb->neighbor(id, point_locator, this, i);
942 
943  // Since coarse elements do not have more refined
944  // neighbors we need to make sure that we don't return one
945  // of these types of neighbors.
946  if (neighbor_i)
947  while (level() < neighbor_i->level())
948  neighbor_i = neighbor_i->parent();
949  return neighbor_i;
950  }
951  }
952 
953  return nullptr;
954 }
955 
956 
958  const MeshBase & mesh,
959  const PointLocatorBase & point_locator,
960  const PeriodicBoundaries * pb) const
961 {
962  // First see if this is a normal "interior" neighbor
963  if (has_neighbor(elem))
964  return true;
965 
966  for (auto n : this->side_index_range())
967  if (this->topological_neighbor(n, mesh, point_locator, pb))
968  return true;
969 
970  return false;
971 }
972 
973 
974 #endif
975 
976 #ifdef DEBUG
977 
979 {
980  libmesh_assert(this->valid_id());
981  for (unsigned int n=0; n != this->n_nodes(); ++n)
982  {
983  libmesh_assert(this->node_ptr(n));
984  libmesh_assert(this->node_ptr(n)->valid_id());
985  }
986 }
987 
988 
989 
991 {
992  for (auto n : this->side_index_range())
993  {
994  const Elem * neigh = this->neighbor_ptr(n);
995 
996  // Any element might have a remote neighbor; checking
997  // to make sure that's not inaccurate is tough.
998  if (neigh == remote_elem)
999  continue;
1000 
1001  if (neigh)
1002  {
1003  // Only subactive elements have subactive neighbors
1004  libmesh_assert (this->subactive() || !neigh->subactive());
1005 
1006  const Elem * elem = this;
1007 
1008  // If we're subactive but our neighbor isn't, its
1009  // return neighbor link will be to our first active
1010  // ancestor OR to our inactive ancestor of the same
1011  // level as neigh,
1012  if (this->subactive() && !neigh->subactive())
1013  {
1014  for (elem = this; !elem->active();
1015  elem = elem->parent())
1016  libmesh_assert(elem);
1017  }
1018  else
1019  {
1020  unsigned int rev = neigh->which_neighbor_am_i(elem);
1021  libmesh_assert_less (rev, neigh->n_neighbors());
1022 
1023  if (this->subactive() && !neigh->subactive())
1024  {
1025  while (neigh->neighbor_ptr(rev) != elem)
1026  {
1027  libmesh_assert(elem->parent());
1028  elem = elem->parent();
1029  }
1030  }
1031  else
1032  {
1033  const Elem * nn = neigh->neighbor_ptr(rev);
1034  libmesh_assert(nn);
1035 
1036  for (; elem != nn; elem = elem->parent())
1037  libmesh_assert(elem);
1038  }
1039  }
1040  }
1041  // If we don't have a neighbor and we're not subactive, our
1042  // ancestors shouldn't have any neighbors in this same
1043  // direction.
1044  else if (!this->subactive())
1045  {
1046  const Elem * my_parent = this->parent();
1047  if (my_parent &&
1048  // A parent with a different dimension isn't really one of
1049  // our ancestors, it means we're on a boundary mesh and this
1050  // is an interior mesh element for which we're on a side.
1051  // Nothing to test for in that case.
1052  (my_parent->dim() == this->dim()))
1053  libmesh_assert (!my_parent->neighbor_ptr(n));
1054  }
1055  }
1056 }
1057 
1058 #endif // DEBUG
1059 
1060 
1061 
1062 void Elem::make_links_to_me_local(unsigned int n)
1063 {
1064  Elem * neigh = this->neighbor_ptr(n);
1065 
1066  // Don't bother calling this function unless it's necessary
1067  libmesh_assert(neigh);
1068  libmesh_assert(!neigh->is_remote());
1069 
1070  // We never have neighbors more refined than us
1071  libmesh_assert_less_equal (neigh->level(), this->level());
1072 
1073  // We never have subactive neighbors of non subactive elements
1074  libmesh_assert(!neigh->subactive() || this->subactive());
1075 
1076  // If we have a neighbor less refined than us then it must not
1077  // have any more refined descendants we could have pointed to
1078  // instead.
1079  libmesh_assert((neigh->level() == this->level()) ||
1080  (neigh->active() && !this->subactive()) ||
1081  (!neigh->has_children() && this->subactive()));
1082 
1083  // If neigh is at our level, then its family might have
1084  // remote_elem neighbor links which need to point to us
1085  // instead, but if not, then we're done.
1086  if (neigh->level() != this->level())
1087  return;
1088 
1089  // What side of neigh are we on? We can't use the usual Elem
1090  // method because we're in the middle of restoring topology
1091  const std::unique_ptr<Elem> my_side = this->side_ptr(n);
1092  unsigned int nn = 0;
1093  for (; nn != neigh->n_sides(); ++nn)
1094  {
1095  const std::unique_ptr<Elem> neigh_side = neigh->side_ptr(nn);
1096  if (*my_side == *neigh_side)
1097  break;
1098  }
1099 
1100  // we had better be on *some* side of neigh
1101  libmesh_assert_less (nn, neigh->n_sides());
1102 
1103  // Find any elements that ought to point to elem
1104  std::vector<const Elem *> neigh_family;
1105 #ifdef LIBMESH_ENABLE_AMR
1106  if (this->active())
1107  neigh->family_tree_by_side(neigh_family, nn);
1108  else if (neigh->subactive())
1109 #endif
1110  neigh_family.push_back(neigh);
1111 
1112  // And point them to elem
1113  for (auto & const_elem : neigh_family)
1114  {
1115  // This const_cast is necessary until we have a version of
1116  // family_tree_by_side that returns a vector of non-constant
1117  // pointers when called on a non-constant Elem.
1118  Elem * neigh_family_member = const_cast<Elem *>(const_elem);
1119 
1120  // Only subactive elements point to other subactive elements
1121  if (this->subactive() && !neigh_family_member->subactive())
1122  continue;
1123 
1124  // Ideally, the neighbor link ought to either be correct
1125  // already or ought to be to remote_elem.
1126  //
1127  // However, if we're redistributing a newly created elem,
1128  // after an AMR step but before find_neighbors has fixed up
1129  // neighbor links, we might have an out of date neighbor
1130  // link to elem's parent instead.
1131 #ifdef LIBMESH_ENABLE_AMR
1132  libmesh_assert((neigh_family_member->neighbor_ptr(nn) &&
1133  (neigh_family_member->neighbor_ptr(nn)->active() ||
1134  neigh_family_member->neighbor_ptr(nn)->is_ancestor_of(this))) ||
1135  (neigh_family_member->neighbor_ptr(nn) == remote_elem) ||
1136  ((this->refinement_flag() == JUST_REFINED) &&
1137  (this->parent() != nullptr) &&
1138  (neigh_family_member->neighbor_ptr(nn) == this->parent())));
1139 #else
1140  libmesh_assert((neigh_family_member->neighbor_ptr(nn) == this) ||
1141  (neigh_family_member->neighbor_ptr(nn) == remote_elem));
1142 #endif
1143 
1144  neigh_family_member->set_neighbor(nn, this);
1145  }
1146 }
1147 
1148 
1150 {
1151  libmesh_assert_not_equal_to (this, remote_elem);
1152 
1153  // We need to have handled any children first
1154 #if defined(LIBMESH_ENABLE_AMR) && defined(DEBUG)
1155  if (this->has_children())
1156  for (auto & child : this->child_ref_range())
1157  libmesh_assert_equal_to (&child, remote_elem);
1158 #endif
1159 
1160  // Remotify any neighbor links
1161  for (auto neigh : this->neighbor_ptr_range())
1162  {
1163  if (neigh && neigh != remote_elem)
1164  {
1165  // My neighbor should never be more refined than me; my real
1166  // neighbor would have been its parent in that case.
1167  libmesh_assert_greater_equal (this->level(), neigh->level());
1168 
1169  if (this->level() == neigh->level() &&
1170  neigh->has_neighbor(this))
1171  {
1172 #ifdef LIBMESH_ENABLE_AMR
1173  // My neighbor may have descendants which also consider me a
1174  // neighbor
1175  std::vector<const Elem *> family;
1176  neigh->total_family_tree_by_neighbor (family, this);
1177 
1178  // FIXME - There's a lot of ugly const_casts here; we
1179  // may want to make remote_elem non-const and create
1180  // non-const versions of the family_tree methods
1181  for (auto & const_elem : family)
1182  {
1183  Elem * n = const_cast<Elem *>(const_elem);
1184  libmesh_assert (n);
1185  if (n == remote_elem)
1186  continue;
1187  unsigned int my_s = n->which_neighbor_am_i(this);
1188  libmesh_assert_less (my_s, n->n_neighbors());
1189  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1190  n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1191  }
1192 #else
1193  unsigned int my_s = neigh->which_neighbor_am_i(this);
1194  libmesh_assert_less (my_s, neigh->n_neighbors());
1195  libmesh_assert_equal_to (neigh->neighbor_ptr(my_s), this);
1196  neigh->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1197 #endif
1198  }
1199 #ifdef LIBMESH_ENABLE_AMR
1200  // Even if my neighbor doesn't link back to me, it might
1201  // have subactive descendants which do
1202  else if (neigh->has_children())
1203  {
1204  // If my neighbor at the same level doesn't have me as a
1205  // neighbor, I must be subactive
1206  libmesh_assert(this->level() > neigh->level() ||
1207  this->subactive());
1208 
1209  // My neighbor must have some ancestor of mine as a
1210  // neighbor
1211  Elem * my_ancestor = this->parent();
1212  libmesh_assert(my_ancestor);
1213  while (!neigh->has_neighbor(my_ancestor))
1214  {
1215  my_ancestor = my_ancestor->parent();
1216  libmesh_assert(my_ancestor);
1217  }
1218 
1219  // My neighbor may have descendants which consider me a
1220  // neighbor
1221  std::vector<const Elem *> family;
1222  neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
1223 
1224  // FIXME - There's a lot of ugly const_casts here; we
1225  // may want to make remote_elem non-const and create
1226  // non-const versions of the family_tree methods
1227  for (auto & const_elem : family)
1228  {
1229  Elem * n = const_cast<Elem *>(const_elem);
1230  libmesh_assert (n);
1231  if (n == remote_elem)
1232  continue;
1233  unsigned int my_s = n->which_neighbor_am_i(this);
1234  libmesh_assert_less (my_s, n->n_neighbors());
1235  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1236  n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1237  }
1238  }
1239 #endif
1240  }
1241  }
1242 
1243 #ifdef LIBMESH_ENABLE_AMR
1244  // Remotify parent's child link
1245  Elem * my_parent = this->parent();
1246  if (my_parent &&
1247  // As long as it's not already remote
1248  my_parent != remote_elem &&
1249  // And it's a real parent, not an interior parent
1250  this->dim() == my_parent->dim())
1251  {
1252  unsigned int me = my_parent->which_child_am_i(this);
1253  libmesh_assert_equal_to (my_parent->child_ptr(me), this);
1254  my_parent->set_child(me, const_cast<RemoteElem *>(remote_elem));
1255  }
1256 #endif
1257 }
1258 
1259 
1261 {
1262  libmesh_assert_not_equal_to (this, remote_elem);
1263 
1264  // We need to have handled any children first
1265 #ifdef LIBMESH_ENABLE_AMR
1266  libmesh_assert (!this->has_children());
1267 #endif
1268 
1269  // Nullify any neighbor links
1270  for (auto neigh : this->neighbor_ptr_range())
1271  {
1272  if (neigh && neigh != remote_elem)
1273  {
1274  // My neighbor should never be more refined than me; my real
1275  // neighbor would have been its parent in that case.
1276  libmesh_assert_greater_equal (this->level(), neigh->level());
1277 
1278  if (this->level() == neigh->level() &&
1279  neigh->has_neighbor(this))
1280  {
1281 #ifdef LIBMESH_ENABLE_AMR
1282  // My neighbor may have descendants which also consider me a
1283  // neighbor
1284  std::vector<const Elem *> family;
1285  neigh->total_family_tree_by_neighbor (family, this);
1286 
1287  // FIXME - There's a lot of ugly const_casts here; we
1288  // may want to make remote_elem non-const and create
1289  // non-const versions of the family_tree methods
1290  for (auto & const_elem : family)
1291  {
1292  Elem * n = const_cast<Elem *>(const_elem);
1293  libmesh_assert (n);
1294  if (n == remote_elem)
1295  continue;
1296  unsigned int my_s = n->which_neighbor_am_i(this);
1297  libmesh_assert_less (my_s, n->n_neighbors());
1298  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1299  n->set_neighbor(my_s, nullptr);
1300  }
1301 #else
1302  unsigned int my_s = neigh->which_neighbor_am_i(this);
1303  libmesh_assert_less (my_s, neigh->n_neighbors());
1304  libmesh_assert_equal_to (neigh->neighbor(my_s), this);
1305  neigh->set_neighbor(my_s, nullptr);
1306 #endif
1307  }
1308 #ifdef LIBMESH_ENABLE_AMR
1309  // Even if my neighbor doesn't link back to me, it might
1310  // have subactive descendants which do
1311  else if (neigh->has_children())
1312  {
1313  // If my neighbor at the same level doesn't have me as a
1314  // neighbor, I must be subactive
1315  libmesh_assert(this->level() > neigh->level() ||
1316  this->subactive());
1317 
1318  // My neighbor must have some ancestor of mine as a
1319  // neighbor
1320  Elem * my_ancestor = this->parent();
1321  libmesh_assert(my_ancestor);
1322  while (!neigh->has_neighbor(my_ancestor))
1323  {
1324  my_ancestor = my_ancestor->parent();
1325  libmesh_assert(my_ancestor);
1326  }
1327 
1328  // My neighbor may have descendants which consider me a
1329  // neighbor
1330  std::vector<const Elem *> family;
1331  neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
1332 
1333  // FIXME - There's a lot of ugly const_casts here; we
1334  // may want to make remote_elem non-const and create
1335  // non-const versions of the family_tree methods
1336  for (auto & const_elem : family)
1337  {
1338  Elem * n = const_cast<Elem *>(const_elem);
1339  libmesh_assert (n);
1340  if (n == remote_elem)
1341  continue;
1342  unsigned int my_s = n->which_neighbor_am_i(this);
1343  libmesh_assert_less (my_s, n->n_neighbors());
1344  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1345  n->set_neighbor(my_s, nullptr);
1346  }
1347  }
1348 #endif
1349  }
1350  }
1351 
1352 #ifdef LIBMESH_ENABLE_AMR
1353  // We can't currently delete a child with a parent!
1354  libmesh_assert (!this->parent());
1355 #endif
1356 }
1357 
1358 
1359 
1360 void Elem::write_connectivity (std::ostream & out_stream,
1361  const IOPackage iop) const
1362 {
1363  libmesh_assert (out_stream.good());
1364  libmesh_assert(_nodes);
1365  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
1366 
1367  switch (iop)
1368  {
1369  case TECPLOT:
1370  {
1371  // This connectivity vector will be used repeatedly instead
1372  // of being reconstructed inside the loop.
1373  std::vector<dof_id_type> conn;
1374  for (unsigned int sc=0; sc <this->n_sub_elem(); sc++)
1375  {
1376  this->connectivity(sc, TECPLOT, conn);
1377 
1378  std::copy(conn.begin(),
1379  conn.end(),
1380  std::ostream_iterator<dof_id_type>(out_stream, " "));
1381 
1382  out_stream << '\n';
1383  }
1384  return;
1385  }
1386 
1387  case UCD:
1388  {
1389  for (auto i : this->node_index_range())
1390  out_stream << this->node_id(i)+1 << "\t";
1391 
1392  out_stream << '\n';
1393  return;
1394  }
1395 
1396  default:
1397  libmesh_error_msg("Unsupported IO package " << iop);
1398  }
1399 }
1400 
1401 
1402 
1404 {
1405  switch (q)
1406  {
1410  default:
1411  {
1412  libmesh_do_once( libmesh_here();
1413 
1414  libMesh::err << "ERROR: unknown quality metric: "
1416  << std::endl
1417  << "Cowardly returning 1."
1418  << std::endl; );
1419 
1420  return 1.;
1421  }
1422  }
1423 }
1424 
1425 
1426 
1427 bool Elem::ancestor() const
1428 {
1429 #ifdef LIBMESH_ENABLE_AMR
1430 
1431  // Use a fast, DistributedMesh-safe definition
1432  const bool is_ancestor =
1433  !this->active() && !this->subactive();
1434 
1435  // But check for inconsistencies if we have time
1436 #ifdef DEBUG
1437  if (!is_ancestor && this->has_children())
1438  {
1439  for (auto & c : this->child_ref_range())
1440  {
1441  if (&c != remote_elem)
1442  {
1443  libmesh_assert(!c.active());
1444  libmesh_assert(!c.ancestor());
1445  }
1446  }
1447  }
1448 #endif // DEBUG
1449 
1450  return is_ancestor;
1451 
1452 #else
1453  return false;
1454 #endif
1455 }
1456 
1457 
1458 
1459 #ifdef LIBMESH_ENABLE_AMR
1460 
1461 void Elem::add_child (Elem * elem)
1462 {
1463  const unsigned int nc = this->n_children();
1464 
1465  if (_children == nullptr)
1466  {
1467  _children = new Elem *[nc];
1468 
1469  for (unsigned int c = 0; c != nc; c++)
1470  this->set_child(c, nullptr);
1471  }
1472 
1473  for (unsigned int c = 0; c != nc; c++)
1474  {
1475  if (this->_children[c] == nullptr || this->_children[c] == remote_elem)
1476  {
1477  libmesh_assert_equal_to (this, elem->parent());
1478  this->set_child(c, elem);
1479  return;
1480  }
1481  }
1482 
1483  libmesh_error_msg("Error: Tried to add a child to an element with full children array");
1484 }
1485 
1486 
1487 
1488 void Elem::add_child (Elem * elem, unsigned int c)
1489 {
1490  if (!this->has_children())
1491  {
1492  const unsigned int nc = this->n_children();
1493  _children = new Elem *[nc];
1494 
1495  for (unsigned int i = 0; i != nc; i++)
1496  this->set_child(i, nullptr);
1497  }
1498 
1499  libmesh_assert (this->_children[c] == nullptr || this->child_ptr(c) == remote_elem);
1500  libmesh_assert (elem == remote_elem || this == elem->parent());
1501 
1502  this->set_child(c, elem);
1503 }
1504 
1505 
1506 
1507 void Elem::replace_child (Elem * elem, unsigned int c)
1508 {
1509  libmesh_assert(this->has_children());
1510 
1511  libmesh_assert(this->child_ptr(c));
1512 
1513  this->set_child(c, elem);
1514 }
1515 
1516 
1517 
1518 bool Elem::is_child_on_edge(const unsigned int libmesh_dbg_var(c),
1519  const unsigned int e) const
1520 {
1521  libmesh_assert_less (c, this->n_children());
1522  libmesh_assert_less (e, this->n_edges());
1523 
1524  std::unique_ptr<const Elem> my_edge = this->build_edge_ptr(e);
1525  std::unique_ptr<const Elem> child_edge = this->build_edge_ptr(e);
1526 
1527  // We're assuming that an overlapping child edge has the same
1528  // number and orientation as its parent
1529  return (child_edge->node_id(0) == my_edge->node_id(0) ||
1530  child_edge->node_id(1) == my_edge->node_id(1));
1531 }
1532 
1533 
1534 void Elem::family_tree (std::vector<const Elem *> & family,
1535  const bool reset) const
1536 {
1537  // The "family tree" doesn't include subactive elements
1538  libmesh_assert(!this->subactive());
1539 
1540  // Clear the vector if the flag reset tells us to.
1541  if (reset)
1542  family.clear();
1543 
1544  // Add this element to the family tree.
1545  family.push_back(this);
1546 
1547  // Recurse into the elements children, if it has them.
1548  // Do not clear the vector any more.
1549  if (!this->active())
1550  for (auto & c : this->child_ref_range())
1551  if (!c.is_remote())
1552  c.family_tree (family, false);
1553 }
1554 
1555 
1556 
1557 void Elem::total_family_tree (std::vector<const Elem *> & family,
1558  const bool reset) const
1559 {
1560  // Clear the vector if the flag reset tells us to.
1561  if (reset)
1562  family.clear();
1563 
1564  // Add this element to the family tree.
1565  family.push_back(this);
1566 
1567  // Recurse into the elements children, if it has them.
1568  // Do not clear the vector any more.
1569  if (this->has_children())
1570  for (auto & c : this->child_ref_range())
1571  if (!c.is_remote())
1572  c.total_family_tree (family, false);
1573 }
1574 
1575 
1576 
1577 void Elem::active_family_tree (std::vector<const Elem *> & active_family,
1578  const bool reset) const
1579 {
1580  // The "family tree" doesn't include subactive elements
1581  libmesh_assert(!this->subactive());
1582 
1583  // Clear the vector if the flag reset tells us to.
1584  if (reset)
1585  active_family.clear();
1586 
1587  // Add this element to the family tree if it is active
1588  if (this->active())
1589  active_family.push_back(this);
1590 
1591  // Otherwise recurse into the element's children.
1592  // Do not clear the vector any more.
1593  else
1594  for (auto & c : this->child_ref_range())
1595  if (!c.is_remote())
1596  c.active_family_tree (active_family, false);
1597 }
1598 
1599 
1600 
1601 void Elem::family_tree_by_side (std::vector<const Elem *> & family,
1602  const unsigned int s,
1603  const bool reset) const
1604 {
1605  // The "family tree" doesn't include subactive elements
1606  libmesh_assert(!this->subactive());
1607 
1608  // Clear the vector if the flag reset tells us to.
1609  if (reset)
1610  family.clear();
1611 
1612  libmesh_assert_less (s, this->n_sides());
1613 
1614  // Add this element to the family tree.
1615  family.push_back(this);
1616 
1617  // Recurse into the elements children, if it has them.
1618  // Do not clear the vector any more.
1619  if (!this->active())
1620  {
1621  const unsigned int nc = this->n_children();
1622  for (unsigned int c = 0; c != nc; c++)
1623  if (!this->child_ptr(c)->is_remote() && this->is_child_on_side(c, s))
1624  this->child_ptr(c)->family_tree_by_side (family, s, false);
1625  }
1626 }
1627 
1628 
1629 
1630 void Elem::active_family_tree_by_side (std::vector<const Elem *> & family,
1631  const unsigned int s,
1632  const bool reset) const
1633 {
1634  // The "family tree" doesn't include subactive or remote elements
1635  libmesh_assert(!this->subactive());
1636  libmesh_assert(this != remote_elem);
1637 
1638  // Clear the vector if the flag reset tells us to.
1639  if (reset)
1640  family.clear();
1641 
1642  libmesh_assert_less (s, this->n_sides());
1643 
1644  // Add an active element to the family tree.
1645  if (this->active())
1646  family.push_back(this);
1647 
1648  // Or recurse into an ancestor element's children.
1649  // Do not clear the vector any more.
1650  else
1651  {
1652  const unsigned int nc = this->n_children();
1653  for (unsigned int c = 0; c != nc; c++)
1654  if (!this->child_ptr(c)->is_remote() && this->is_child_on_side(c, s))
1655  this->child_ptr(c)->active_family_tree_by_side (family, s, false);
1656  }
1657 }
1658 
1659 
1660 
1661 void Elem::family_tree_by_neighbor (std::vector<const Elem *> & family,
1662  const Elem * neighbor_in,
1663  const bool reset) const
1664 {
1665  // The "family tree" doesn't include subactive elements
1666  libmesh_assert(!this->subactive());
1667 
1668  // Clear the vector if the flag reset tells us to.
1669  if (reset)
1670  family.clear();
1671 
1672  // This only makes sense if we're already a neighbor
1673  libmesh_assert (this->has_neighbor(neighbor_in));
1674 
1675  // Add this element to the family tree.
1676  family.push_back(this);
1677 
1678  // Recurse into the elements children, if it's not active.
1679  // Do not clear the vector any more.
1680  if (!this->active())
1681  for (auto & c : this->child_ref_range())
1682  if (&c != remote_elem && c.has_neighbor(neighbor_in))
1683  c.family_tree_by_neighbor (family, neighbor_in, false);
1684 }
1685 
1686 
1687 
1688 void Elem::total_family_tree_by_neighbor (std::vector<const Elem *> & family,
1689  const Elem * neighbor_in,
1690  const bool reset) const
1691 {
1692  // Clear the vector if the flag reset tells us to.
1693  if (reset)
1694  family.clear();
1695 
1696  // This only makes sense if we're already a neighbor
1697  libmesh_assert (this->has_neighbor(neighbor_in));
1698 
1699  // Add this element to the family tree.
1700  family.push_back(this);
1701 
1702  // Recurse into the elements children, if it has any.
1703  // Do not clear the vector any more.
1704  if (this->has_children())
1705  for (auto & c : this->child_ref_range())
1706  if (&c != remote_elem && c.has_neighbor(neighbor_in))
1707  c.total_family_tree_by_neighbor (family, neighbor_in, false);
1708 }
1709 
1710 
1711 
1712 void Elem::family_tree_by_subneighbor (std::vector<const Elem *> & family,
1713  const Elem * neighbor_in,
1714  const Elem * subneighbor,
1715  const bool reset) const
1716 {
1717  // The "family tree" doesn't include subactive elements
1718  libmesh_assert(!this->subactive());
1719 
1720  // Clear the vector if the flag reset tells us to.
1721  if (reset)
1722  family.clear();
1723 
1724  // To simplify this function we need an existing neighbor
1725  libmesh_assert (neighbor_in);
1726  libmesh_assert_not_equal_to (neighbor_in, remote_elem);
1727  libmesh_assert (this->has_neighbor(neighbor_in));
1728 
1729  // This only makes sense if subneighbor descends from neighbor
1730  libmesh_assert (subneighbor);
1731  libmesh_assert_not_equal_to (subneighbor, remote_elem);
1732  libmesh_assert (neighbor_in->is_ancestor_of(subneighbor));
1733 
1734  // Add this element to the family tree if applicable.
1735  if (neighbor_in == subneighbor)
1736  family.push_back(this);
1737 
1738  // Recurse into the elements children, if it's not active.
1739  // Do not clear the vector any more.
1740  if (!this->active())
1741  for (auto & c : this->child_ref_range())
1742  if (&c != remote_elem)
1743  for (auto child_neigh : c.neighbor_ptr_range())
1744  if (child_neigh &&
1745  (child_neigh == neighbor_in ||
1746  (child_neigh->parent() == neighbor_in &&
1747  child_neigh->is_ancestor_of(subneighbor))))
1748  c.family_tree_by_subneighbor (family, child_neigh,
1749  subneighbor, false);
1750 }
1751 
1752 
1753 
1754 void Elem::total_family_tree_by_subneighbor (std::vector<const Elem *> & family,
1755  const Elem * neighbor_in,
1756  const Elem * subneighbor,
1757  const bool reset) const
1758 {
1759  // Clear the vector if the flag reset tells us to.
1760  if (reset)
1761  family.clear();
1762 
1763  // To simplify this function we need an existing neighbor
1764  libmesh_assert (neighbor_in);
1765  libmesh_assert_not_equal_to (neighbor_in, remote_elem);
1766  libmesh_assert (this->has_neighbor(neighbor_in));
1767 
1768  // This only makes sense if subneighbor descends from neighbor
1769  libmesh_assert (subneighbor);
1770  libmesh_assert_not_equal_to (subneighbor, remote_elem);
1771  libmesh_assert (neighbor_in->is_ancestor_of(subneighbor));
1772 
1773  // Add this element to the family tree if applicable.
1774  if (neighbor_in == subneighbor)
1775  family.push_back(this);
1776 
1777  // Recurse into the elements children, if it has any.
1778  // Do not clear the vector any more.
1779  if (this->has_children())
1780  for (auto & c : this->child_ref_range())
1781  if (&c != remote_elem)
1782  for (auto child_neigh : c.neighbor_ptr_range())
1783  if (child_neigh &&
1784  (child_neigh == neighbor_in ||
1785  (child_neigh->parent() == neighbor_in &&
1786  child_neigh->is_ancestor_of(subneighbor))))
1787  c.total_family_tree_by_subneighbor
1788  (family, child_neigh, subneighbor, false);
1789 }
1790 
1791 
1792 
1793 void
1794 Elem::
1795 active_family_tree_by_topological_neighbor(std::vector<const Elem *> & family,
1796  const Elem * neighbor_in,
1797  const MeshBase & mesh,
1798  const PointLocatorBase & point_locator,
1799  const PeriodicBoundaries * pb,
1800  const bool reset) const
1801 {
1802  // The "family tree" doesn't include subactive elements or
1803  // remote_elements
1804  libmesh_assert(!this->subactive());
1805  libmesh_assert(this != remote_elem);
1806 
1807  // Clear the vector if the flag reset tells us to.
1808  if (reset)
1809  family.clear();
1810 
1811  // This only makes sense if we're already a topological neighbor
1812 #ifndef NDEBUG
1813  if (this->level() >= neighbor_in->level())
1814  libmesh_assert (this->has_topological_neighbor(neighbor_in,
1815  mesh,
1816  point_locator,
1817  pb));
1818 #endif
1819 
1820  // Add an active element to the family tree.
1821  if (this->active())
1822  family.push_back(this);
1823 
1824  // Or recurse into an ancestor element's children.
1825  // Do not clear the vector any more.
1826  else if (!this->active())
1827  for (auto & c : this->child_ref_range())
1828  if (&c != remote_elem &&
1829  c.has_topological_neighbor(neighbor_in, mesh, point_locator,
1830  pb))
1831  c.active_family_tree_by_topological_neighbor
1832  (family, neighbor_in, mesh, point_locator, pb, false);
1833 }
1834 
1835 
1836 
1837 void Elem::active_family_tree_by_neighbor (std::vector<const Elem *> & family,
1838  const Elem * neighbor_in,
1839  const bool reset) const
1840 {
1841  // The "family tree" doesn't include subactive elements or
1842  // remote_elements
1843  libmesh_assert(!this->subactive());
1844  libmesh_assert(this != remote_elem);
1845 
1846  // Clear the vector if the flag reset tells us to.
1847  if (reset)
1848  family.clear();
1849 
1850  // This only makes sense if we're already a neighbor
1851 #ifndef NDEBUG
1852  if (this->level() >= neighbor_in->level())
1853  libmesh_assert (this->has_neighbor(neighbor_in));
1854 #endif
1855 
1856  // Add an active element to the family tree.
1857  if (this->active())
1858  family.push_back(this);
1859 
1860  // Or recurse into an ancestor element's children.
1861  // Do not clear the vector any more.
1862  else if (!this->active())
1863  for (auto & c : this->child_ref_range())
1864  if (&c != remote_elem && c.has_neighbor(neighbor_in))
1865  c.active_family_tree_by_neighbor (family, neighbor_in, false);
1866 }
1867 
1868 
1869 
1870 unsigned int Elem::min_p_level_by_neighbor(const Elem * neighbor_in,
1871  unsigned int current_min) const
1872 {
1873  libmesh_assert(!this->subactive());
1874  libmesh_assert(neighbor_in->active());
1875 
1876  // If we're an active element this is simple
1877  if (this->active())
1878  return std::min(current_min, this->p_level());
1879 
1880  libmesh_assert(has_neighbor(neighbor_in));
1881 
1882  // The p_level() of an ancestor element is already the minimum
1883  // p_level() of its children - so if that's high enough, we don't
1884  // need to examine any children.
1885  if (current_min <= this->p_level())
1886  return current_min;
1887 
1888  unsigned int min_p_level = current_min;
1889 
1890  for (auto & c : this->child_ref_range())
1891  if (&c != remote_elem && c.has_neighbor(neighbor_in))
1892  min_p_level =
1893  c.min_p_level_by_neighbor(neighbor_in, min_p_level);
1894 
1895  return min_p_level;
1896 }
1897 
1898 
1899 unsigned int Elem::min_new_p_level_by_neighbor(const Elem * neighbor_in,
1900  unsigned int current_min) const
1901 {
1902  libmesh_assert(!this->subactive());
1903  libmesh_assert(neighbor_in->active());
1904 
1905  // If we're an active element this is simple
1906  if (this->active())
1907  {
1908  unsigned int new_p_level = this->p_level();
1909  if (this->p_refinement_flag() == Elem::REFINE)
1910  new_p_level += 1;
1911  if (this->p_refinement_flag() == Elem::COARSEN)
1912  {
1913  libmesh_assert_greater (new_p_level, 0);
1914  new_p_level -= 1;
1915  }
1916  return std::min(current_min, new_p_level);
1917  }
1918 
1919  libmesh_assert(has_neighbor(neighbor_in));
1920 
1921  unsigned int min_p_level = current_min;
1922 
1923  for (auto & c : this->child_ref_range())
1924  if (&c != remote_elem && c.has_neighbor(neighbor_in))
1925  min_p_level =
1926  c.min_new_p_level_by_neighbor(neighbor_in, min_p_level);
1927 
1928  return min_p_level;
1929 }
1930 
1931 
1932 
1933 unsigned int Elem::as_parent_node (unsigned int child,
1934  unsigned int child_node) const
1935 {
1936  const unsigned int nc = this->n_children();
1937  libmesh_assert_less(child, nc);
1938 
1939  // Cached return values, indexed first by embedding_matrix version,
1940  // then by child number, then by child node number.
1941  std::vector<std::vector<std::vector<signed char>>> &
1942  cached_parent_indices = this->_get_parent_indices_cache();
1943 
1944  unsigned int em_vers = this->embedding_matrix_version();
1945 
1946  // We may be updating the cache on one thread, and while that
1947  // happens we can't safely access the cache from other threads.
1948  Threads::spin_mutex::scoped_lock lock(parent_indices_mutex);
1949 
1950  if (em_vers >= cached_parent_indices.size())
1951  cached_parent_indices.resize(em_vers+1);
1952 
1953  if (child >= cached_parent_indices[em_vers].size())
1954  {
1955  const signed char nn = cast_int<signed char>(this->n_nodes());
1956 
1957  cached_parent_indices[em_vers].resize(nc);
1958 
1959  for (unsigned int c = 0; c != nc; ++c)
1960  {
1961  const unsigned int ncn = this->n_nodes_in_child(c);
1962  cached_parent_indices[em_vers][c].resize(ncn);
1963  for (unsigned int cn = 0; cn != ncn; ++cn)
1964  {
1965  for (signed char n = 0; n != nn; ++n)
1966  {
1967  const float em_val = this->embedding_matrix
1968  (c, cn, n);
1969  if (em_val == 1)
1970  {
1971  cached_parent_indices[em_vers][c][cn] = n;
1972  break;
1973  }
1974 
1975  if (em_val != 0)
1976  {
1977  cached_parent_indices[em_vers][c][cn] =
1978  -1;
1979  break;
1980  }
1981 
1982  // We should never see an all-zero embedding matrix
1983  // row
1984  libmesh_assert_not_equal_to (n+1, nn);
1985  }
1986  }
1987  }
1988  }
1989 
1990  const signed char cache_val =
1991  cached_parent_indices[em_vers][child][child_node];
1992  if (cache_val == -1)
1993  return libMesh::invalid_uint;
1994 
1995  return cached_parent_indices[em_vers][child][child_node];
1996 }
1997 
1998 
1999 
2000 const std::vector<std::pair<unsigned char, unsigned char>> &
2002  unsigned int child_node) const
2003 {
2004  // Indexed first by embedding matrix type, then by child id, then by
2005  // child node, then by bracketing pair
2006  std::vector<std::vector<std::vector<std::vector<std::pair<unsigned char, unsigned char>>>>> &
2007  cached_bracketing_nodes = this->_get_bracketing_node_cache();
2008 
2009  const unsigned int em_vers = this->embedding_matrix_version();
2010 
2011  // We may be updating the cache on one thread, and while that
2012  // happens we can't safely access the cache from other threads.
2013  Threads::spin_mutex::scoped_lock lock(parent_bracketing_nodes_mutex);
2014 
2015  if (cached_bracketing_nodes.size() <= em_vers)
2016  cached_bracketing_nodes.resize(em_vers+1);
2017 
2018  const unsigned int nc = this->n_children();
2019 
2020  // If we haven't cached the bracketing nodes corresponding to this
2021  // embedding matrix yet, let's do so now.
2022  if (cached_bracketing_nodes[em_vers].size() < nc)
2023  {
2024  // If we're a second-order element but we're not a full-order
2025  // element, then some of our bracketing nodes may not exist
2026  // except on the equivalent full-order element. Let's build an
2027  // equivalent full-order element and make a copy of its cache to
2028  // use.
2029  if (this->default_order() != FIRST &&
2030  second_order_equivalent_type(this->type(), /*full_ordered=*/ true) != this->type())
2031  {
2032  // Check that we really are the non-full-order type
2033  libmesh_assert_equal_to
2034  (second_order_equivalent_type (this->type(), false),
2035  this->type());
2036 
2037  // Build the full-order type
2038  ElemType full_type =
2039  second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
2040  std::unique_ptr<Elem> full_elem = Elem::build(full_type);
2041 
2042  // This won't work for elements with multiple
2043  // embedding_matrix versions, but every such element is full
2044  // order anyways.
2045  libmesh_assert_equal_to(em_vers, 0);
2046 
2047  // Make sure its cache has been built. We temporarily
2048  // release our mutex lock so that the inner call can
2049  // re-acquire it.
2050  lock.release();
2051  full_elem->parent_bracketing_nodes(0,0);
2052 
2053  // And then we need to lock again, so that if someone *else*
2054  // grabbed our lock before we did we don't risk accessing
2055  // cached_bracketing_nodes while they're working on it.
2056  // Threading is hard.
2057  lock.acquire(parent_bracketing_nodes_mutex);
2058 
2059  // Copy its cache
2060  cached_bracketing_nodes =
2061  full_elem->_get_bracketing_node_cache();
2062 
2063  // Now we don't need to build the cache ourselves.
2064  return cached_bracketing_nodes[em_vers][child][child_node];
2065  }
2066 
2067  cached_bracketing_nodes[em_vers].resize(nc);
2068 
2069  const unsigned int nn = this->n_nodes();
2070 
2071  // We have to examine each child
2072  for (unsigned int c = 0; c != nc; ++c)
2073  {
2074  const unsigned int ncn = this->n_nodes_in_child(c);
2075 
2076  cached_bracketing_nodes[em_vers][c].resize(ncn);
2077 
2078  // We have to examine each node in that child
2079  for (unsigned int n = 0; n != ncn; ++n)
2080  {
2081  // If this child node isn't a vertex or an infinite
2082  // child element's mid-infinite-edge node, then we need
2083  // to find bracketing nodes on the child.
2084  if (!this->is_vertex_on_child(c, n)
2085 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2086  && !this->is_mid_infinite_edge_node(n)
2087 #endif
2088  )
2089  {
2090  // Use the embedding matrix to find the child node
2091  // location in parent master element space
2092  Point bracketed_pt;
2093 
2094  for (unsigned int pn = 0; pn != nn; ++pn)
2095  {
2096  const float em_val =
2097  this->embedding_matrix(c,n,pn);
2098 
2099  libmesh_assert_not_equal_to (em_val, 1);
2100  if (em_val != 0.)
2101  bracketed_pt.add_scaled(this->master_point(pn), em_val);
2102  }
2103 
2104  // Check each pair of nodes on the child which are
2105  // also both parent nodes
2106  for (unsigned int n1 = 0; n1 != ncn; ++n1)
2107  {
2108  if (n1 == n)
2109  continue;
2110 
2111  unsigned int parent_n1 =
2112  this->as_parent_node(c,n1);
2113 
2114  if (parent_n1 == libMesh::invalid_uint)
2115  continue;
2116 
2117  Point p1 = this->master_point(parent_n1);
2118 
2119  for (unsigned int n2 = n1+1; n2 < nn; ++n2)
2120  {
2121  if (n2 == n)
2122  continue;
2123 
2124  unsigned int parent_n2 =
2125  this->as_parent_node(c,n2);
2126 
2127  if (parent_n2 == libMesh::invalid_uint)
2128  continue;
2129 
2130  Point p2 = this->master_point(parent_n2);
2131 
2132  Point pmid = (p1 + p2)/2;
2133 
2134  if (pmid == bracketed_pt)
2135  {
2136  cached_bracketing_nodes[em_vers][c][n].push_back
2137  (std::make_pair(parent_n1,parent_n2));
2138  break;
2139  }
2140  else
2141  libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
2142  }
2143  }
2144  }
2145  // If this child node is a parent node, we need to
2146  // find bracketing nodes on the parent.
2147  else
2148  {
2149  unsigned int parent_node = this->as_parent_node(c,n);
2150 
2151  Point bracketed_pt;
2152 
2153  // If we're not a parent node, use the embedding
2154  // matrix to find the child node location in parent
2155  // master element space
2156  if (parent_node == libMesh::invalid_uint)
2157  {
2158  for (unsigned int pn = 0; pn != nn; ++pn)
2159  {
2160  const float em_val =
2161  this->embedding_matrix(c,n,pn);
2162 
2163  libmesh_assert_not_equal_to (em_val, 1);
2164  if (em_val != 0.)
2165  bracketed_pt.add_scaled(this->master_point(pn), em_val);
2166  }
2167  }
2168  // If we're a parent node then we need no arithmetic
2169  else
2170  bracketed_pt = this->master_point(parent_node);
2171 
2172  for (unsigned int n1 = 0; n1 != nn; ++n1)
2173  {
2174  if (n1 == parent_node)
2175  continue;
2176 
2177  Point p1 = this->master_point(n1);
2178 
2179  for (unsigned int n2 = n1+1; n2 < nn; ++n2)
2180  {
2181  if (n2 == parent_node)
2182  continue;
2183 
2184  Point pmid = (p1 + this->master_point(n2))/2;
2185 
2186  if (pmid == bracketed_pt)
2187  {
2188  cached_bracketing_nodes[em_vers][c][n].push_back
2189  (std::make_pair(n1,n2));
2190  break;
2191  }
2192  else
2193  libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
2194  }
2195  }
2196  }
2197  }
2198  }
2199  }
2200 
2201  return cached_bracketing_nodes[em_vers][child][child_node];
2202 }
2203 
2204 
2205 const std::vector<std::pair<dof_id_type, dof_id_type>>
2206 Elem::bracketing_nodes(unsigned int child,
2207  unsigned int child_node) const
2208 {
2209  std::vector<std::pair<dof_id_type, dof_id_type>> returnval;
2210 
2211  const std::vector<std::pair<unsigned char, unsigned char>> & pbc =
2212  this->parent_bracketing_nodes(child,child_node);
2213 
2214  for (const auto & pb : pbc)
2215  {
2216  const unsigned short n_n = this->n_nodes();
2217  if (pb.first < n_n && pb.second < n_n)
2218  returnval.push_back(std::make_pair(this->node_id(pb.first),
2219  this->node_id(pb.second)));
2220  else
2221  {
2222  // We must be on a non-full-order higher order element...
2223  libmesh_assert_not_equal_to(this->default_order(), FIRST);
2224  libmesh_assert_not_equal_to
2225  (second_order_equivalent_type (this->type(), true),
2226  this->type());
2227  libmesh_assert_equal_to
2228  (second_order_equivalent_type (this->type(), false),
2229  this->type());
2230 
2231  // And that's a shame, because this is a nasty search:
2232 
2233  // Build the full-order type
2234  ElemType full_type =
2235  second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
2236  std::unique_ptr<Elem> full_elem = Elem::build(full_type);
2237 
2240 
2241  // Find the bracketing nodes by figuring out what
2242  // already-created children will have them.
2243 
2244  // This only doesn't break horribly because we add children
2245  // and nodes in straightforward + hierarchical orders...
2246  for (unsigned int c=0; c <= child; ++c)
2247  for (unsigned int n=0; n != this->n_nodes_in_child(c); ++n)
2248  {
2249  if (c == child && n == child_node)
2250  break;
2251 
2252  if (pb.first == full_elem->as_parent_node(c,n))
2253  {
2254  // We should be consistent
2255  if (pt1 != DofObject::invalid_id)
2256  libmesh_assert_equal_to(pt1, this->child_ptr(c)->node_id(n));
2257 
2258  pt1 = this->child_ptr(c)->node_id(n);
2259  }
2260 
2261  if (pb.second == full_elem->as_parent_node(c,n))
2262  {
2263  // We should be consistent
2264  if (pt2 != DofObject::invalid_id)
2265  libmesh_assert_equal_to(pt2, this->child_ptr(c)->node_id(n));
2266 
2267  pt2 = this->child_ptr(c)->node_id(n);
2268  }
2269  }
2270 
2271  // We should *usually* find all bracketing nodes by the time
2272  // we query them (again, because of the child & node add
2273  // order)
2274  //
2275  // The exception is if we're a HEX20, in which case we will
2276  // find pairs of vertex nodes and edge nodes bracketing the
2277  // new central node but we *won't* find the pairs of face
2278  // nodes which we would have had on a HEX27. In that case
2279  // we'll still have enough bracketing nodes for a
2280  // topological lookup, but we won't be able to make the
2281  // following assertions.
2282  if (this->type() != HEX20)
2283  {
2284  libmesh_assert_not_equal_to (pt1, DofObject::invalid_id);
2285  libmesh_assert_not_equal_to (pt2, DofObject::invalid_id);
2286  }
2287 
2288  if (pt1 != DofObject::invalid_id &&
2289  pt2 != DofObject::invalid_id)
2290  returnval.push_back(std::make_pair(pt1, pt2));
2291  }
2292  }
2293 
2294  return returnval;
2295 }
2296 #endif // #ifdef LIBMESH_ENABLE_AMR
2297 
2298 
2299 
2300 
2301 bool Elem::contains_point (const Point & p, Real tol) const
2302 {
2303  // We currently allow the user to enlarge the bounding box by
2304  // providing a tol > TOLERANCE (so this routine is identical to
2305  // Elem::close_to_point()), but print a warning so that the
2306  // user can eventually switch his code over to calling close_to_point()
2307  // instead, which is intended to be used for this purpose.
2308  if (tol > TOLERANCE)
2309  {
2310  libmesh_do_once(libMesh::err
2311  << "WARNING: Resizing bounding box to match user-specified tolerance!\n"
2312  << "In the future, calls to Elem::contains_point() with tol > TOLERANCE\n"
2313  << "will be more optimized, but should not be used\n"
2314  << "to search for points 'close to' elements!\n"
2315  << "Instead, use Elem::close_to_point() for this purpose.\n"
2316  << std::endl;);
2317  return this->point_test(p, tol, tol);
2318  }
2319  else
2320  return this->point_test(p, TOLERANCE, tol);
2321 }
2322 
2323 
2324 
2325 
2326 bool Elem::close_to_point (const Point & p, Real tol) const
2327 {
2328  // This test uses the user's passed-in tolerance for the
2329  // bounding box test as well, thereby allowing the routine to
2330  // find points which are not only "in" the element, but also
2331  // "nearby" to within some tolerance.
2332  return this->point_test(p, tol, tol);
2333 }
2334 
2335 
2336 
2337 
2338 bool Elem::point_test(const Point & p, Real box_tol, Real map_tol) const
2339 {
2340  libmesh_assert_greater (box_tol, 0.);
2341  libmesh_assert_greater (map_tol, 0.);
2342 
2343  // This is a great optimization on first order elements, but it
2344  // could return false negatives on higher orders
2345  if (this->default_order() == FIRST)
2346  {
2347  // Check to make sure the element *could* contain this point, so we
2348  // can avoid an expensive inverse_map call if it doesn't.
2349  bool
2350 #if LIBMESH_DIM > 2
2351  point_above_min_z = false,
2352  point_below_max_z = false,
2353 #endif
2354 #if LIBMESH_DIM > 1
2355  point_above_min_y = false,
2356  point_below_max_y = false,
2357 #endif
2358  point_above_min_x = false,
2359  point_below_max_x = false;
2360 
2361  // For relative bounding box checks in physical space
2362  const Real my_hmax = this->hmax();
2363 
2364  for (auto & n : this->node_ref_range())
2365  {
2366  point_above_min_x = point_above_min_x || (n(0) - my_hmax*box_tol <= p(0));
2367  point_below_max_x = point_below_max_x || (n(0) + my_hmax*box_tol >= p(0));
2368 #if LIBMESH_DIM > 1
2369  point_above_min_y = point_above_min_y || (n(1) - my_hmax*box_tol <= p(1));
2370  point_below_max_y = point_below_max_y || (n(1) + my_hmax*box_tol >= p(1));
2371 #endif
2372 #if LIBMESH_DIM > 2
2373  point_above_min_z = point_above_min_z || (n(2) - my_hmax*box_tol <= p(2));
2374  point_below_max_z = point_below_max_z || (n(2) + my_hmax*box_tol >= p(2));
2375 #endif
2376  }
2377 
2378  if (
2379 #if LIBMESH_DIM > 2
2380  !point_above_min_z ||
2381  !point_below_max_z ||
2382 #endif
2383 #if LIBMESH_DIM > 1
2384  !point_above_min_y ||
2385  !point_below_max_y ||
2386 #endif
2387  !point_above_min_x ||
2388  !point_below_max_x)
2389  return false;
2390  }
2391 
2392  // Declare a basic FEType. Will be a Lagrange
2393  // element by default.
2394  FEType fe_type(this->default_order());
2395 
2396  // To be on the safe side, we converge the inverse_map() iteration
2397  // to a slightly tighter tolerance than that requested by the
2398  // user...
2399  const Point mapped_point = FEInterface::inverse_map(this->dim(),
2400  fe_type,
2401  this,
2402  p,
2403  0.1*map_tol, // <- this is |dx| tolerance, the Newton residual should be ~ |dx|^2
2404  /*secure=*/ false);
2405 
2406  // Check that the refspace point maps back to p! This is only necessary
2407  // for 1D and 2D elements, 3D elements always live in 3D.
2408  //
2409  // TODO: The contains_point() function could most likely be implemented
2410  // more efficiently in the element sub-classes themselves, at least for
2411  // the linear element types.
2412  if (this->dim() < 3)
2413  {
2414  Point xyz = FEInterface::map(this->dim(),
2415  fe_type,
2416  this,
2417  mapped_point);
2418 
2419  // Compute the distance between the original point and the re-mapped point.
2420  // They should be in the same place.
2421  Real dist = (xyz - p).norm();
2422 
2423 
2424  // If dist is larger than some fraction of the tolerance, then return false.
2425  // This can happen when e.g. a 2D element is living in 3D, and
2426  // FEInterface::inverse_map() maps p onto the projection of the element,
2427  // effectively "tricking" FEInterface::on_reference_element().
2428  if (dist > this->hmax() * map_tol)
2429  return false;
2430  }
2431 
2432 
2433 
2434  return FEInterface::on_reference_element(mapped_point, this->type(), map_tol);
2435 }
2436 
2437 
2438 
2439 
2440 void Elem::print_info (std::ostream & os) const
2441 {
2442  os << this->get_info()
2443  << std::endl;
2444 }
2445 
2446 
2447 
2448 std::string Elem::get_info () const
2449 {
2450  std::ostringstream oss;
2451 
2452  oss << " Elem Information" << '\n'
2453  << " id()=";
2454 
2455  if (this->valid_id())
2456  oss << this->id();
2457  else
2458  oss << "invalid";
2459 
2460 #ifdef LIBMESH_ENABLE_UNIQUE_ID
2461  oss << ", unique_id()=";
2462  if (this->valid_unique_id())
2463  oss << this->unique_id();
2464  else
2465  oss << "invalid";
2466 #endif
2467 
2468  oss << ", processor_id()=" << this->processor_id() << '\n';
2469 
2470  oss << " type()=" << Utility::enum_to_string(this->type()) << '\n'
2471  << " dim()=" << this->dim() << '\n'
2472  << " n_nodes()=" << this->n_nodes() << '\n';
2473 
2474  for (unsigned int n=0; n != this->n_nodes(); ++n)
2475  oss << " " << n << this->node_ref(n);
2476 
2477  oss << " n_sides()=" << this->n_sides() << '\n';
2478 
2479  for (unsigned int s=0; s != this->n_sides(); ++s)
2480  {
2481  oss << " neighbor(" << s << ")=";
2482  if (this->neighbor_ptr(s))
2483  oss << this->neighbor_ptr(s)->id() << '\n';
2484  else
2485  oss << "nullptr\n";
2486  }
2487 
2488 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2489  if (!this->infinite())
2490  {
2491 #endif
2492  oss << " hmin()=" << this->hmin()
2493  << ", hmax()=" << this->hmax() << '\n'
2494  << " volume()=" << this->volume() << '\n';
2495 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2496  }
2497 #endif
2498  oss << " active()=" << this->active()
2499  << ", ancestor()=" << this->ancestor()
2500  << ", subactive()=" << this->subactive()
2501  << ", has_children()=" << this->has_children() << '\n'
2502  << " parent()=";
2503  if (this->parent())
2504  oss << this->parent()->id() << '\n';
2505  else
2506  oss << "nullptr\n";
2507  oss << " level()=" << this->level()
2508  << ", p_level()=" << this->p_level() << '\n'
2509 #ifdef LIBMESH_ENABLE_AMR
2510  << " refinement_flag()=" << Utility::enum_to_string(this->refinement_flag()) << '\n'
2511  << " p_refinement_flag()=" << Utility::enum_to_string(this->p_refinement_flag()) << '\n'
2512 #endif
2513 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2514  << " infinite()=" << this->infinite() << '\n';
2515  if (this->infinite())
2516  oss << " origin()=" << this->origin() << '\n'
2517 #endif
2518  ;
2519 
2520  oss << " DoFs=";
2521  for (unsigned int s=0; s != this->n_systems(); ++s)
2522  for (unsigned int v=0; v != this->n_vars(s); ++v)
2523  for (unsigned int c=0; c != this->n_comp(s,v); ++c)
2524  oss << '(' << s << '/' << v << '/' << this->dof_number(s,v,c) << ") ";
2525 
2526 
2527  return oss.str();
2528 }
2529 
2530 
2531 
2533 {
2534  // Tell any of my neighbors about my death...
2535  // Looks strange, huh?
2536  for (auto n : this->side_index_range())
2537  {
2538  Elem * current_neighbor = this->neighbor_ptr(n);
2539  if (current_neighbor && current_neighbor != remote_elem)
2540  {
2541  // Note: it is possible that I see the neighbor
2542  // (which is coarser than me)
2543  // but they don't see me, so avoid that case.
2544  if (current_neighbor->level() == this->level())
2545  {
2546  const unsigned int w_n_a_i = current_neighbor->which_neighbor_am_i(this);
2547  libmesh_assert_less (w_n_a_i, current_neighbor->n_neighbors());
2548  current_neighbor->set_neighbor(w_n_a_i, nullptr);
2549  this->set_neighbor(n, nullptr);
2550  }
2551  }
2552  }
2553 }
2554 
2555 
2556 
2557 
2558 unsigned int Elem::n_second_order_adjacent_vertices (const unsigned int) const
2559 {
2560  // for linear elements, always return 0
2561  return 0;
2562 }
2563 
2564 
2565 
2566 unsigned short int Elem::second_order_adjacent_vertex (const unsigned int,
2567  const unsigned int) const
2568 {
2569  // for linear elements, always return 0
2570  return 0;
2571 }
2572 
2573 
2574 
2575 std::pair<unsigned short int, unsigned short int>
2576 Elem::second_order_child_vertex (const unsigned int) const
2577 {
2578  // for linear elements, always return 0
2579  return std::pair<unsigned short int, unsigned short int>(0,0);
2580 }
2581 
2582 
2583 
2585 {
2586  switch (et)
2587  {
2588  case EDGE2:
2589  case EDGE3:
2590  case EDGE4:
2591  return EDGE2;
2592  case TRI3:
2593  case TRI6:
2594  return TRI3;
2595  case TRISHELL3:
2596  return TRISHELL3;
2597  case QUAD4:
2598  case QUAD8:
2599  case QUAD9:
2600  return QUAD4;
2601  case QUADSHELL4:
2602  case QUADSHELL8:
2603  return QUADSHELL4;
2604  case TET4:
2605  case TET10:
2606  return TET4;
2607  case HEX8:
2608  case HEX27:
2609  case HEX20:
2610  return HEX8;
2611  case PRISM6:
2612  case PRISM15:
2613  case PRISM18:
2614  return PRISM6;
2615  case PYRAMID5:
2616  case PYRAMID13:
2617  case PYRAMID14:
2618  return PYRAMID5;
2619 
2620 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2621 
2622  case INFQUAD4:
2623  case INFQUAD6:
2624  return INFQUAD4;
2625  case INFHEX8:
2626  case INFHEX16:
2627  case INFHEX18:
2628  return INFHEX8;
2629  case INFPRISM6:
2630  case INFPRISM12:
2631  return INFPRISM6;
2632 
2633 #endif
2634 
2635  default:
2636  // unknown element
2637  return INVALID_ELEM;
2638  }
2639 }
2640 
2641 
2642 
2644  const bool full_ordered)
2645 {
2646  /* for second-order elements, always return \p INVALID_ELEM
2647  * since second-order elements should not be converted
2648  * into something else. Only linear elements should
2649  * return something sensible here
2650  */
2651  switch (et)
2652  {
2653  case EDGE2:
2654  case EDGE3:
2655  {
2656  // full_ordered not relevant
2657  return EDGE3;
2658  }
2659 
2660  case EDGE4:
2661  {
2662  // full_ordered not relevant
2663  return EDGE4;
2664  }
2665 
2666  case TRI3:
2667  case TRI6:
2668  {
2669  // full_ordered not relevant
2670  return TRI6;
2671  }
2672 
2673  case QUAD4:
2674  case QUAD8:
2675  {
2676  if (full_ordered)
2677  return QUAD9;
2678  else
2679  return QUAD8;
2680  }
2681 
2682  case QUADSHELL4:
2683  case QUADSHELL8:
2684  {
2685  if (full_ordered)
2686  libmesh_error();
2687  else
2688  return QUADSHELL8;
2689  }
2690 
2691  case QUAD9:
2692  {
2693  // full_ordered not relevant
2694  return QUAD9;
2695  }
2696 
2697  case TET4:
2698  case TET10:
2699  {
2700  // full_ordered not relevant
2701  return TET10;
2702  }
2703 
2704  case HEX8:
2705  case HEX20:
2706  {
2707  // see below how this correlates with INFHEX8
2708  if (full_ordered)
2709  return HEX27;
2710  else
2711  return HEX20;
2712  }
2713 
2714  case HEX27:
2715  {
2716  // full_ordered not relevant
2717  return HEX27;
2718  }
2719 
2720  case PRISM6:
2721  case PRISM15:
2722  {
2723  if (full_ordered)
2724  return PRISM18;
2725  else
2726  return PRISM15;
2727  }
2728 
2729  case PRISM18:
2730  {
2731  // full_ordered not relevant
2732  return PRISM18;
2733  }
2734 
2735  case PYRAMID5:
2736  case PYRAMID13:
2737  {
2738  if (full_ordered)
2739  return PYRAMID14;
2740  else
2741  return PYRAMID13;
2742  }
2743 
2744  case PYRAMID14:
2745  {
2746  // full_ordered not relevant
2747  return PYRAMID14;
2748  }
2749 
2750 
2751 
2752 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2753 
2754  // infinite elements
2755  case INFEDGE2:
2756  {
2757  return INVALID_ELEM;
2758  }
2759 
2760  case INFQUAD4:
2761  case INFQUAD6:
2762  {
2763  // full_ordered not relevant
2764  return INFQUAD6;
2765  }
2766 
2767  case INFHEX8:
2768  case INFHEX16:
2769  {
2770  /*
2771  * Note that this matches with \p Hex8:
2772  * For full-ordered, \p InfHex18 and \p Hex27
2773  * belong together, and for not full-ordered,
2774  * \p InfHex16 and \p Hex20 belong together.
2775  */
2776  if (full_ordered)
2777  return INFHEX18;
2778  else
2779  return INFHEX16;
2780  }
2781 
2782  case INFHEX18:
2783  {
2784  // full_ordered not relevant
2785  return INFHEX18;
2786  }
2787 
2788  case INFPRISM6:
2789  case INFPRISM12:
2790  {
2791  // full_ordered not relevant
2792  return INFPRISM12;
2793  }
2794 
2795 #endif
2796 
2797 
2798  default:
2799  {
2800  // what did we miss?
2801  libmesh_error();
2802  }
2803  }
2804 }
2805 
2806 
2807 
2809 {
2811  return side_iterator(this->_first_side(), this->_last_side(), bsp);
2812 }
2813 
2814 
2815 
2816 
2818 {
2820  return side_iterator(this->_last_side(), this->_last_side(), bsp);
2821 }
2822 
2823 
2824 
2825 
2827 {
2828  // The default implementation builds a finite element of the correct
2829  // order and sums up the JxW contributions. This can be expensive,
2830  // so the various element types can overload this method and compute
2831  // the volume more efficiently.
2832  FEType fe_type (this->default_order() , LAGRANGE);
2833 
2834  std::unique_ptr<FEBase> fe (FEBase::build(this->dim(),
2835  fe_type));
2836 
2837  const std::vector<Real> & JxW = fe->get_JxW();
2838 
2839  // The default quadrature rule should integrate the mass matrix,
2840  // thus it should be plenty to compute the area
2841  QGauss qrule (this->dim(), fe_type.default_quadrature_order());
2842 
2843  fe->attach_quadrature_rule(&qrule);
2844 
2845  fe->reinit(this);
2846 
2847  Real vol=0.;
2848  for (unsigned int qp=0; qp<qrule.n_points(); ++qp)
2849  vol += JxW[qp];
2850 
2851  return vol;
2852 
2853 }
2854 
2855 
2856 
2858 {
2859  Point pmin = this->point(0);
2860  Point pmax = pmin;
2861 
2862  unsigned int n_points = this->n_nodes();
2863  for (unsigned int p=0; p != n_points; ++p)
2864  for (unsigned d=0; d<LIBMESH_DIM; ++d)
2865  {
2866  const Point & pt = this->point(p);
2867  if (pmin(d) > pt(d))
2868  pmin(d) = pt(d);
2869 
2870  if (pmax(d) < pt(d))
2871  pmax(d) = pt(d);
2872  }
2873 
2874  return BoundingBox(pmin, pmax);
2875 }
2876 
2877 
2878 
2879 bool Elem::is_vertex_on_parent(unsigned int c,
2880  unsigned int n) const
2881 {
2882 #ifdef LIBMESH_ENABLE_AMR
2883 
2884  unsigned int my_n_vertices = this->n_vertices();
2885  for (unsigned int n_parent = 0; n_parent != my_n_vertices;
2886  ++n_parent)
2887  if (this->node_ptr(n_parent) == this->child_ptr(c)->node_ptr(n))
2888  return true;
2889  return false;
2890 
2891 #else
2892 
2893  // No AMR?
2894  libmesh_ignore(c,n);
2895  libmesh_error_msg("ERROR: AMR disabled, how did we get here?");
2896  return true;
2897 
2898 #endif
2899 }
2900 
2901 
2902 
2903 unsigned int Elem::opposite_side(const unsigned int /*s*/) const
2904 {
2905  // If the subclass didn't rederive this, using it is an error
2906  libmesh_not_implemented();
2907 }
2908 
2909 
2910 
2911 unsigned int Elem::opposite_node(const unsigned int /*n*/,
2912  const unsigned int /*s*/) const
2913 {
2914  // If the subclass didn't rederive this, using it is an error
2915  libmesh_not_implemented();
2916 }
2917 
2918 } // namespace libMesh
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:179
void total_family_tree_by_subneighbor(std::vector< const Elem *> &family, const Elem *neighbor, const Elem *subneighbor, const bool reset=true) const
Definition: elem.C:1754
bool has_neighbor(const Elem *elem) const
Definition: elem.h:2093
virtual bool is_vertex_on_parent(unsigned int c, unsigned int n) const
Definition: elem.C:2879
static Point map(unsigned int dim, const FEType &fe_t, const Elem *elem, const Point &p)
Definition: fe_interface.C:574
RefinementState refinement_flag() const
Definition: elem.h:2638
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:833
void write_connectivity(std::ostream &out, const IOPackage iop) const
Definition: elem.C:1360
const Elem * parent() const
Definition: elem.h:2479
virtual const std::vector< std::pair< dof_id_type, dof_id_type > > bracketing_nodes(unsigned int c, unsigned int n) const
Definition: elem.C:2206
void print_info(std::ostream &os=libMesh::out) const
Definition: elem.C:2440
bool is_ancestor_of(const Elem *descendant) const
Definition: elem.h:2458
Node ** _nodes
Definition: elem.h:1695
void family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, const bool reset=true) const
Definition: elem.C:1661
virtual Point origin() const
Definition: elem.h:1553
const unsigned int invalid_uint
Definition: libmesh.h:245
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:803
std::string get_info() const
Definition: elem.C:2448
static const unsigned int type_to_n_sides_map[INVALID_ELEM]
Definition: elem.h:620
const Elem * interior_parent() const
Definition: elem.C:804
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:920
bool is_semilocal(const processor_id_type my_pid) const
Definition: elem.C:451
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2166
void libmesh_assert_valid_node_pointers() const
Definition: elem.C:978
virtual dof_id_type key() const
Definition: elem.C:401
void add_scaled(const TypeVector< T2 > &, const T)
Definition: type_vector.h:627
Maps between boundary ids and PeriodicBoundaryBase objects.
virtual unsigned int embedding_matrix_version() const
Definition: elem.h:1609
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const =0
RefinementState p_refinement_flag() const
Definition: elem.h:2654
void find_interior_neighbors(std::set< const Elem *> &neighbor_set) const
Definition: elem.C:725
Threads::spin_mutex parent_indices_mutex
Definition: elem.C:85
The base class for all geometric element types.
Definition: elem.h:100
MeshBase & mesh
uint8_t processor_id_type
Definition: id_types.h:99
PeriodicBoundaryBase * boundary(boundary_id_type id)
void add_child(Elem *elem)
Definition: elem.C:1461
virtual BoundingBox loose_bounding_box() const
Definition: elem.C:2857
unsigned int min_new_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
Definition: elem.C:1899
virtual float embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
unique_id_type unique_id() const
Definition: dof_object.h:672
Order default_quadrature_order() const
Definition: fe_type.h:333
virtual unsigned int n_children() const =0
unsigned int p_level() const
Definition: elem.h:2555
void find_edge_neighbors(const Point &p1, const Point &p2, std::set< const Elem *> &neighbor_set) const
Definition: elem.C:637
side_iterator boundary_sides_end()
Definition: elem.C:2817
static const Real TOLERANCE
IterBase * end
void active_family_tree(std::vector< const Elem *> &active_family, const bool reset=true) const
Definition: elem.C:1577
void active_family_tree_by_topological_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb, const bool reset=true) const
Definition: elem.C:1795
void make_links_to_me_remote()
Definition: elem.C:1149
virtual Real hmax() const
Definition: elem.C:373
long double max(long double a, double b)
unsigned int min_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
Definition: elem.C:1870
void set_interior_parent(Elem *p)
Definition: elem.C:856
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
Definition: elem.h:589
void total_family_tree(std::vector< const Elem *> &active_family, const bool reset=true) const
Definition: elem.C:1557
Base class for Mesh.
Definition: mesh_base.h:77
SimpleRange< ChildRefIter > child_ref_range()
Definition: elem.h:1779
void family_tree_by_side(std::vector< const Elem *> &family, const unsigned int side, const bool reset=true) const
Definition: elem.C:1601
void add(const TypeVector< T2 > &)
Definition: type_vector.h:603
bool ancestor() const
Definition: elem.C:1427
bool has_topological_neighbor(const Elem *elem, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:957
side_iterator boundary_sides_begin()
Definition: elem.C:2808
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval=0)
Definition: hashword.h:153
void total_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, const bool reset=true) const
Definition: elem.C:1688
void replace_child(Elem *elem, unsigned int c)
Definition: elem.C:1507
void libmesh_ignore(const Args &...)
static const subdomain_id_type invalid_subdomain_id
Definition: elem.h:262
void remove_links_to_me()
Definition: elem.C:1260
virtual std::vector< std::vector< std::vector< signed char > > > & _get_parent_indices_cache() const
Definition: elem.h:1673
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
Definition: elem.C:2301
Real length(const unsigned int n1, const unsigned int n2) const
Definition: elem.C:390
void active_family_tree_by_side(std::vector< const Elem *> &family, const unsigned int side, const bool reset=true) const
Definition: elem.C:1630
const Node & node_ref(const unsigned int i) const
Definition: elem.h:1979
dof_id_type id() const
Definition: dof_object.h:655
virtual Real hmin() const
Definition: elem.C:356
virtual unsigned int n_nodes() const =0
static const unsigned int type_to_n_edges_map[INVALID_ELEM]
Definition: elem.h:669
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:768
bool contains_edge_of(const Elem *e) const
Definition: elem.C:477
unsigned int which_neighbor_am_i(const Elem *e) const
Definition: elem.h:2314
virtual unsigned int as_parent_node(unsigned int c, unsigned int n) const
Definition: elem.C:1933
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:245
unsigned int n_systems() const
Definition: dof_object.h:749
virtual unsigned int opposite_node(const unsigned int n, const unsigned int s) const
Definition: elem.C:2911
virtual std::pair< unsigned short int, unsigned short int > second_order_child_vertex(const unsigned int n) const
Definition: elem.C:2576
Elem ** _elemlinks
Definition: elem.h:1701
void find_point_neighbors(const Point &p, std::set< const Elem *> &neighbor_set) const
Definition: elem.C:498
Elem ** _children
Definition: elem.h:1707
bool point_test(const Point &p, Real box_tol, Real map_tol) const
Definition: elem.C:2338
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
void family_tree(std::vector< const Elem *> &family, const bool reset=true) const
Definition: elem.C:1534
static const dof_id_type invalid_id
Definition: dof_object.h:347
Threads::spin_mutex parent_bracketing_nodes_mutex
Definition: elem.C:86
const Elem * reference_elem() const
Definition: elem.C:337
static Point inverse_map(const unsigned int dim, const FEType &fe_t, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true)
Definition: fe_interface.C:590
void libmesh_assert_valid_neighbors() const
Definition: elem.C:990
virtual bool is_remote() const
Definition: elem.h:555
bool valid_unique_id() const
Definition: dof_object.h:705
OStreamProxy err(std::cerr)
virtual unsigned int n_edges() const =0
virtual unsigned int n_second_order_adjacent_vertices(const unsigned int n) const
Definition: elem.C:2558
SideIter _last_side()
Definition: elem.h:2963
bool absolute_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
Definition: type_vector.h:965
void set_neighbor(const unsigned int i, Elem *n)
Definition: elem.h:2083
static bool on_reference_element(const Point &p, const ElemType t, const Real eps=TOLERANCE)
Definition: fe_interface.C:647
static ElemType second_order_equivalent_type(const ElemType et, const bool full_ordered=true)
Definition: elem.C:2643
unsigned int which_child_am_i(const Elem *e) const
Definition: elem.h:2620
bool contains_vertex_of(const Elem *e) const
Definition: elem.C:466
std::string enum_to_string(const T e)
void active_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, const bool reset=true) const
Definition: elem.C:1837
Elem * child(const unsigned int i) const
Definition: elem.h:2598
SimpleRange< NodeRefIter > node_ref_range()
Definition: elem.h:2130
virtual unsigned int is_vertex_on_child(unsigned int, unsigned int n) const
Definition: elem.h:694
virtual unsigned int n_sides() const =0
Real norm_sq() const
Definition: type_vector.h:943
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2050
virtual bool close_to_point(const Point &p, Real tol) const
Definition: elem.C:2326
unsigned int level() const
Definition: elem.h:2521
virtual unsigned int n_vertices() const =0
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual std::unique_ptr< Elem > side_ptr(unsigned int i)=0
bool valid_id() const
Definition: dof_object.h:697
const Elem * neighbor(boundary_id_type boundary_id, const PointLocatorBase &point_locator, const Elem *e, unsigned int side) const
virtual unsigned short dim() const =0
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:1957
virtual Point master_point(const unsigned int i) const =0
unsigned int n_neighbors() const
Definition: elem.h:644
virtual Real quality(const ElemQuality q) const
Definition: elem.C:1403
virtual unsigned short int second_order_adjacent_vertex(const unsigned int n, const unsigned int v) const
Definition: elem.C:2566
bool subactive() const
Definition: elem.h:2408
virtual Real volume() const
Definition: elem.C:2826
Implements 1, 2, and 3D "Gaussian" quadrature rules.
void set_child(unsigned int c, Elem *elem)
Definition: elem.h:2610
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const =0
IntRange< unsigned short > node_index_range() const
Definition: elem.h:2148
void nullify_neighbors()
Definition: elem.C:2532
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Definition: elem.h:2988
virtual bool infinite() const =0
virtual unsigned int n_sub_elem() const =0
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i)=0
void make_links_to_me_local(unsigned int n)
Definition: elem.C:1062
virtual Order default_order() const =0
virtual const std::vector< std::pair< unsigned char, unsigned char > > & parent_bracketing_nodes(unsigned int c, unsigned int n) const
Definition: elem.C:2001
virtual std::vector< std::vector< std::vector< std::vector< std::pair< unsigned char, unsigned char > > > > > & _get_bracketing_node_cache() const
Definition: elem.h:1659
virtual unsigned int opposite_side(const unsigned int s) const
Definition: elem.C:2903
bool active() const
Definition: elem.h:2390
static ElemType first_order_equivalent_type(const ElemType et)
Definition: elem.C:2584
processor_id_type processor_id() const
Definition: dof_object.h:717
virtual ElemType type() const =0
long double min(long double a, double b)
A geometric point in (x,y,z) space.
Definition: point.h:38
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1914
const Point & point(const unsigned int i) const
Definition: elem.h:1892
virtual Point centroid() const
Definition: elem.C:344
bool operator==(const Elem &rhs) const
Definition: elem.C:419
bool has_children() const
Definition: elem.h:2428
virtual bool is_child_on_edge(const unsigned int c, const unsigned int e) const
Definition: elem.C:1518
const Elem & get(const ElemType type_in)
virtual unsigned int n_nodes_in_child(unsigned int) const
Definition: elem.h:613
static const unsigned int max_n_nodes
Definition: elem.h:600
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:2578
uint8_t dof_id_type
Definition: id_types.h:64
void family_tree_by_subneighbor(std::vector< const Elem *> &family, const Elem *neighbor, const Elem *subneighbor, const bool reset=true) const
Definition: elem.C:1712
virtual bool is_mid_infinite_edge_node(const unsigned int) const
Definition: elem.h:1544
SideIter _first_side()
Definition: elem.h:2955
const RemoteElem * remote_elem
Definition: remote_elem.C:57