libMesh
elem.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 // Local includes
20 #include "libmesh/elem.h"
21 
22 #include "libmesh/boundary_info.h"
23 #include "libmesh/fe_type.h"
24 #include "libmesh/fe_interface.h"
25 #include "libmesh/node_elem.h"
26 #include "libmesh/edge_edge2.h"
27 #include "libmesh/edge_edge3.h"
28 #include "libmesh/edge_edge4.h"
29 #include "libmesh/edge_inf_edge2.h"
30 #include "libmesh/face_c0polygon.h"
31 #include "libmesh/face_tri3.h"
32 #include "libmesh/face_tri3_subdivision.h"
33 #include "libmesh/face_tri3_shell.h"
34 #include "libmesh/face_tri6.h"
35 #include "libmesh/face_tri7.h"
36 #include "libmesh/face_quad4.h"
37 #include "libmesh/face_quad4_shell.h"
38 #include "libmesh/face_quad8.h"
39 #include "libmesh/face_quad8_shell.h"
40 #include "libmesh/face_quad9.h"
41 #include "libmesh/face_quad9_shell.h"
42 #include "libmesh/face_inf_quad4.h"
43 #include "libmesh/face_inf_quad6.h"
44 #include "libmesh/cell_tet4.h"
45 #include "libmesh/cell_tet10.h"
46 #include "libmesh/cell_tet14.h"
47 #include "libmesh/cell_hex8.h"
48 #include "libmesh/cell_hex20.h"
49 #include "libmesh/cell_hex27.h"
50 #include "libmesh/cell_inf_hex8.h"
51 #include "libmesh/cell_inf_hex16.h"
52 #include "libmesh/cell_inf_hex18.h"
53 #include "libmesh/cell_prism6.h"
54 #include "libmesh/cell_prism15.h"
55 #include "libmesh/cell_prism18.h"
56 #include "libmesh/cell_prism20.h"
57 #include "libmesh/cell_prism21.h"
58 #include "libmesh/cell_inf_prism6.h"
59 #include "libmesh/cell_inf_prism12.h"
60 #include "libmesh/cell_pyramid5.h"
61 #include "libmesh/cell_pyramid13.h"
62 #include "libmesh/cell_pyramid14.h"
63 #include "libmesh/cell_pyramid18.h"
64 #include "libmesh/fe_base.h"
65 #include "libmesh/mesh_base.h"
66 #include "libmesh/quadrature_nodal.h"
67 #include "libmesh/quadrature_gauss.h"
68 #include "libmesh/remote_elem.h"
69 #include "libmesh/reference_elem.h"
70 #include "libmesh/enum_to_string.h"
71 #include "libmesh/threads.h"
72 #include "libmesh/enum_elem_quality.h"
73 #include "libmesh/enum_io_package.h"
74 #include "libmesh/enum_order.h"
75 #include "libmesh/elem_internal.h"
76 
77 #ifdef LIBMESH_ENABLE_PERIODIC
78 #include "libmesh/mesh.h"
79 #include "libmesh/periodic_boundaries.h"
80 #endif
81 
82 
83 // C++ includes
84 #include <algorithm> // for std::sort
85 #include <array>
86 #include <iterator> // for std::ostream_iterator
87 #include <sstream>
88 #include <limits> // for std::numeric_limits<>
89 #include <cmath> // for std::sqrt()
90 #include <memory>
91 #include <regex> // for exceptions in volume()
92 
93 
94 namespace libMesh
95 {
96 
99 
100 // Initialize static member variables
101 const unsigned int Elem::type_to_dim_map [] =
102  {
103  1, // EDGE2
104  1, // EDGE3
105  1, // EDGE4
106 
107  2, // TRI3
108  2, // TRI6
109 
110  2, // QUAD4
111  2, // QUAD8
112  2, // QUAD9
113 
114  3, // TET4
115  3, // TET10
116 
117  3, // HEX8
118  3, // HEX20
119  3, // HEX27
120 
121  3, // PRISM6
122  3, // PRISM15
123  3, // PRISM18
124 
125  3, // PYRAMID5
126  3, // PYRAMID13
127  3, // PYRAMID14
128 
129  1, // INFEDGE2
130 
131  2, // INFQUAD4
132  2, // INFQUAD6
133 
134  3, // INFHEX8
135  3, // INFHEX16
136  3, // INFHEX18
137 
138  3, // INFPRISM6
139  3, // INFPRISM12
140 
141  0, // NODEELEM
142 
143  0, // REMOTEELEM
144 
145  2, // TRI3SUBDIVISION
146  2, // TRISHELL3
147  2, // QUADSHELL4
148  2, // QUADSHELL8
149 
150  2, // TRI7
151  3, // TET14
152  3, // PRISM20
153  3, // PRISM21
154  3, // PYRAMID18
155 
156  2, // QUADSHELL9
157 
158  2, // C0POLYGON
159  3, // C0POLYHEDRON
160  };
161 
162 const unsigned int Elem::max_n_nodes;
163 
164 const unsigned int Elem::type_to_n_nodes_map [] =
165  {
166  2, // EDGE2
167  3, // EDGE3
168  4, // EDGE4
169 
170  3, // TRI3
171  6, // TRI6
172 
173  4, // QUAD4
174  8, // QUAD8
175  9, // QUAD9
176 
177  4, // TET4
178  10, // TET10
179 
180  8, // HEX8
181  20, // HEX20
182  27, // HEX27
183 
184  6, // PRISM6
185  15, // PRISM15
186  18, // PRISM18
187 
188  5, // PYRAMID5
189  13, // PYRAMID13
190  14, // PYRAMID14
191 
192  2, // INFEDGE2
193 
194  4, // INFQUAD4
195  6, // INFQUAD6
196 
197  8, // INFHEX8
198  16, // INFHEX16
199  18, // INFHEX18
200 
201  6, // INFPRISM6
202  12, // INFPRISM12
203 
204  1, // NODEELEM
205 
206  0, // REMOTEELEM
207 
208  3, // TRI3SUBDIVISION
209  3, // TRISHELL3
210  4, // QUADSHELL4
211  8, // QUADSHELL8
212 
213  7, // TRI7
214  14, // TET14
215  20, // PRISM20
216  21, // PRISM21
217  18, // PYRAMID18
218 
219  9, // QUADSHELL9
220 
221  invalid_uint, // C0POLYGON
222  invalid_uint, // C0POLYHEDRON
223  };
224 
225 const unsigned int Elem::type_to_n_sides_map [] =
226  {
227  2, // EDGE2
228  2, // EDGE3
229  2, // EDGE4
230 
231  3, // TRI3
232  3, // TRI6
233 
234  4, // QUAD4
235  4, // QUAD8
236  4, // QUAD9
237 
238  4, // TET4
239  4, // TET10
240 
241  6, // HEX8
242  6, // HEX20
243  6, // HEX27
244 
245  5, // PRISM6
246  5, // PRISM15
247  5, // PRISM18
248 
249  5, // PYRAMID5
250  5, // PYRAMID13
251  5, // PYRAMID14
252 
253  2, // INFEDGE2
254 
255  3, // INFQUAD4
256  3, // INFQUAD6
257 
258  5, // INFHEX8
259  5, // INFHEX16
260  5, // INFHEX18
261 
262  4, // INFPRISM6
263  4, // INFPRISM12
264 
265  0, // NODEELEM
266 
267  0, // REMOTEELEM
268 
269  3, // TRI3SUBDIVISION
270  3, // TRISHELL3
271  4, // QUADSHELL4
272  4, // QUADSHELL8
273 
274  3, // TRI7
275  4, // TET14
276  5, // PRISM20
277  5, // PRISM21
278  5, // PYRAMID18
279 
280  4, // QUADSHELL9
281 
282  invalid_uint, // C0POLYGON
283  invalid_uint, // C0POLYHEDRON
284  };
285 
286 const unsigned int Elem::type_to_n_edges_map [] =
287  {
288  0, // EDGE2
289  0, // EDGE3
290  0, // EDGE4
291 
292  3, // TRI3
293  3, // TRI6
294 
295  4, // QUAD4
296  4, // QUAD8
297  4, // QUAD9
298 
299  6, // TET4
300  6, // TET10
301 
302  12, // HEX8
303  12, // HEX20
304  12, // HEX27
305 
306  9, // PRISM6
307  9, // PRISM15
308  9, // PRISM18
309 
310  8, // PYRAMID5
311  8, // PYRAMID13
312  8, // PYRAMID14
313 
314  0, // INFEDGE2
315 
316  3, // INFQUAD4
317  3, // INFQUAD6
318 
319  8, // INFHEX8
320  8, // INFHEX16
321  8, // INFHEX18
322 
323  6, // INFPRISM6
324  6, // INFPRISM12
325 
326  0, // NODEELEM
327 
328  0, // REMOTEELEM
329 
330  3, // TRI3SUBDIVISION
331  3, // TRISHELL3
332  4, // QUADSHELL4
333  4, // QUADSHELL8
334 
335  3, // TRI7
336  6, // TET14
337  9, // PRISM20
338  9, // PRISM21
339  8, // PYRAMID18
340 
341  4, // QUADSHELL9
342 
343  invalid_uint, // C0POLYGON
344  invalid_uint, // C0POLYHEDRON
345  };
346 
348  {
349  FIRST, // EDGE2
350  SECOND, // EDGE3
351  THIRD, // EDGE4
352 
353  FIRST, // TRI3
354  SECOND, // TRI6
355 
356  FIRST, // QUAD4
357  SECOND, // QUAD8
358  SECOND, // QUAD9
359 
360  FIRST, // TET4
361  SECOND, // TET10
362 
363  FIRST, // HEX8
364  SECOND, // HEX20
365  SECOND, // HEX27
366 
367  FIRST, // PRISM6
368  SECOND, // PRISM15
369  SECOND, // PRISM18
370 
371  FIRST, // PYRAMID5
372  SECOND, // PYRAMID13
373  SECOND, // PYRAMID14
374 
375  FIRST, // INFEDGE2
376 
377  FIRST, // INFQUAD4
378  SECOND, // INFQUAD6
379 
380  FIRST, // INFHEX8
381  SECOND, // INFHEX16
382  SECOND, // INFHEX18
383 
384  FIRST, // INFPRISM6
385  SECOND, // INFPRISM12
386 
387  CONSTANT, // NODEELEM
388 
389  INVALID_ORDER, // REMOTEELEM
390 
391  FIRST, // TRI3SUBDIVISION
392  FIRST, // TRISHELL3
393  FIRST, // QUADSHELL4
394  SECOND, // QUADSHELL8
395 
396  THIRD, // TRI7
397  THIRD, // TET14
398  THIRD, // PRISM20
399  THIRD, // PRISM21
400  THIRD, // PYRAMID18
401 
402  SECOND, // QUADSHELL9
403 
404  FIRST, // C0POLYGON
405  FIRST, // C0POLYHEDRON
406  };
407 
408 // ------------------------------------------------------------
409 // Elem class member functions
410 std::unique_ptr<Elem> Elem::disconnected_clone() const
411 {
412  std::unique_ptr<Elem> returnval;
413 
414  switch (this->type())
415  {
416  case C0POLYGON:
417  returnval = std::make_unique<C0Polygon>(this->n_sides());
418  break;
419 
420  default:
421  returnval = Elem::build(this->type());
422  }
423 
424  returnval->set_id() = this->id();
425 #ifdef LIBMESH_ENABLE_UNIQUE_ID
426  if (this->valid_unique_id())
427  returnval->set_unique_id(this->unique_id());
428 #endif
429 
430  const auto n_elem_ints = this->n_extra_integers();
431  returnval->add_extra_integers(n_elem_ints);
432  for (unsigned int i = 0; i != n_elem_ints; ++i)
433  returnval->set_extra_integer(i, this->get_extra_integer(i));
434 
435  returnval->inherit_data_from(*this);
436 
437  return returnval;
438 }
439 
440 
441 
442 std::unique_ptr<Elem> Elem::build(const ElemType type,
443  Elem * p)
444 {
445  switch (type)
446  {
447  // 0D elements
448  case NODEELEM:
449  return std::make_unique<NodeElem>(p);
450 
451  // 1D elements
452  case EDGE2:
453  return std::make_unique<Edge2>(p);
454  case EDGE3:
455  return std::make_unique<Edge3>(p);
456  case EDGE4:
457  return std::make_unique<Edge4>(p);
458 
459  // 2D elements
460  case TRI3:
461  return std::make_unique<Tri3>(p);
462  case TRISHELL3:
463  return std::make_unique<TriShell3>(p);
464  case TRI3SUBDIVISION:
465  return std::make_unique<Tri3Subdivision>(p);
466  case TRI6:
467  return std::make_unique<Tri6>(p);
468  case TRI7:
469  return std::make_unique<Tri7>(p);
470  case QUAD4:
471  return std::make_unique<Quad4>(p);
472  case QUADSHELL4:
473  return std::make_unique<QuadShell4>(p);
474  case QUAD8:
475  return std::make_unique<Quad8>(p);
476  case QUADSHELL8:
477  return std::make_unique<QuadShell8>(p);
478  case QUAD9:
479  return std::make_unique<Quad9>(p);
480  case QUADSHELL9:
481  return std::make_unique<QuadShell9>(p);
482 
483  // Well, a hexagon is *a* polygon...
484  case C0POLYGON:
485  return std::make_unique<C0Polygon>(6, p);
486 
487  // Building a polyhedron can't currently be done without creating
488  // its nodes first
489  case C0POLYHEDRON:
490  libmesh_not_implemented_msg
491  ("Polyhedra cannot be built via Elem::build()");
492 
493  // 3D elements
494  case TET4:
495  return std::make_unique<Tet4>(p);
496  case TET10:
497  return std::make_unique<Tet10>(p);
498  case TET14:
499  return std::make_unique<Tet14>(p);
500  case HEX8:
501  return std::make_unique<Hex8>(p);
502  case HEX20:
503  return std::make_unique<Hex20>(p);
504  case HEX27:
505  return std::make_unique<Hex27>(p);
506  case PRISM6:
507  return std::make_unique<Prism6>(p);
508  case PRISM15:
509  return std::make_unique<Prism15>(p);
510  case PRISM18:
511  return std::make_unique<Prism18>(p);
512  case PRISM20:
513  return std::make_unique<Prism20>(p);
514  case PRISM21:
515  return std::make_unique<Prism21>(p);
516  case PYRAMID5:
517  return std::make_unique<Pyramid5>(p);
518  case PYRAMID13:
519  return std::make_unique<Pyramid13>(p);
520  case PYRAMID14:
521  return std::make_unique<Pyramid14>(p);
522  case PYRAMID18:
523  return std::make_unique<Pyramid18>(p);
524 
525 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
526  // 1D infinite elements
527  case INFEDGE2:
528  return std::make_unique<InfEdge2>(p);
529 
530  // 2D infinite elements
531  case INFQUAD4:
532  return std::make_unique<InfQuad4>(p);
533  case INFQUAD6:
534  return std::make_unique<InfQuad6>(p);
535 
536  // 3D infinite elements
537  case INFHEX8:
538  return std::make_unique<InfHex8>(p);
539  case INFHEX16:
540  return std::make_unique<InfHex16>(p);
541  case INFHEX18:
542  return std::make_unique<InfHex18>(p);
543  case INFPRISM6:
544  return std::make_unique<InfPrism6>(p);
545  case INFPRISM12:
546  return std::make_unique<InfPrism12>(p);
547 #endif
548 
549  default:
550  libmesh_error_msg("ERROR: Undefined element type == " << Utility::enum_to_string(type));
551  }
552 }
553 
554 
555 
556 std::unique_ptr<Elem> Elem::build_with_id (const ElemType type,
557  dof_id_type id)
558 {
559  // Call the other build() method with nullptr parent, then set the
560  // required id.
561  auto temp = Elem::build(type, nullptr);
562  temp->set_id(id);
563  return temp;
564 }
565 
566 
567 
568 const Elem * Elem::reference_elem () const
569 {
570  return &(ReferenceElem::get(this->type()));
571 }
572 
573 
574 
575 #ifdef LIBMESH_ENABLE_DEPRECATED
577 {
578  libmesh_do_once(libMesh::err
579  << "Elem::centroid() has been deprecated. Replace with either "
580  << "Elem::vertex_average() to maintain existing behavior, or "
581  << "the more expensive Elem::true_centroid() "
582  << "in cases where the true 'geometric' centroid is required."
583  << std::endl);
584  libmesh_deprecated();
585 
586  return Elem::vertex_average();
587 }
588 #endif // LIBMESH_ENABLE_DEPRECATED
589 
590 
591 
593 {
594  // The base class implementation builds a finite element of the correct
595  // order and computes the centroid, c=(cx, cy, cz), where:
596  //
597  // [cx] [\int x dV]
598  // [cy] := (1/V) * [\int y dV]
599  // [cz] [\int z dV]
600  //
601  // using quadrature. Note that we can expand "x" in the FE space as:
602  //
603  // x = \sum_i x_i \phi_i
604  //
605  // where x_i are the nodal positions of the element and \phi_i are the
606  // associated Lagrange shape functions. This allows us to write the
607  // integrals above as e.g.:
608  //
609  // \int x dV = \sum_i x_i \int \phi_i dV
610  //
611  // Defining:
612  //
613  // V_i := \int \phi_i dV
614  //
615  // we then have:
616  //
617  // [cx] [\sum_i x_i V_i]
618  // [cy] = (1/V) * [\sum_i y_i V_i]
619  // [cz] [\sum_i z_i V_i]
620  //
621  // where:
622  // V = \sum_i V_i
623  //
624  // Derived element types can overload this method to compute
625  // the centroid more efficiently when possible.
626 
627  // If this Elem has an elevated p_level, then we need to generate a
628  // barebones copy of it with zero p_level and call true_centroid()
629  // on that instead. This workaround allows us to avoid issues with
630  // calling FE::reinit() with a default_order() FEType, and then
631  // having that order incorrectly boosted by p_level.
632  if (this->p_level())
633  {
634  auto elem_copy = this->disconnected_clone();
635 #ifdef LIBMESH_ENABLE_AMR
636  elem_copy->set_p_level(0);
637 #endif
638 
639  // Set node pointers
640  for (auto n : this->node_index_range())
641  elem_copy->set_node(n, _nodes[n]);
642 
643  return elem_copy->true_centroid();
644  }
645 
646  const FEFamily mapping_family = FEMap::map_fe_type(*this);
647  const FEType fe_type(this->default_order(), mapping_family);
648 
649  // Build FE and attach quadrature rule. The default quadrature rule
650  // integrates the mass matrix exactly, thus it is overkill to
651  // integrate the basis functions, but this is convenient.
652  std::unique_ptr<FEBase> fe = FEBase::build(this->dim(), fe_type);
653  QGauss qrule (this->dim(), fe_type.default_quadrature_order());
654  fe->attach_quadrature_rule(&qrule);
655 
656  // Pre-request required data
657  const auto & JxW = fe->get_JxW();
658  const auto & phi = fe->get_phi();
659 
660  // Re-compute element-specific values
661  fe->reinit(this);
662 
663  // Number of basis functions
664  auto N = phi.size();
665  libmesh_assert_equal_to(N, this->n_nodes());
666 
667  // Compute V_i
668  std::vector<Real> V(N);
669  for (auto qp : index_range(JxW))
670  for (auto i : make_range(N))
671  V[i] += JxW[qp] * phi[i][qp];
672 
673  // Compute centroid
674  Point cp;
675  Real vol = 0.;
676 
677  for (auto i : make_range(N))
678  {
679  cp += this->point(i) * V[i];
680  vol += V[i];
681  }
682 
683  return cp / vol;
684 }
685 
687 {
688  Point cp;
689 
690  const auto n_vertices = this->n_vertices();
691 
692  for (unsigned int n=0; n<n_vertices; n++)
693  cp.add (this->point(n));
694 
695  return (cp /= static_cast<Real>(n_vertices));
696 }
697 
698 
699 
701 {
702  Real h_min=std::numeric_limits<Real>::max();
703 
704  // Avoid calling a virtual a lot of times
705  const auto n_vertices = this->n_vertices();
706 
707  for (unsigned int n_outer=0; n_outer<n_vertices; n_outer++)
708  for (unsigned int n_inner=n_outer+1; n_inner<n_vertices; n_inner++)
709  {
710  const auto diff = (this->point(n_outer) - this->point(n_inner));
711 
712  h_min = std::min(h_min, diff.norm_sq());
713  }
714 
715  return std::sqrt(h_min);
716 }
717 
718 
719 
721 {
722  Real h_max=0;
723 
724  // Avoid calling a virtual a lot of times
725  const auto n_vertices = this->n_vertices();
726 
727  for (unsigned int n_outer=0; n_outer<n_vertices; n_outer++)
728  for (unsigned int n_inner=n_outer+1; n_inner<n_vertices; n_inner++)
729  {
730  const auto diff = (this->point(n_outer) - this->point(n_inner));
731 
732  h_max = std::max(h_max, diff.norm_sq());
733  }
734 
735  return std::sqrt(h_max);
736 }
737 
738 
739 
740 Real Elem::length(const unsigned int n1,
741  const unsigned int n2) const
742 {
743  libmesh_assert_less ( n1, this->n_vertices() );
744  libmesh_assert_less ( n2, this->n_vertices() );
745 
746  return (this->point(n1) - this->point(n2)).norm();
747 }
748 
749 
750 
752 {
753  const unsigned short n_n = this->n_nodes();
754 
755  std::array<dof_id_type, Elem::max_n_nodes> node_ids;
756 
757  for (unsigned short n=0; n != n_n; ++n)
758  node_ids[n] = this->node_id(n);
759 
760  // Always sort, so that different local node numberings hash to the
761  // same value.
762  std::sort (node_ids.begin(), node_ids.begin()+n_n);
763 
764  return Utility::hashword(node_ids.data(), n_n);
765 }
766 
767 
768 
769 bool Elem::operator == (const Elem & rhs) const
770 {
771  // If the elements aren't the same type, they aren't equal
772  if (this->type() != rhs.type())
773  return false;
774 
775  const unsigned short n_n = this->n_nodes();
776  libmesh_assert_equal_to(n_n, rhs.n_nodes());
777 
778  // Make two sorted arrays of global node ids and compare them for
779  // equality.
780  std::array<dof_id_type, Elem::max_n_nodes> this_ids, rhs_ids;
781 
782  for (unsigned short n = 0; n != n_n; n++)
783  {
784  this_ids[n] = this->node_id(n);
785  rhs_ids[n] = rhs.node_id(n);
786  }
787 
788  // Sort the vectors to rule out different local node numberings.
789  std::sort(this_ids.begin(), this_ids.begin()+n_n);
790  std::sort(rhs_ids.begin(), rhs_ids.begin()+n_n);
791 
792  // If the node ids match, the elements are equal!
793  for (unsigned short n = 0; n != n_n; ++n)
794  if (this_ids[n] != rhs_ids[n])
795  return false;
796  return true;
797 }
798 
799 
800 
801 bool Elem::topologically_equal (const Elem & rhs) const
802 {
803  // If the elements aren't the same type, they aren't equal
804  if (this->type() != rhs.type())
805  return false;
806 
807  libmesh_assert_equal_to(this->n_nodes(), rhs.n_nodes());
808 
809  for (auto n : make_range(this->n_nodes()))
810  if (this->node_id(n) != rhs.node_id(n))
811  return false;
812 
813  for (auto neigh : make_range(this->n_neighbors()))
814  {
815  if (!this->neighbor_ptr(neigh))
816  {
817  if (rhs.neighbor_ptr(neigh))
818  return false;
819  continue;
820  }
821  if (!rhs.neighbor_ptr(neigh) ||
822  this->neighbor_ptr(neigh)->id() !=
823  rhs.neighbor_ptr(neigh)->id())
824  return false;
825  }
826 
827  if (this->parent())
828  {
829  if (!rhs.parent())
830  return false;
831  if (this->parent()->id() != rhs.parent()->id())
832  return false;
833  }
834  else if (rhs.parent())
835  return false;
836 
837  if (this->interior_parent())
838  {
839  if (!rhs.interior_parent())
840  return false;
841  if (this->interior_parent()->id() !=
842  rhs.interior_parent()->id())
843  return false;
844  }
845  else if (rhs.interior_parent())
846  return false;
847 
848  return true;
849 }
850 
851 
852 
853 bool Elem::is_semilocal(const processor_id_type my_pid) const
854 {
855  std::set<const Elem *> point_neighbors;
856 
857  this->find_point_neighbors(point_neighbors);
858 
859  for (const auto & elem : point_neighbors)
860  if (elem->processor_id() == my_pid)
861  return true;
862 
863  return false;
864 }
865 
866 
867 
868 unsigned int Elem::which_side_am_i (const Elem * e) const
869 {
870  libmesh_assert(e);
871 
872  const unsigned int ns = this->n_sides();
873  const unsigned int nn = this->n_nodes();
874 
875  const unsigned int en = e->n_nodes();
876 
877  // e might be on any side until proven otherwise
878  std::vector<bool> might_be_side(ns, true);
879 
880  for (unsigned int i=0; i != en; ++i)
881  {
882  Point side_point = e->point(i);
883  unsigned int local_node_id = libMesh::invalid_uint;
884 
885  // Look for a node of this that's contiguous with node i of
886  // e. Note that the exact floating point comparison of Point
887  // positions is intentional, see the class documentation for
888  // this function.
889  for (unsigned int j=0; j != nn; ++j)
890  if (this->point(j) == side_point)
891  local_node_id = j;
892 
893  // If a node of e isn't contiguous with some node of this, then
894  // e isn't a side of this.
895  if (local_node_id == libMesh::invalid_uint)
896  return libMesh::invalid_uint;
897 
898  // If a node of e isn't contiguous with some node on side s of
899  // this, then e isn't on side s.
900  for (unsigned int s=0; s != ns; ++s)
901  if (!this->is_node_on_side(local_node_id, s))
902  might_be_side[s] = false;
903  }
904 
905  for (unsigned int s=0; s != ns; ++s)
906  if (might_be_side[s])
907  {
908 #ifdef DEBUG
909  for (unsigned int s2=s+1; s2 < ns; ++s2)
910  libmesh_assert (!might_be_side[s2]);
911 #endif
912  return s;
913  }
914 
915  // Didn't find any matching side
916  return libMesh::invalid_uint;
917 }
918 
919 
920 
921 #ifdef LIBMESH_ENABLE_DEPRECATED
922 unsigned int Elem::which_node_am_i(unsigned int side,
923  unsigned int side_node) const
924 {
925  libmesh_deprecated();
926  return local_side_node(side, side_node);
927 }
928 #endif // LIBMESH_ENABLE_DEPRECATED
929 
930 
931 
932 bool Elem::contains_vertex_of(const Elem * e, bool mesh_connection) const
933 {
934  // Our vertices are the first numbered nodes
935  const unsigned int nv = e->n_vertices();
936  const unsigned int my_nv = this->n_vertices();
937 
938  // Check for vertex-to-vertex containment first; contains_point() is
939  // expensive
940  for (auto n : make_range(nv))
941  {
942  const Node * vertex = e->node_ptr(n);
943  for (auto my_n : make_range(my_nv))
944  if (&this->node_ref(my_n) == vertex)
945  return true;
946  }
947 
948  // If e is in our mesh, then we might be done testing
949  if (mesh_connection)
950  {
951  const unsigned int l = this->level();
952  const unsigned int el = e->level();
953 
954  if (l >= el)
955  return false;
956 
957  // We could also return false for l==el-1 iff we knew we had no
958  // triangular faces, but we don't have an API to check that.
959  }
960 
961  // Our vertices are the first numbered nodes
962  for (auto n : make_range(nv))
963  if (this->contains_point(e->point(n)))
964  return true;
965  return false;
966 }
967 
968 
969 
970 bool Elem::contains_edge_of(const Elem * e) const
971 {
972  unsigned int num_contained_edges = 0;
973 
974  // Our vertices are the first numbered nodes
975  for (auto n : make_range(e->n_vertices()))
976  {
977  if (this->contains_point(e->point(n)))
978  {
979  num_contained_edges++;
980  if (num_contained_edges>=2)
981  {
982  return true;
983  }
984  }
985  }
986  return false;
987 }
988 
989 
990 
992  std::set<const Elem *> & neighbor_set) const
993 {
994  libmesh_assert(this->contains_point(p));
995  libmesh_assert(this->active());
996 
997  neighbor_set.clear();
998  neighbor_set.insert(this);
999 
1000  std::set<const Elem *> untested_set, next_untested_set;
1001  untested_set.insert(this);
1002 
1003 #ifdef LIBMESH_ENABLE_AMR
1004  std::vector<const Elem *> active_neighbor_children;
1005 #endif // #ifdef LIBMESH_ENABLE_AMR
1006 
1007  while (!untested_set.empty())
1008  {
1009  // Loop over all the elements in the patch that haven't already
1010  // been tested
1011  for (const auto & elem : untested_set)
1012  for (auto current_neighbor : elem->neighbor_ptr_range())
1013  {
1014  if (current_neighbor &&
1015  current_neighbor != remote_elem) // we have a real neighbor on this side
1016  {
1017  if (current_neighbor->active()) // ... if it is active
1018  {
1019  auto it = neighbor_set.lower_bound(current_neighbor);
1020  if ((it == neighbor_set.end() || *it != current_neighbor) &&
1021  current_neighbor->contains_point(p)) // ... don't have and touches p
1022  {
1023  // Add it and test it
1024  next_untested_set.insert(current_neighbor);
1025  neighbor_set.emplace_hint(it, current_neighbor);
1026  }
1027  }
1028 #ifdef LIBMESH_ENABLE_AMR
1029  else // ... the neighbor is *not* active,
1030  { // ... so add *all* neighboring
1031  // active children that touch p
1032  active_neighbor_children.clear();
1033  current_neighbor->active_family_tree_by_neighbor
1034  (active_neighbor_children, elem);
1035 
1036  for (const auto & current_child : active_neighbor_children)
1037  {
1038  auto it = neighbor_set.lower_bound(current_child);
1039  if ((it == neighbor_set.end() || *it != current_child) &&
1040  current_child->contains_point(p))
1041  {
1042  // Add it and test it
1043  next_untested_set.insert(current_child);
1044  neighbor_set.emplace_hint(it, current_child);
1045  }
1046  }
1047  }
1048 #endif // #ifdef LIBMESH_ENABLE_AMR
1049  }
1050  }
1051  untested_set.swap(next_untested_set);
1052  next_untested_set.clear();
1053  }
1054 }
1055 
1056 
1057 
1058 void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set) const
1059 {
1060  this->find_point_neighbors(neighbor_set, this);
1061 }
1062 
1063 
1064 
1065 void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set,
1066  const Elem * start_elem) const
1067 {
1068  ElemInternal::find_point_neighbors(this, neighbor_set, start_elem);
1069 }
1070 
1071 
1072 
1073 void Elem::find_point_neighbors(std::set<Elem *> & neighbor_set,
1074  Elem * start_elem)
1075 {
1076  ElemInternal::find_point_neighbors(this, neighbor_set, start_elem);
1077 }
1078 
1079 
1080 
1082  const Point & p2,
1083  std::set<const Elem *> & neighbor_set) const
1084 {
1085  // Simple but perhaps suboptimal code: find elements containing the
1086  // first point, then winnow this set down by removing elements which
1087  // don't also contain the second point
1088 
1089  libmesh_assert(this->contains_point(p2));
1090  this->find_point_neighbors(p1, neighbor_set);
1091 
1092  std::set<const Elem *>::iterator it = neighbor_set.begin();
1093  const std::set<const Elem *>::iterator end = neighbor_set.end();
1094 
1095  while (it != end)
1096  {
1097  // As of C++11, set::erase returns an iterator to the element
1098  // following the erased element, or end.
1099  if (!(*it)->contains_point(p2))
1100  it = neighbor_set.erase(it);
1101  else
1102  ++it;
1103  }
1104 }
1105 
1106 
1107 
1108 void Elem::find_edge_neighbors(std::set<const Elem *> & neighbor_set) const
1109 {
1110  neighbor_set.clear();
1111  neighbor_set.insert(this);
1112 
1113  std::set<const Elem *> untested_set, next_untested_set;
1114  untested_set.insert(this);
1115 
1116  while (!untested_set.empty())
1117  {
1118  // Loop over all the elements in the patch that haven't already
1119  // been tested
1120  for (const auto & elem : untested_set)
1121  {
1122  for (auto current_neighbor : elem->neighbor_ptr_range())
1123  {
1124  if (current_neighbor &&
1125  current_neighbor != remote_elem) // we have a real neighbor on this side
1126  {
1127  if (current_neighbor->active()) // ... if it is active
1128  {
1129  if (this->contains_edge_of(current_neighbor) // ... and touches us
1130  || current_neighbor->contains_edge_of(this))
1131  {
1132  // Make sure we'll test it
1133  if (!neighbor_set.count(current_neighbor))
1134  next_untested_set.insert (current_neighbor);
1135 
1136  // And add it
1137  neighbor_set.insert (current_neighbor);
1138  }
1139  }
1140 #ifdef LIBMESH_ENABLE_AMR
1141  else // ... the neighbor is *not* active,
1142  { // ... so add *all* neighboring
1143  // active children
1144  std::vector<const Elem *> active_neighbor_children;
1145 
1146  current_neighbor->active_family_tree_by_neighbor
1147  (active_neighbor_children, elem);
1148 
1149  for (const auto & current_child : active_neighbor_children)
1150  if (this->contains_edge_of(current_child) || current_child->contains_edge_of(this))
1151  {
1152  // Make sure we'll test it
1153  if (!neighbor_set.count(current_child))
1154  next_untested_set.insert (current_child);
1155 
1156  neighbor_set.insert (current_child);
1157  }
1158  }
1159 #endif // #ifdef LIBMESH_ENABLE_AMR
1160  }
1161  }
1162  }
1163  untested_set.swap(next_untested_set);
1164  next_untested_set.clear();
1165  }
1166 }
1167 
1168 
1169 
1170 void Elem::find_interior_neighbors(std::set<const Elem *> & neighbor_set) const
1171 {
1172  ElemInternal::find_interior_neighbors(this, neighbor_set);
1173 }
1174 
1175 
1176 
1177 void Elem::find_interior_neighbors(std::set<Elem *> & neighbor_set)
1178 {
1179  ElemInternal::find_interior_neighbors(this, neighbor_set);
1180 }
1181 
1182 
1183 
1184 const Elem * Elem::interior_parent () const
1185 {
1186  // interior parents make no sense for full-dimensional elements.
1187  if (this->dim() >= LIBMESH_DIM)
1188  return nullptr;
1189 
1190  // they USED TO BE only good for level-0 elements, but we now
1191  // support keeping interior_parent() valid on refined boundary
1192  // elements.
1193  // if (this->level() != 0)
1194  // return this->parent()->interior_parent();
1195 
1196  // We store the interior_parent pointer after both the parent
1197  // neighbor and neighbor pointers
1198  Elem * interior_p = _elemlinks[1+this->n_sides()];
1199 
1200  // If we have an interior_parent, we USED TO assume it was a
1201  // one-higher-dimensional interior element, but we now allow e.g.
1202  // edge elements to have a 3D interior_parent with no
1203  // intermediate 2D element.
1204  // libmesh_assert (!interior_p ||
1205  // interior_p->dim() == (this->dim()+1));
1206  libmesh_assert (!interior_p ||
1207  (interior_p == remote_elem) ||
1208  (interior_p->dim() > this->dim()));
1209 
1210  // If an element in a multi-dimensional mesh has an interior_parent
1211  // link, it should be at our level or coarser, just like a neighbor
1212  // link. Our collect_families() code relies on this, but it might
1213  // be tempting for users to manually assign something that breaks
1214  // it.
1215  //
1216  // However, we *also* create temporary side elements, and we don't
1217  // bother with creating ancestors for those, so they can be at level
1218  // 0 even when they're sides of non-level-0 elements.
1219  libmesh_assert (!interior_p ||
1220  (interior_p->level() <= this->level()) ||
1221  (this->level() == 0 &&
1222  this->id() == DofObject::invalid_id));
1223 
1224  return interior_p;
1225 }
1226 
1227 
1228 
1230 {
1231  // See the const version for comments
1232  if (this->dim() >= LIBMESH_DIM)
1233  return nullptr;
1234 
1235  Elem * interior_p = _elemlinks[1+this->n_sides()];
1236 
1237  libmesh_assert (!interior_p ||
1238  (interior_p == remote_elem) ||
1239  (interior_p->dim() > this->dim()));
1240 
1241  return interior_p;
1242 }
1243 
1244 
1245 
1247 {
1248  // interior parents make no sense for full-dimensional elements.
1249  libmesh_assert (!p ||
1250  this->dim() < LIBMESH_DIM);
1251 
1252  // If we have an interior_parent, we USED TO assume it was a
1253  // one-higher-dimensional interior element, but we now allow e.g.
1254  // edge elements to have a 3D interior_parent with no
1255  // intermediate 2D element.
1256  // libmesh_assert (!p ||
1257  // p->dim() == (this->dim()+1));
1258  libmesh_assert (!p ||
1259  (p == remote_elem) ||
1260  (p->dim() > this->dim()));
1261 
1262  _elemlinks[1+this->n_sides()] = p;
1263 }
1264 
1265 
1266 
1267 #ifdef LIBMESH_ENABLE_PERIODIC
1268 
1269 Elem * Elem::topological_neighbor (const unsigned int i,
1270  MeshBase & mesh,
1271  const PointLocatorBase & point_locator,
1272  const PeriodicBoundaries * pb)
1273 {
1274  libmesh_assert_less (i, this->n_neighbors());
1275 
1276  Elem * neighbor_i = this->neighbor_ptr(i);
1277  if (neighbor_i != nullptr)
1278  return neighbor_i;
1279 
1280  if (pb)
1281  {
1282  // Since the neighbor is nullptr it must be on a boundary. We need
1283  // see if this is a periodic boundary in which case it will have a
1284  // topological neighbor
1285  std::vector<boundary_id_type> bc_ids;
1286  mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
1287  for (const auto & id : bc_ids)
1288  if (pb->boundary(id))
1289  {
1290  // Since the point locator inside of periodic boundaries
1291  // returns a const pointer we will retrieve the proper
1292  // pointer directly from the mesh object.
1293  const Elem * const cn = pb->neighbor(id, point_locator, this, i);
1294  neighbor_i = const_cast<Elem *>(cn);
1295 
1296  // Since coarse elements do not have more refined
1297  // neighbors we need to make sure that we don't return one
1298  // of these types of neighbors.
1299  if (neighbor_i)
1300  while (level() < neighbor_i->level())
1301  neighbor_i = neighbor_i->parent();
1302  return neighbor_i;
1303  }
1304  }
1305 
1306  return nullptr;
1307 }
1308 
1309 
1310 
1311 const Elem * Elem::topological_neighbor (const unsigned int i,
1312  const MeshBase & mesh,
1313  const PointLocatorBase & point_locator,
1314  const PeriodicBoundaries * pb) const
1315 {
1316  libmesh_assert_less (i, this->n_neighbors());
1317 
1318  const Elem * neighbor_i = this->neighbor_ptr(i);
1319  if (neighbor_i != nullptr)
1320  return neighbor_i;
1321 
1322  if (pb)
1323  {
1324  // Since the neighbor is nullptr it must be on a boundary. We need
1325  // see if this is a periodic boundary in which case it will have a
1326  // topological neighbor
1327  std::vector<boundary_id_type> bc_ids;
1328  mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
1329  for (const auto & id : bc_ids)
1330  if (pb->boundary(id))
1331  {
1332  neighbor_i = pb->neighbor(id, point_locator, this, i);
1333 
1334  // Since coarse elements do not have more refined
1335  // neighbors we need to make sure that we don't return one
1336  // of these types of neighbors.
1337  if (neighbor_i)
1338  while (level() < neighbor_i->level())
1339  neighbor_i = neighbor_i->parent();
1340  return neighbor_i;
1341  }
1342  }
1343 
1344  return nullptr;
1345 }
1346 
1347 
1349  const MeshBase & mesh,
1350  const PointLocatorBase & point_locator,
1351  const PeriodicBoundaries * pb) const
1352 {
1353  // First see if this is a normal "interior" neighbor
1354  if (has_neighbor(elem))
1355  return true;
1356 
1357  for (auto n : this->side_index_range())
1358  if (this->topological_neighbor(n, mesh, point_locator, pb))
1359  return true;
1360 
1361  return false;
1362 }
1363 
1364 
1365 #endif
1366 
1367 #ifndef NDEBUG
1368 
1370 {
1371  libmesh_assert(this->valid_id());
1372  for (auto n : this->node_index_range())
1373  {
1374  libmesh_assert(this->node_ptr(n));
1375  libmesh_assert(this->node_ptr(n)->valid_id());
1376  }
1377 }
1378 
1379 
1380 
1382 {
1383  for (auto n : this->side_index_range())
1384  {
1385  const Elem * neigh = this->neighbor_ptr(n);
1386 
1387  // Any element might have a remote neighbor; checking
1388  // to make sure that's not inaccurate is tough.
1389  if (neigh == remote_elem)
1390  continue;
1391 
1392  if (neigh)
1393  {
1394  // Only subactive elements have subactive neighbors
1395  libmesh_assert (this->subactive() || !neigh->subactive());
1396 
1397  const Elem * elem = this;
1398 
1399  // If we're subactive but our neighbor isn't, its
1400  // return neighbor link will be to our first active
1401  // ancestor OR to our inactive ancestor of the same
1402  // level as neigh,
1403  if (this->subactive() && !neigh->subactive())
1404  {
1405  for (elem = this; !elem->active();
1406  elem = elem->parent())
1407  libmesh_assert(elem);
1408  }
1409  else
1410  {
1411  unsigned int rev = neigh->which_neighbor_am_i(elem);
1412  libmesh_assert_less (rev, neigh->n_neighbors());
1413 
1414  if (this->subactive() && !neigh->subactive())
1415  {
1416  while (neigh->neighbor_ptr(rev) != elem)
1417  {
1418  libmesh_assert(elem->parent());
1419  elem = elem->parent();
1420  }
1421  }
1422  else
1423  {
1424  const Elem * nn = neigh->neighbor_ptr(rev);
1425  libmesh_assert(nn);
1426 
1427  for (; elem != nn; elem = elem->parent())
1428  libmesh_assert(elem);
1429  }
1430  }
1431  }
1432  // If we don't have a neighbor and we're not subactive, our
1433  // ancestors shouldn't have any neighbors in this same
1434  // direction.
1435  else if (!this->subactive())
1436  {
1437  const Elem * my_parent = this->parent();
1438  if (my_parent &&
1439  // A parent with a different dimension isn't really one of
1440  // our ancestors, it means we're on a boundary mesh and this
1441  // is an interior mesh element for which we're on a side.
1442  // Nothing to test for in that case.
1443  (my_parent->dim() == this->dim()))
1444  libmesh_assert (!my_parent->neighbor_ptr(n));
1445  }
1446  }
1447 }
1448 
1449 #endif // !NDEBUG
1450 
1451 
1452 
1453 void Elem::make_links_to_me_local(unsigned int n, unsigned int nn)
1454 {
1455  Elem * neigh = this->neighbor_ptr(n);
1456 
1457  // Don't bother calling this function unless it's necessary
1458  libmesh_assert(neigh);
1459  libmesh_assert(!neigh->is_remote());
1460 
1461  // We never have neighbors more refined than us
1462  libmesh_assert_less_equal (neigh->level(), this->level());
1463 
1464  // We never have subactive neighbors of non subactive elements
1465  libmesh_assert(!neigh->subactive() || this->subactive());
1466 
1467  // If we have a neighbor less refined than us then it must not
1468  // have any more refined descendants we could have pointed to
1469  // instead.
1470  libmesh_assert((neigh->level() == this->level()) ||
1471  (neigh->active() && !this->subactive()) ||
1472  (!neigh->has_children() && this->subactive()));
1473 
1474  // If neigh is at our level, then its family might have
1475  // remote_elem neighbor links which need to point to us
1476  // instead, but if not, then we're done.
1477  if (neigh->level() != this->level())
1478  return;
1479 
1480  // What side of neigh are we on? nn.
1481  //
1482  // We can't use the usual Elem method because we're in the middle of
1483  // restoring topology. We can't compare side_ptr nodes because
1484  // users want to abuse neighbor_ptr to point to
1485  // not-technically-neighbors across mesh slits. We can't compare
1486  // node locations because users want to move those
1487  // not-technically-neighbors until they're
1488  // not-even-geometrically-neighbors.
1489 
1490  // Find any elements that ought to point to elem
1491  std::vector<Elem *> neigh_family;
1492 #ifdef LIBMESH_ENABLE_AMR
1493  if (this->active())
1494  neigh->family_tree_by_side(neigh_family, nn);
1495  else
1496 #endif
1497  neigh_family.push_back(neigh);
1498 
1499  // And point them to elem
1500  for (auto & neigh_family_member : neigh_family)
1501  {
1502  // Only subactive elements point to other subactive elements
1503  if (this->subactive() && !neigh_family_member->subactive())
1504  continue;
1505 
1506  // Ideally, the neighbor link ought to either be correct
1507  // already or ought to be to remote_elem.
1508  //
1509  // However, if we're redistributing a newly created elem,
1510  // after an AMR step but before find_neighbors has fixed up
1511  // neighbor links, we might have an out of date neighbor
1512  // link to elem's parent instead.
1513 #ifdef LIBMESH_ENABLE_AMR
1514  libmesh_assert((neigh_family_member->neighbor_ptr(nn) &&
1515  (neigh_family_member->neighbor_ptr(nn)->active() ||
1516  neigh_family_member->neighbor_ptr(nn)->is_ancestor_of(this))) ||
1517  (neigh_family_member->neighbor_ptr(nn) == remote_elem) ||
1518  ((this->refinement_flag() == JUST_REFINED) &&
1519  (this->parent() != nullptr) &&
1520  (neigh_family_member->neighbor_ptr(nn) == this->parent())));
1521 #else
1522  libmesh_assert((neigh_family_member->neighbor_ptr(nn) == this) ||
1523  (neigh_family_member->neighbor_ptr(nn) == remote_elem));
1524 #endif
1525 
1526  neigh_family_member->set_neighbor(nn, this);
1527  }
1528 }
1529 
1530 
1532 {
1533  libmesh_assert_not_equal_to (this, remote_elem);
1534 
1535  // We need to have handled any children first
1536 #if defined(LIBMESH_ENABLE_AMR) && defined(DEBUG)
1537  if (this->has_children())
1538  for (auto & child : this->child_ref_range())
1539  libmesh_assert_equal_to (&child, remote_elem);
1540 #endif
1541 
1542  // Remotify any neighbor links
1543  for (auto neigh : this->neighbor_ptr_range())
1544  {
1545  if (neigh && neigh != remote_elem)
1546  {
1547  // My neighbor should never be more refined than me; my real
1548  // neighbor would have been its parent in that case.
1549  libmesh_assert_greater_equal (this->level(), neigh->level());
1550 
1551  if (this->level() == neigh->level() &&
1552  neigh->has_neighbor(this))
1553  {
1554 #ifdef LIBMESH_ENABLE_AMR
1555  // My neighbor may have descendants which also consider me a
1556  // neighbor
1557  std::vector<Elem *> family;
1558  neigh->total_family_tree_by_neighbor (family, this);
1559 
1560  // FIXME - There's a lot of ugly const_casts here; we
1561  // may want to make remote_elem non-const
1562  for (auto & n : family)
1563  {
1564  libmesh_assert (n);
1565  if (n == remote_elem)
1566  continue;
1567  unsigned int my_s = n->which_neighbor_am_i(this);
1568  libmesh_assert_less (my_s, n->n_neighbors());
1569  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1570  n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1571  }
1572 #else
1573  unsigned int my_s = neigh->which_neighbor_am_i(this);
1574  libmesh_assert_less (my_s, neigh->n_neighbors());
1575  libmesh_assert_equal_to (neigh->neighbor_ptr(my_s), this);
1576  neigh->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1577 #endif
1578  }
1579 #ifdef LIBMESH_ENABLE_AMR
1580  // Even if my neighbor doesn't link back to me, it might
1581  // have subactive descendants which do
1582  else if (neigh->has_children())
1583  {
1584  // If my neighbor at the same level doesn't have me as a
1585  // neighbor, I must be subactive
1586  libmesh_assert(this->level() > neigh->level() ||
1587  this->subactive());
1588 
1589  // My neighbor must have some ancestor of mine as a
1590  // neighbor
1591  Elem * my_ancestor = this->parent();
1592  libmesh_assert(my_ancestor);
1593  while (!neigh->has_neighbor(my_ancestor))
1594  {
1595  my_ancestor = my_ancestor->parent();
1596  libmesh_assert(my_ancestor);
1597  }
1598 
1599  // My neighbor may have descendants which consider me a
1600  // neighbor
1601  std::vector<Elem *> family;
1602  neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
1603 
1604  for (auto & n : family)
1605  {
1606  libmesh_assert (n);
1607  if (n->is_remote())
1608  continue;
1609  unsigned int my_s = n->which_neighbor_am_i(this);
1610  libmesh_assert_less (my_s, n->n_neighbors());
1611  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1612  // TODO: we may want to make remote_elem non-const.
1613  n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
1614  }
1615  }
1616 #endif
1617  }
1618  }
1619 
1620 #ifdef LIBMESH_ENABLE_AMR
1621  // Remotify parent's child link
1622  Elem * my_parent = this->parent();
1623  if (my_parent &&
1624  // As long as it's not already remote
1625  my_parent != remote_elem &&
1626  // And it's a real parent, not an interior parent
1627  this->dim() == my_parent->dim())
1628  {
1629  unsigned int me = my_parent->which_child_am_i(this);
1630  libmesh_assert_equal_to (my_parent->child_ptr(me), this);
1631  my_parent->set_child(me, const_cast<RemoteElem *>(remote_elem));
1632  }
1633 #endif
1634 }
1635 
1636 
1638 {
1639  libmesh_assert_not_equal_to (this, remote_elem);
1640 
1641  // We need to have handled any children first
1642 #ifdef LIBMESH_ENABLE_AMR
1643  libmesh_assert (!this->has_children());
1644 #endif
1645 
1646  // Nullify any neighbor links
1647  for (auto neigh : this->neighbor_ptr_range())
1648  {
1649  if (neigh && neigh != remote_elem)
1650  {
1651  // My neighbor should never be more refined than me; my real
1652  // neighbor would have been its parent in that case.
1653  libmesh_assert_greater_equal (this->level(), neigh->level());
1654 
1655  if (this->level() == neigh->level() &&
1656  neigh->has_neighbor(this))
1657  {
1658 #ifdef LIBMESH_ENABLE_AMR
1659  // My neighbor may have descendants which also consider me a
1660  // neighbor
1661  std::vector<Elem *> family;
1662  neigh->total_family_tree_by_neighbor (family, this);
1663 
1664  for (auto & n : family)
1665  {
1666  libmesh_assert (n);
1667  if (n->is_remote())
1668  continue;
1669  unsigned int my_s = n->which_neighbor_am_i(this);
1670  libmesh_assert_less (my_s, n->n_neighbors());
1671  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1672  n->set_neighbor(my_s, nullptr);
1673  }
1674 #else
1675  unsigned int my_s = neigh->which_neighbor_am_i(this);
1676  libmesh_assert_less (my_s, neigh->n_neighbors());
1677  libmesh_assert_equal_to (neigh->neighbor_ptr(my_s), this);
1678  neigh->set_neighbor(my_s, nullptr);
1679 #endif
1680  }
1681 #ifdef LIBMESH_ENABLE_AMR
1682  // Even if my neighbor doesn't link back to me, it might
1683  // have subactive descendants which do
1684  else if (neigh->has_children())
1685  {
1686  // If my neighbor at the same level doesn't have me as a
1687  // neighbor, I must be subactive
1688  libmesh_assert(this->level() > neigh->level() ||
1689  this->subactive());
1690 
1691  // My neighbor must have some ancestor of mine as a
1692  // neighbor
1693  Elem * my_ancestor = this->parent();
1694  libmesh_assert(my_ancestor);
1695  while (!neigh->has_neighbor(my_ancestor))
1696  {
1697  my_ancestor = my_ancestor->parent();
1698  libmesh_assert(my_ancestor);
1699  }
1700 
1701  // My neighbor may have descendants which consider me a
1702  // neighbor
1703  std::vector<Elem *> family;
1704  neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
1705 
1706  for (auto & n : family)
1707  {
1708  libmesh_assert (n);
1709  if (n->is_remote())
1710  continue;
1711  unsigned int my_s = n->which_neighbor_am_i(this);
1712  libmesh_assert_less (my_s, n->n_neighbors());
1713  libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
1714  n->set_neighbor(my_s, nullptr);
1715  }
1716  }
1717 #endif
1718  }
1719  }
1720 
1721 #ifdef LIBMESH_ENABLE_AMR
1722  // We can't currently delete a child with a parent!
1723  libmesh_assert (!this->parent());
1724 #endif
1725 }
1726 
1727 
1728 
1729 void Elem::write_connectivity (std::ostream & out_stream,
1730  const IOPackage iop) const
1731 {
1732  libmesh_assert (out_stream.good());
1734  libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
1735 
1736  switch (iop)
1737  {
1738  case TECPLOT:
1739  {
1740  // This connectivity vector will be used repeatedly instead
1741  // of being reconstructed inside the loop.
1742  std::vector<dof_id_type> conn;
1743  for (auto sc : make_range(this->n_sub_elem()))
1744  {
1745  this->connectivity(sc, TECPLOT, conn);
1746 
1747  std::copy(conn.begin(),
1748  conn.end(),
1749  std::ostream_iterator<dof_id_type>(out_stream, " "));
1750 
1751  out_stream << '\n';
1752  }
1753  return;
1754  }
1755 
1756  case UCD:
1757  {
1758  for (auto i : this->node_index_range())
1759  out_stream << this->node_id(i)+1 << "\t";
1760 
1761  out_stream << '\n';
1762  return;
1763  }
1764 
1765  default:
1766  libmesh_error_msg("Unsupported IO package " << iop);
1767  }
1768 }
1769 
1770 
1771 
1773 {
1774  switch (q)
1775  {
1776  // Return the maximum ratio of edge lengths, or zero if that
1777  // maximum would otherwise be infinity.
1778  case EDGE_LENGTH_RATIO:
1779  {
1780  if (this->dim() < 2)
1781  return 1;
1782 
1783  std::vector<Real> edge_lengths(this->n_edges());
1784  for (auto e : index_range(edge_lengths))
1785  edge_lengths[e] = (this->point(this->local_edge_node(e,1)) -
1786  this->point(this->local_edge_node(e,0))).norm();
1787 
1788  auto [min, max] =
1789  std::minmax_element(edge_lengths.begin(), edge_lengths.end());
1790 
1791  if (*min == 0.)
1792  return 0.;
1793  else
1794  return *max / *min;
1795  }
1796 
1797  case MIN_ANGLE:
1798  case MAX_ANGLE:
1799  {
1800  // 1D elements don't have interior angles, so just return some
1801  // dummy value in that case.
1802  if (this->dim() < 2)
1803  return 0.;
1804 
1805  // Initialize return values
1806  Real min_angle = std::numeric_limits<Real>::max();
1807  Real max_angle = -std::numeric_limits<Real>::max();
1808 
1809  for (auto n : this->node_index_range())
1810  {
1811  // Get list of edge ids adjacent to this node.
1812  const auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
1813 
1814  // Skip any nodes with fewer than 2 adjacent edges. You
1815  // need at least two adjacent edges to form an interior
1816  // element angle.
1817  auto N = adjacent_edge_ids.size();
1818  if (N < 2)
1819  continue;
1820 
1821  // Consider all possible pairs of edges adjacent to node n
1822  for (unsigned int first = 0; first < N-1; ++first)
1823  for (unsigned int second = first+1; second < N; ++second)
1824  {
1825  // Get ids of first and second edges
1826  auto first_edge = adjacent_edge_ids[first];
1827  auto second_edge = adjacent_edge_ids[second];
1828 
1829  // Get node ids of first and second edge
1830  auto first_edge_node_0 = this->local_edge_node(first_edge, 0);
1831  auto first_edge_node_1 = this->local_edge_node(first_edge, 1);
1832  auto second_edge_node_0 = this->local_edge_node(second_edge, 0);
1833  auto second_edge_node_1 = this->local_edge_node(second_edge, 1);
1834 
1835  // Orient both edges so that edge node 0 == n
1836  if (first_edge_node_0 != n)
1837  std::swap(first_edge_node_0, first_edge_node_1);
1838  if (second_edge_node_0 != n)
1839  std::swap(second_edge_node_0, second_edge_node_1);
1840 
1841  libmesh_assert_equal_to(first_edge_node_0, n);
1842  libmesh_assert_equal_to(second_edge_node_0, n);
1843 
1844  // Locally oriented edge vectors
1845  Point
1846  first_ev = this->point(first_edge_node_1) - this->point(first_edge_node_0),
1847  second_ev = this->point(second_edge_node_1) - this->point(second_edge_node_0);
1848 
1849  // Angle between them in the range [0, pi]
1850  Real theta = std::acos(first_ev.unit() * second_ev.unit());
1851 
1852  // Track min and max angles seen
1853  min_angle = std::min(theta, min_angle);
1854  max_angle = std::max(theta, max_angle);
1855  }
1856  }
1857 
1858  // Return requested extreme value (in degrees)
1859  return Real(180)/libMesh::pi * ((q == MIN_ANGLE) ? min_angle : max_angle);
1860  }
1861 
1862  case MIN_DIHEDRAL_ANGLE:
1863  case MAX_DIHEDRAL_ANGLE:
1864  {
1865  // For 1D and 2D elements, just call this function with MIN,MAX_ANGLE instead.
1866  if (this->dim() < 3)
1867  return this->quality((q == MIN_DIHEDRAL_ANGLE) ? MIN_ANGLE : MAX_ANGLE);
1868 
1869  // Initialize return values
1870  Real min_angle = std::numeric_limits<Real>::max();
1871  Real max_angle = -std::numeric_limits<Real>::max();
1872 
1873  // Algorithm for computing dihedral angles:
1874  // .) Loop over the edges, use the edge_sides_map to get the
1875  // two sides adjacent to the edge.
1876  // .) For each adjacent side, use the side_nodes_map to get the
1877  // list of three (or more) node ids on that side.
1878  // .) Use the node ids to compute the (approximate) inward
1879  // normal for the side. Note: this is approximate since 3D
1880  // elements with four-sided faces and quadratic tetrahedra
1881  // do not necessarily have planar faces.
1882  // .) Compute the dihedral angle for the current edge, compare
1883  // it to the current min and max dihedral angles.
1884  for (auto e : this->edge_index_range())
1885  {
1886  // Get list of edge ids adjacent to this node.
1887  const auto adjacent_side_ids = this->sides_on_edge(e);
1888 
1889  // All 3D elements should have exactly two sides adjacent to each edge.
1890  libmesh_assert_equal_to(adjacent_side_ids.size(), 2);
1891 
1892  // Get lists of node ids on each side
1893  const auto side_0_node_ids = this->nodes_on_side(adjacent_side_ids[0]);
1894  const auto side_1_node_ids = this->nodes_on_side(adjacent_side_ids[1]);
1895 
1896  // All 3D elements have at least three nodes on each side
1897  libmesh_assert_greater_equal(side_0_node_ids.size(), 3);
1898  libmesh_assert_greater_equal(side_1_node_ids.size(), 3);
1899 
1900  // Construct (approximate) inward normal on each adjacent side
1901  const auto side_0_normal =
1902  (this->point(side_0_node_ids[2]) - this->point(side_0_node_ids[0])).cross
1903  (this->point(side_0_node_ids[1]) - this->point(side_0_node_ids[0])).unit();
1904  const auto side_1_normal =
1905  (this->point(side_1_node_ids[2]) - this->point(side_1_node_ids[0])).cross
1906  (this->point(side_1_node_ids[1]) - this->point(side_1_node_ids[0])).unit();
1907 
1908  // Compute dihedral angle between the planes.
1909  // Using the absolute value ensures that we get the same result
1910  // even if the orientation of one of the planes is flipped, i.e.
1911  // it always gives us a value in the range [0, pi/2].
1912  // https://en.wikipedia.org/wiki/Dihedral_angle
1913  Real theta = std::acos(std::abs(side_0_normal * side_1_normal));
1914 
1915  // Track min and max angles seen
1916  min_angle = std::min(theta, min_angle);
1917  max_angle = std::max(theta, max_angle);
1918  }
1919 
1920  // Return requested extreme value (in degrees)
1921  return Real(180)/libMesh::pi * ((q == MIN_DIHEDRAL_ANGLE) ? min_angle : max_angle);
1922  }
1923 
1924  case JACOBIAN:
1925  case SCALED_JACOBIAN:
1926  {
1927  // 1D elements don't have interior corners, so this metric
1928  // does not really apply to them.
1929  const auto N = this->dim();
1930  if (N < 2)
1931  return 1.;
1932 
1933  // Initialize return value
1934  Real min_node_area = std::numeric_limits<Real>::max();
1935 
1936  for (auto n : this->node_index_range())
1937  {
1938  // Get list of edge ids adjacent to this node.
1939  auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
1940 
1941  // Skip any nodes that don't have dim() adjacent edges. In 2D,
1942  // you need at least two adjacent edges to compute the cross
1943  // product, and in 3D, you need at least three adjacent edges
1944  // to compute the scalar triple product. The only element
1945  // type which has an unusual topology in this regard is the
1946  // Pyramid element in 3D, where 4 edges meet at the apex node.
1947  // For now, we just skip this node when computing the JACOBIAN
1948  // metric for Pyramids.
1949  if (adjacent_edge_ids.size() != N)
1950  continue;
1951 
1952  // Construct oriented edges
1953  std::vector<Point> oriented_edges(N);
1954  for (auto i : make_range(N))
1955  {
1956  auto node_0 = this->local_edge_node(adjacent_edge_ids[i], 0);
1957  auto node_1 = this->local_edge_node(adjacent_edge_ids[i], 1);
1958  if (node_0 != n)
1959  std::swap(node_0, node_1);
1960  oriented_edges[i] = this->point(node_1) - this->point(node_0);
1961  }
1962 
1963  // Compute unscaled area (2D) or volume (3D) using the
1964  // cross product (2D) or scalar triple product (3D) of the
1965  // oriented edges. We take the absolute value so that we
1966  // don't have to worry about the sign of the area.
1967  Real node_area = (N == 2) ?
1968  cross_norm(oriented_edges[0], oriented_edges[1]) :
1969  std::abs(triple_product(oriented_edges[0], oriented_edges[1], oriented_edges[2]));
1970 
1971  // Divide by (non-zero) edge lengths if computing scaled Jacobian.
1972  // If any length is zero, then set node_area to zero. This means that
1973  // e.g. degenerate quadrilaterals will have a zero SCALED_JACOBIAN metric.
1974  if (q == SCALED_JACOBIAN)
1975  for (auto i : make_range(N))
1976  {
1977  Real len_i = oriented_edges[i].norm();
1978  node_area = (len_i == 0.) ? 0. : (node_area / len_i);
1979  }
1980 
1981  // Update minimum
1982  min_node_area = std::min(node_area, min_node_area);
1983  }
1984 
1985  return min_node_area;
1986  }
1987 
1988  // Return 1 if we made it here
1989  default:
1990  {
1991  libmesh_do_once( libmesh_here();
1992 
1993  libMesh::err << "ERROR: quality metric "
1995  << " not implemented on element type "
1996  << Utility::enum_to_string(this->type())
1997  << std::endl
1998  << "Returning 1."
1999  << std::endl; );
2000 
2001  return 1.;
2002  }
2003  }
2004 }
2005 
2006 
2007 
2008 bool Elem::ancestor() const
2009 {
2010 #ifdef LIBMESH_ENABLE_AMR
2011 
2012  // Use a fast, DistributedMesh-safe definition
2013  const bool is_ancestor =
2014  !this->active() && !this->subactive();
2015 
2016  // But check for inconsistencies if we have time
2017 #ifdef DEBUG
2018  if (!is_ancestor && this->has_children())
2019  {
2020  for (auto & c : this->child_ref_range())
2021  {
2022  if (&c != remote_elem)
2023  {
2024  libmesh_assert(!c.active());
2025  libmesh_assert(!c.ancestor());
2026  }
2027  }
2028  }
2029 #endif // DEBUG
2030 
2031  return is_ancestor;
2032 
2033 #else
2034  return false;
2035 #endif
2036 }
2037 
2038 
2039 
2040 #ifdef LIBMESH_ENABLE_AMR
2041 
2042 void Elem::add_child (Elem * elem)
2043 {
2044  const unsigned int nc = this->n_children();
2045 
2046  if (!_children)
2047  {
2048  _children = std::make_unique<Elem *[]>(nc);
2049 
2050  for (unsigned int c = 0; c != nc; c++)
2051  this->set_child(c, nullptr);
2052  }
2053 
2054  for (unsigned int c = 0; c != nc; c++)
2055  {
2056  if (this->_children[c] == nullptr || this->_children[c] == remote_elem)
2057  {
2058  libmesh_assert_equal_to (this, elem->parent());
2059  this->set_child(c, elem);
2060  return;
2061  }
2062  }
2063 
2064  libmesh_error_msg("Error: Tried to add a child to an element with full children array");
2065 }
2066 
2067 
2068 
2069 void Elem::add_child (Elem * elem, unsigned int c)
2070 {
2071  if (!this->has_children())
2072  {
2073  const unsigned int nc = this->n_children();
2074  _children = std::make_unique<Elem *[]>(nc);
2075 
2076  for (unsigned int i = 0; i != nc; i++)
2077  this->set_child(i, nullptr);
2078  }
2079 
2080  libmesh_assert (this->_children[c] == nullptr || this->child_ptr(c) == remote_elem);
2081  libmesh_assert (elem == remote_elem || this == elem->parent());
2082 
2083  this->set_child(c, elem);
2084 }
2085 
2086 
2087 
2088 void Elem::replace_child (Elem * elem, unsigned int c)
2089 {
2090  libmesh_assert(this->has_children());
2091 
2092  libmesh_assert(this->child_ptr(c));
2093 
2094  this->set_child(c, elem);
2095 }
2096 
2097 
2098 
2099 void Elem::family_tree (std::vector<const Elem *> & family,
2100  bool reset) const
2101 {
2102  ElemInternal::family_tree(this, family, reset);
2103 }
2104 
2105 
2106 
2107 void Elem::family_tree (std::vector<Elem *> & family,
2108  bool reset)
2109 {
2110  ElemInternal::family_tree(this, family, reset);
2111 }
2112 
2113 
2114 
2115 void Elem::total_family_tree (std::vector<const Elem *> & family,
2116  bool reset) const
2117 {
2118  ElemInternal::total_family_tree(this, family, reset);
2119 }
2120 
2121 
2122 
2123 void Elem::total_family_tree (std::vector<Elem *> & family,
2124  bool reset)
2125 {
2126  ElemInternal::total_family_tree(this, family, reset);
2127 }
2128 
2129 
2130 
2131 void Elem::active_family_tree (std::vector<const Elem *> & active_family,
2132  bool reset) const
2133 {
2134  ElemInternal::active_family_tree(this, active_family, reset);
2135 }
2136 
2137 
2138 
2139 void Elem::active_family_tree (std::vector<Elem *> & active_family,
2140  bool reset)
2141 {
2142  ElemInternal::active_family_tree(this, active_family, reset);
2143 }
2144 
2145 
2146 
2147 void Elem::family_tree_by_side (std::vector<const Elem *> & family,
2148  unsigned int side,
2149  bool reset) const
2150 {
2151  ElemInternal::family_tree_by_side(this, family, side, reset);
2152 }
2153 
2154 
2155 
2156 void Elem:: family_tree_by_side (std::vector<Elem *> & family,
2157  unsigned int side,
2158  bool reset)
2159 {
2160  ElemInternal::family_tree_by_side(this, family, side, reset);
2161 }
2162 
2163 
2164 
2165 void Elem::active_family_tree_by_side (std::vector<const Elem *> & family,
2166  unsigned int side,
2167  bool reset) const
2168 {
2169  ElemInternal::active_family_tree_by_side(this, family, side, reset);
2170 }
2171 
2172 
2173 
2174 void Elem::active_family_tree_by_side (std::vector<Elem *> & family,
2175  unsigned int side,
2176  bool reset)
2177 {
2178  ElemInternal::active_family_tree_by_side(this, family, side, reset);
2179 }
2180 
2181 
2182 
2183 void Elem::family_tree_by_neighbor (std::vector<const Elem *> & family,
2184  const Elem * neighbor,
2185  bool reset) const
2186 {
2187  ElemInternal::family_tree_by_neighbor(this, family, neighbor, reset);
2188 }
2189 
2190 
2191 
2192 void Elem::family_tree_by_neighbor (std::vector<Elem *> & family,
2193  Elem * neighbor,
2194  bool reset)
2195 {
2196  ElemInternal::family_tree_by_neighbor(this, family, neighbor, reset);
2197 }
2198 
2199 
2200 
2201 void Elem::total_family_tree_by_neighbor (std::vector<const Elem *> & family,
2202  const Elem * neighbor,
2203  bool reset) const
2204 {
2205  ElemInternal::total_family_tree_by_neighbor(this, family, neighbor, reset);
2206 }
2207 
2208 
2209 
2210 void Elem::total_family_tree_by_neighbor (std::vector<Elem *> & family,
2211  Elem * neighbor,
2212  bool reset)
2213 {
2214  ElemInternal::total_family_tree_by_neighbor(this, family, neighbor, reset);
2215 }
2216 
2217 
2218 
2219 void Elem::family_tree_by_subneighbor (std::vector<const Elem *> & family,
2220  const Elem * neighbor,
2221  const Elem * subneighbor,
2222  bool reset) const
2223 {
2224  ElemInternal::family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2225 }
2226 
2227 
2228 
2229 void Elem::family_tree_by_subneighbor (std::vector<Elem *> & family,
2230  Elem * neighbor,
2231  Elem * subneighbor,
2232  bool reset)
2233 {
2234  ElemInternal::family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2235 }
2236 
2237 
2238 
2239 void Elem::total_family_tree_by_subneighbor (std::vector<const Elem *> & family,
2240  const Elem * neighbor,
2241  const Elem * subneighbor,
2242  bool reset) const
2243 {
2244  ElemInternal::total_family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2245 }
2246 
2247 
2248 
2249 void Elem::total_family_tree_by_subneighbor (std::vector<Elem *> & family,
2250  Elem * neighbor,
2251  Elem * subneighbor,
2252  bool reset)
2253 {
2254  ElemInternal::total_family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
2255 }
2256 
2257 
2258 
2259 void Elem::active_family_tree_by_neighbor (std::vector<const Elem *> & family,
2260  const Elem * neighbor,
2261  bool reset) const
2262 {
2263  ElemInternal::active_family_tree_by_neighbor(this, family, neighbor, reset);
2264 }
2265 
2266 
2267 
2268 void Elem::active_family_tree_by_neighbor (std::vector<Elem *> & family,
2269  Elem * neighbor,
2270  bool reset)
2271 {
2272  ElemInternal::active_family_tree_by_neighbor(this, family, neighbor, reset);
2273 }
2274 
2275 
2276 
2277 void Elem::active_family_tree_by_topological_neighbor (std::vector<const Elem *> & family,
2278  const Elem * neighbor,
2279  const MeshBase & mesh,
2280  const PointLocatorBase & point_locator,
2281  const PeriodicBoundaries * pb,
2282  bool reset) const
2283 {
2285  mesh, point_locator, pb,
2286  reset);
2287 }
2288 
2289 
2290 
2291 void Elem::active_family_tree_by_topological_neighbor (std::vector<Elem *> & family,
2292  Elem * neighbor,
2293  const MeshBase & mesh,
2294  const PointLocatorBase & point_locator,
2295  const PeriodicBoundaries * pb,
2296  bool reset)
2297 {
2299  mesh, point_locator, pb,
2300  reset);
2301 }
2302 
2303 
2304 bool Elem::is_child_on_edge(const unsigned int c,
2305  const unsigned int e) const
2306 {
2307  libmesh_assert_less (c, this->n_children());
2308  libmesh_assert_less (e, this->n_edges());
2309 
2310  std::unique_ptr<const Elem> my_edge = this->build_edge_ptr(e);
2311  std::unique_ptr<const Elem> child_edge = this->child_ptr(c)->build_edge_ptr(e);
2312 
2313  // We're assuming that an overlapping child edge has the same
2314  // number and orientation as its parent
2315  return (child_edge->node_id(0) == my_edge->node_id(0) ||
2316  child_edge->node_id(1) == my_edge->node_id(1));
2317 }
2318 
2319 
2320 
2321 unsigned int Elem::min_p_level_by_neighbor(const Elem * neighbor_in,
2322  unsigned int current_min) const
2323 {
2324  libmesh_assert(!this->subactive());
2325  libmesh_assert(neighbor_in->active());
2326 
2327  // If we're an active element this is simple
2328  if (this->active())
2329  return std::min(current_min, this->p_level());
2330 
2331  libmesh_assert(has_neighbor(neighbor_in));
2332 
2333  // The p_level() of an ancestor element is already the minimum
2334  // p_level() of its children - so if that's high enough, we don't
2335  // need to examine any children.
2336  if (current_min <= this->p_level())
2337  return current_min;
2338 
2339  unsigned int min_p_level = current_min;
2340 
2341  for (auto & c : this->child_ref_range())
2342  if (&c != remote_elem && c.has_neighbor(neighbor_in))
2343  min_p_level =
2344  c.min_p_level_by_neighbor(neighbor_in, min_p_level);
2345 
2346  return min_p_level;
2347 }
2348 
2349 
2350 unsigned int Elem::min_new_p_level_by_neighbor(const Elem * neighbor_in,
2351  unsigned int current_min) const
2352 {
2353  libmesh_assert(!this->subactive());
2354  libmesh_assert(neighbor_in->active());
2355 
2356  // If we're an active element this is simple
2357  if (this->active())
2358  {
2359  unsigned int new_p_level = this->p_level();
2360  if (this->p_refinement_flag() == Elem::REFINE)
2361  new_p_level += 1;
2362  if (this->p_refinement_flag() == Elem::COARSEN)
2363  {
2364  libmesh_assert_greater (new_p_level, 0);
2365  new_p_level -= 1;
2366  }
2367  return std::min(current_min, new_p_level);
2368  }
2369 
2370  libmesh_assert(has_neighbor(neighbor_in));
2371 
2372  unsigned int min_p_level = current_min;
2373 
2374  for (auto & c : this->child_ref_range())
2375  if (&c != remote_elem && c.has_neighbor(neighbor_in))
2376  min_p_level =
2377  c.min_new_p_level_by_neighbor(neighbor_in, min_p_level);
2378 
2379  return min_p_level;
2380 }
2381 
2382 
2383 
2384 unsigned int Elem::as_parent_node (unsigned int child,
2385  unsigned int child_node) const
2386 {
2387  const unsigned int nc = this->n_children();
2388  libmesh_assert_less(child, nc);
2389 
2390  // Cached return values, indexed first by embedding_matrix version,
2391  // then by child number, then by child node number.
2392  std::vector<std::vector<std::vector<signed char>>> &
2393  cached_parent_indices = this->_get_parent_indices_cache();
2394 
2395  unsigned int em_vers = this->embedding_matrix_version();
2396 
2397  // We may be updating the cache on one thread, and while that
2398  // happens we can't safely access the cache from other threads.
2399  Threads::spin_mutex::scoped_lock lock(parent_indices_mutex);
2400 
2401  if (em_vers >= cached_parent_indices.size())
2402  cached_parent_indices.resize(em_vers+1);
2403 
2404  if (child >= cached_parent_indices[em_vers].size())
2405  {
2406  const signed char nn = cast_int<signed char>(this->n_nodes());
2407 
2408  cached_parent_indices[em_vers].resize(nc);
2409 
2410  for (unsigned int c = 0; c != nc; ++c)
2411  {
2412  const unsigned int ncn = this->n_nodes_in_child(c);
2413  cached_parent_indices[em_vers][c].resize(ncn);
2414  for (unsigned int cn = 0; cn != ncn; ++cn)
2415  {
2416  for (signed char n = 0; n != nn; ++n)
2417  {
2418  const Real em_val = this->embedding_matrix
2419  (c, cn, n);
2420  if (em_val == 1)
2421  {
2422  cached_parent_indices[em_vers][c][cn] = n;
2423  break;
2424  }
2425 
2426  if (em_val != 0)
2427  {
2428  cached_parent_indices[em_vers][c][cn] =
2429  -1;
2430  break;
2431  }
2432 
2433  // We should never see an all-zero embedding matrix
2434  // row
2435  libmesh_assert_not_equal_to (n+1, nn);
2436  }
2437  }
2438  }
2439  }
2440 
2441  const signed char cache_val =
2442  cached_parent_indices[em_vers][child][child_node];
2443  if (cache_val == -1)
2444  return libMesh::invalid_uint;
2445 
2446  return cached_parent_indices[em_vers][child][child_node];
2447 }
2448 
2449 
2450 
2451 const std::vector<std::pair<unsigned char, unsigned char>> &
2453  unsigned int child_node) const
2454 {
2455  // Indexed first by embedding matrix type, then by child id, then by
2456  // child node, then by bracketing pair
2457  std::vector<std::vector<std::vector<std::vector<std::pair<unsigned char, unsigned char>>>>> &
2458  cached_bracketing_nodes = this->_get_bracketing_node_cache();
2459 
2460  const unsigned int em_vers = this->embedding_matrix_version();
2461 
2462  // We may be updating the cache on one thread, and while that
2463  // happens we can't safely access the cache from other threads.
2464  Threads::spin_mutex::scoped_lock lock(parent_bracketing_nodes_mutex);
2465 
2466  if (cached_bracketing_nodes.size() <= em_vers)
2467  cached_bracketing_nodes.resize(em_vers+1);
2468 
2469  const unsigned int nc = this->n_children();
2470 
2471  // If we haven't cached the bracketing nodes corresponding to this
2472  // embedding matrix yet, let's do so now.
2473  if (cached_bracketing_nodes[em_vers].size() < nc)
2474  {
2475  // If we're a second-order element but we're not a full-order
2476  // element, then some of our bracketing nodes may not exist
2477  // except on the equivalent full-order element. Let's build an
2478  // equivalent full-order element and make a copy of its cache to
2479  // use.
2480  if (this->default_order() != FIRST &&
2481  second_order_equivalent_type(this->type(), /*full_ordered=*/ true) != this->type())
2482  {
2483  // Check that we really are the non-full-order type
2484  libmesh_assert_equal_to
2485  (second_order_equivalent_type (this->type(), false),
2486  this->type());
2487 
2488  // Build the full-order type
2489  ElemType full_type =
2490  second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
2491  std::unique_ptr<Elem> full_elem = Elem::build(full_type);
2492 
2493  // This won't work for elements with multiple
2494  // embedding_matrix versions, but every such element is full
2495  // order anyways.
2496  libmesh_assert_equal_to(em_vers, 0);
2497 
2498  // Make sure its cache has been built. We temporarily
2499  // release our mutex lock so that the inner call can
2500  // re-acquire it.
2501  lock.release();
2502  full_elem->parent_bracketing_nodes(0,0);
2503 
2504  // And then we need to lock again, so that if someone *else*
2505  // grabbed our lock before we did we don't risk accessing
2506  // cached_bracketing_nodes while they're working on it.
2507  // Threading is hard.
2508  lock.acquire(parent_bracketing_nodes_mutex);
2509 
2510  // Copy its cache
2511  cached_bracketing_nodes =
2512  full_elem->_get_bracketing_node_cache();
2513 
2514  // Now we don't need to build the cache ourselves.
2515  return cached_bracketing_nodes[em_vers][child][child_node];
2516  }
2517 
2518  cached_bracketing_nodes[em_vers].resize(nc);
2519 
2520  const unsigned int nn = this->n_nodes();
2521 
2522  // We have to examine each child
2523  for (unsigned int c = 0; c != nc; ++c)
2524  {
2525  const unsigned int ncn = this->n_nodes_in_child(c);
2526 
2527  cached_bracketing_nodes[em_vers][c].resize(ncn);
2528 
2529  // We have to examine each node in that child
2530  for (unsigned int n = 0; n != ncn; ++n)
2531  {
2532  // If this child node isn't a vertex or an infinite
2533  // child element's mid-infinite-edge node, then we need
2534  // to find bracketing nodes on the child.
2535  if (!this->is_vertex_on_child(c, n)
2536 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
2537  && !this->is_mid_infinite_edge_node(n)
2538 #endif
2539  )
2540  {
2541  // Use the embedding matrix to find the child node
2542  // location in parent master element space
2543  Point bracketed_pt;
2544 
2545  for (unsigned int pn = 0; pn != nn; ++pn)
2546  {
2547  const Real em_val =
2548  this->embedding_matrix(c,n,pn);
2549 
2550  libmesh_assert_not_equal_to (em_val, 1);
2551  if (em_val != 0.)
2552  bracketed_pt.add_scaled(this->master_point(pn), em_val);
2553  }
2554 
2555  // Check each pair of nodes on the child which are
2556  // also both parent nodes
2557  for (unsigned int n1 = 0; n1 != ncn; ++n1)
2558  {
2559  if (n1 == n)
2560  continue;
2561 
2562  unsigned int parent_n1 =
2563  this->as_parent_node(c,n1);
2564 
2565  if (parent_n1 == libMesh::invalid_uint)
2566  continue;
2567 
2568  Point p1 = this->master_point(parent_n1);
2569 
2570  for (unsigned int n2 = n1+1; n2 < nn; ++n2)
2571  {
2572  if (n2 == n)
2573  continue;
2574 
2575  unsigned int parent_n2 =
2576  this->as_parent_node(c,n2);
2577 
2578  if (parent_n2 == libMesh::invalid_uint)
2579  continue;
2580 
2581  Point p2 = this->master_point(parent_n2);
2582 
2583  Point pmid = (p1 + p2)/2;
2584 
2585  if (pmid == bracketed_pt)
2586  {
2587  cached_bracketing_nodes[em_vers][c][n].emplace_back(parent_n1, parent_n2);
2588  break;
2589  }
2590  else
2591  libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
2592  }
2593  }
2594  }
2595  // If this child node is a parent node, we need to
2596  // find bracketing nodes on the parent.
2597  else
2598  {
2599  unsigned int parent_node = this->as_parent_node(c,n);
2600 
2601  Point bracketed_pt;
2602 
2603  // If we're not a parent node, use the embedding
2604  // matrix to find the child node location in parent
2605  // master element space
2606  if (parent_node == libMesh::invalid_uint)
2607  {
2608  for (unsigned int pn = 0; pn != nn; ++pn)
2609  {
2610  const Real em_val =
2611  this->embedding_matrix(c,n,pn);
2612 
2613  libmesh_assert_not_equal_to (em_val, 1);
2614  if (em_val != 0.)
2615  bracketed_pt.add_scaled(this->master_point(pn), em_val);
2616  }
2617  }
2618  // If we're a parent node then we need no arithmetic
2619  else
2620  bracketed_pt = this->master_point(parent_node);
2621 
2622  for (unsigned int n1 = 0; n1 != nn; ++n1)
2623  {
2624  if (n1 == parent_node)
2625  continue;
2626 
2627  Point p1 = this->master_point(n1);
2628 
2629  for (unsigned int n2 = n1+1; n2 < nn; ++n2)
2630  {
2631  if (n2 == parent_node)
2632  continue;
2633 
2634  Point pmid = (p1 + this->master_point(n2))/2;
2635 
2636  if (pmid == bracketed_pt)
2637  {
2638  cached_bracketing_nodes[em_vers][c][n].emplace_back(n1, n2);
2639  break;
2640  }
2641  else
2642  libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
2643  }
2644  }
2645  }
2646  }
2647  }
2648  }
2649 
2650  return cached_bracketing_nodes[em_vers][child][child_node];
2651 }
2652 
2653 
2654 const std::vector<std::pair<dof_id_type, dof_id_type>>
2655 Elem::bracketing_nodes(unsigned int child,
2656  unsigned int child_node) const
2657 {
2658  std::vector<std::pair<dof_id_type, dof_id_type>> returnval;
2659 
2660  const std::vector<std::pair<unsigned char, unsigned char>> & pbc =
2661  this->parent_bracketing_nodes(child,child_node);
2662 
2663  for (const auto & pb : pbc)
2664  {
2665  const unsigned short n_n = this->n_nodes();
2666  if (pb.first < n_n && pb.second < n_n)
2667  returnval.emplace_back(this->node_id(pb.first), this->node_id(pb.second));
2668  else
2669  {
2670  // We must be on a non-full-order higher order element...
2671  libmesh_assert_not_equal_to(this->default_order(), FIRST);
2672  libmesh_assert_not_equal_to
2673  (second_order_equivalent_type (this->type(), true),
2674  this->type());
2675  libmesh_assert_equal_to
2676  (second_order_equivalent_type (this->type(), false),
2677  this->type());
2678 
2679  // And that's a shame, because this is a nasty search:
2680 
2681  // Build the full-order type
2682  ElemType full_type =
2683  second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
2684  std::unique_ptr<Elem> full_elem = Elem::build(full_type);
2685 
2688 
2689  // Find the bracketing nodes by figuring out what
2690  // already-created children will have them.
2691 
2692  // This only doesn't break horribly because we add children
2693  // and nodes in straightforward + hierarchical orders...
2694  for (unsigned int c=0; c <= child; ++c)
2695  {
2696  libmesh_assert(this->child_ptr(c));
2697  if (this->child_ptr(c) == remote_elem)
2698  continue;
2699 
2700  for (auto n : make_range(this->n_nodes_in_child(c)))
2701  {
2702  if (c == child && n == child_node)
2703  break;
2704 
2705  if (pb.first == full_elem->as_parent_node(c,n))
2706  {
2707  // We should be consistent
2708  if (pt1 != DofObject::invalid_id)
2709  libmesh_assert_equal_to(pt1, this->child_ptr(c)->node_id(n));
2710 
2711  pt1 = this->child_ptr(c)->node_id(n);
2712  }
2713 
2714  if (pb.second == full_elem->as_parent_node(c,n))
2715  {
2716  // We should be consistent
2717  if (pt2 != DofObject::invalid_id)
2718  libmesh_assert_equal_to(pt2, this->child_ptr(c)->node_id(n));
2719 
2720  pt2 = this->child_ptr(c)->node_id(n);
2721  }
2722  }
2723  }
2724 
2725  // We should *usually* find all bracketing nodes by the time
2726  // we query them (again, because of the child & node add
2727  // order)
2728  //
2729  // The exception is if we're a HEX20, in which case we will
2730  // find pairs of vertex nodes and edge nodes bracketing the
2731  // new central node but we *won't* find the pairs of face
2732  // nodes which we would have had on a HEX27. In that case
2733  // we'll still have enough bracketing nodes for a
2734  // topological lookup, but we won't be able to make the
2735  // following assertions.
2736  if (this->type() != HEX20)
2737  {
2738  libmesh_assert_not_equal_to (pt1, DofObject::invalid_id);
2739  libmesh_assert_not_equal_to (pt2, DofObject::invalid_id);
2740  }
2741 
2742  if (pt1 != DofObject::invalid_id &&
2743  pt2 != DofObject::invalid_id)
2744  returnval.emplace_back(pt1, pt2);
2745  }
2746  }
2747 
2748  return returnval;
2749 }
2750 #endif // #ifdef LIBMESH_ENABLE_AMR
2751 
2752 
2753 
2754 
2755 bool Elem::contains_point (const Point & p, Real tol) const
2756 {
2757  // We currently allow the user to enlarge the bounding box by
2758  // providing a tol > TOLERANCE (so this routine is identical to
2759  // Elem::close_to_point()), but print a warning so that the
2760  // user can eventually switch his code over to calling close_to_point()
2761  // instead, which is intended to be used for this purpose.
2762  if (tol > TOLERANCE)
2763  {
2764  libmesh_do_once(libMesh::err
2765  << "WARNING: Resizing bounding box to match user-specified tolerance!\n"
2766  << "In the future, calls to Elem::contains_point() with tol > TOLERANCE\n"
2767  << "will be more optimized, but should not be used\n"
2768  << "to search for points 'close to' elements!\n"
2769  << "Instead, use Elem::close_to_point() for this purpose.\n"
2770  << std::endl;);
2771  return this->point_test(p, tol, tol);
2772  }
2773  else
2774  return this->point_test(p, TOLERANCE, tol);
2775 }
2776 
2777 
2778 
2779 
2780 bool Elem::close_to_point (const Point & p, Real tol) const
2781 {
2782  // This test uses the user's passed-in tolerance for the
2783  // bounding box test as well, thereby allowing the routine to
2784  // find points which are not only "in" the element, but also
2785  // "nearby" to within some tolerance.
2786  return this->point_test(p, tol, tol);
2787 }
2788 
2789 
2790 
2791 
2792 bool Elem::point_test(const Point & p, Real box_tol, Real map_tol) const
2793 {
2794  libmesh_assert_greater (box_tol, 0.);
2795  libmesh_assert_greater (map_tol, 0.);
2796 
2797  // This is a great optimization on first order elements, but it
2798  // could return false negatives on higher orders
2799  if (this->default_order() == FIRST)
2800  {
2801  // Check to make sure the element *could* contain this point, so we
2802  // can avoid an expensive inverse_map call if it doesn't.
2803  bool
2804 #if LIBMESH_DIM > 2
2805  point_above_min_z = false,
2806  point_below_max_z = false,
2807 #endif
2808 #if LIBMESH_DIM > 1
2809  point_above_min_y = false,
2810  point_below_max_y = false,
2811 #endif
2812  point_above_min_x = false,
2813  point_below_max_x = false;
2814 
2815  // For relative bounding box checks in physical space
2816  const Real my_hmax = this->hmax();
2817 
2818  for (auto & n : this->node_ref_range())
2819  {
2820  point_above_min_x = point_above_min_x || (n(0) - my_hmax*box_tol <= p(0));
2821  point_below_max_x = point_below_max_x || (n(0) + my_hmax*box_tol >= p(0));
2822 #if LIBMESH_DIM > 1
2823  point_above_min_y = point_above_min_y || (n(1) - my_hmax*box_tol <= p(1));
2824  point_below_max_y = point_below_max_y || (n(1) + my_hmax*box_tol >= p(1));
2825 #endif
2826 #if LIBMESH_DIM > 2
2827  point_above_min_z = point_above_min_z || (n(2) - my_hmax*box_tol <= p(2));
2828  point_below_max_z = point_below_max_z || (n(2) + my_hmax*box_tol >= p(2));
2829 #endif
2830  }
2831 
2832  if (
2833 #if LIBMESH_DIM > 2
2834  !point_above_min_z ||
2835  !point_below_max_z ||
2836 #endif
2837 #if LIBMESH_DIM > 1
2838  !point_above_min_y ||
2839  !point_below_max_y ||
2840 #endif
2841  !point_above_min_x ||
2842  !point_below_max_x)
2843  return false;
2844  }
2845 
2846  // To be on the safe side, we converge the inverse_map() iteration
2847  // to a slightly tighter tolerance than that requested by the
2848  // user...
2849  const Point mapped_point = FEMap::inverse_map(this->dim(),
2850  this,
2851  p,
2852  0.1*map_tol, // <- this is |dx| tolerance, the Newton residual should be ~ |dx|^2
2853  /*secure=*/ false,
2854  /*extra_checks=*/ false);
2855 
2856  // Check that the refspace point maps back to p! This is only necessary
2857  // for 1D and 2D elements, 3D elements always live in 3D.
2858  //
2859  // TODO: The contains_point() function could most likely be implemented
2860  // more efficiently in the element sub-classes themselves, at least for
2861  // the linear element types.
2862  if (this->dim() < 3)
2863  {
2864  Point xyz = FEMap::map(this->dim(), this, mapped_point);
2865 
2866  // Compute the distance between the original point and the re-mapped point.
2867  // They should be in the same place.
2868  Real dist = (xyz - p).norm();
2869 
2870 
2871  // If dist is larger than some fraction of the tolerance, then return false.
2872  // This can happen when e.g. a 2D element is living in 3D, and
2873  // FEMap::inverse_map() maps p onto the projection of the element,
2874  // effectively "tricking" on_reference_element().
2875  if (dist > this->hmax() * map_tol)
2876  return false;
2877  }
2878 
2879  return this->on_reference_element(mapped_point, map_tol);
2880 }
2881 
2882 
2883 
2884 
2885 bool Elem::has_invertible_map(Real /*tol*/) const
2886 {
2887  QNodal qnodal {this->dim()};
2888  FEMap fe_map;
2889  auto & jac = fe_map.get_jacobian();
2890 
2891  // We have a separate check for is_singular_node() below, so in this
2892  // case its "OK" to do nodal quadrature on pyramids.
2893  qnodal.allow_nodal_pyramid_quadrature = true;
2894  qnodal.init(*this);
2895  auto & qp = qnodal.get_points();
2896  libmesh_assert_equal_to(qp.size(), this->n_nodes());
2897 
2898  std::vector<Point> one_point(1);
2899  std::vector<Real> one_weight(1,1);
2900  for (auto i : index_range(qp))
2901  {
2902  if (this->is_singular_node(i))
2903  continue;
2904 
2905  one_point[0] = qp[i];
2906 
2907  fe_map.init_reference_to_physical_map(this->dim(), one_point, this);
2908  fe_map.compute_map(this->dim(), one_weight, this, false);
2909 
2910  if (jac[0] <= 0)
2911  return false;
2912  }
2913 
2914  return true;
2915 }
2916 
2917 
2918 
2919 void Elem::print_info (std::ostream & os) const
2920 {
2921  os << this->get_info()
2922  << std::endl;
2923 }
2924 
2925 
2926 
2927 std::string Elem::get_info () const
2928 {
2929  std::ostringstream oss;
2930 
2931  oss << " Elem Information" << '\n'
2932  << " id()=";
2933 
2934  if (this->valid_id())
2935  oss << this->id();
2936  else
2937  oss << "invalid";
2938 
2939 #ifdef LIBMESH_ENABLE_UNIQUE_ID
2940  oss << ", unique_id()=";
2941  if (this->valid_unique_id())
2942  oss << this->unique_id();
2943  else
2944  oss << "invalid";
2945 #endif
2946 
2947  oss << ", subdomain_id()=" << this->subdomain_id();
2948  oss << ", processor_id()=" << this->processor_id() << '\n';
2949 
2950  oss << " type()=" << Utility::enum_to_string(this->type()) << '\n'
2951  << " dim()=" << this->dim() << '\n'
2952  << " n_nodes()=" << this->n_nodes() << '\n';
2953 
2954  oss << " mapping=" << Utility::enum_to_string(this->mapping_type()) << '\n';
2955 
2956  for (auto n : this->node_index_range())
2957  {
2958  oss << " " << n << this->node_ref(n);
2959  if (this->mapping_type() == RATIONAL_BERNSTEIN_MAP)
2960  {
2961  const unsigned char datum_index = this->mapping_data();
2962  oss << " weight=" <<
2963  this->node_ref(n).get_extra_datum<Real>(datum_index) << '\n';
2964  }
2965  }
2966 
2967  oss << " n_sides()=" << this->n_sides() << '\n';
2968 
2969  for (auto s : this->side_index_range())
2970  {
2971  oss << " neighbor(" << s << ")=";
2972  if (this->neighbor_ptr(s))
2973  oss << this->neighbor_ptr(s)->id() << '\n';
2974  else
2975  oss << "nullptr\n";
2976  }
2977 
2978  if (!this->infinite())
2979  {
2980  oss << " hmin()=" << this->hmin()
2981  << ", hmax()=" << this->hmax() << '\n'
2982  << " volume()=" << this->volume() << '\n';
2983  }
2984  oss << " active()=" << this->active()
2985  << ", ancestor()=" << this->ancestor()
2986  << ", subactive()=" << this->subactive()
2987  << ", has_children()=" << this->has_children() << '\n'
2988  << " parent()=";
2989  if (this->parent())
2990  oss << this->parent()->id() << '\n';
2991  else
2992  oss << "nullptr\n";
2993  oss << " level()=" << this->level()
2994  << ", p_level()=" << this->p_level() << '\n'
2995 #ifdef LIBMESH_ENABLE_AMR
2996  << " refinement_flag()=" << Utility::enum_to_string(this->refinement_flag()) << '\n'
2997  << " p_refinement_flag()=" << Utility::enum_to_string(this->p_refinement_flag()) << '\n'
2998 #endif
2999 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
3000  << " infinite()=" << this->infinite() << '\n';
3001  if (this->infinite())
3002  oss << " origin()=" << this->origin() << '\n'
3003 #endif
3004  ;
3005 
3006  oss << " DoFs=";
3007  for (auto s : make_range(this->n_systems()))
3008  for (auto v : make_range(this->n_vars(s)))
3009  for (auto c : make_range(this->n_comp(s,v)))
3010  oss << '(' << s << '/' << v << '/' << this->dof_number(s,v,c) << ") ";
3011 
3012 
3013  return oss.str();
3014 }
3015 
3016 
3017 
3019 {
3020  // Tell any of my neighbors about my death...
3021  // Looks strange, huh?
3022  for (auto n : this->side_index_range())
3023  {
3024  Elem * current_neighbor = this->neighbor_ptr(n);
3025  if (current_neighbor && current_neighbor != remote_elem)
3026  {
3027  // Note: it is possible that I see the neighbor
3028  // (which is coarser than me)
3029  // but they don't see me, so avoid that case.
3030  if (current_neighbor->level() == this->level())
3031  {
3032  const unsigned int w_n_a_i = current_neighbor->which_neighbor_am_i(this);
3033  libmesh_assert_less (w_n_a_i, current_neighbor->n_neighbors());
3034  current_neighbor->set_neighbor(w_n_a_i, nullptr);
3035  this->set_neighbor(n, nullptr);
3036  }
3037  }
3038  }
3039 }
3040 
3041 
3042 
3043 
3044 unsigned int Elem::n_second_order_adjacent_vertices (const unsigned int) const
3045 {
3046  // for linear elements, always return 0
3047  return 0;
3048 }
3049 
3050 
3051 
3052 unsigned short int Elem::second_order_adjacent_vertex (const unsigned int,
3053  const unsigned int) const
3054 {
3055  // for linear elements, always return 0
3056  return 0;
3057 }
3058 
3059 
3060 
3061 std::pair<unsigned short int, unsigned short int>
3062 Elem::second_order_child_vertex (const unsigned int) const
3063 {
3064  // for linear elements, always return 0
3065  return std::pair<unsigned short int, unsigned short int>(0,0);
3066 }
3067 
3068 
3069 
3071 {
3072  switch (et)
3073  {
3074  case NODEELEM:
3075  return NODEELEM;
3076  case EDGE2:
3077  case EDGE3:
3078  case EDGE4:
3079  return EDGE2;
3080  case TRI3:
3081  case TRI6:
3082  case TRI7:
3083  return TRI3;
3084  case TRISHELL3:
3085  return TRISHELL3;
3086  case QUAD4:
3087  case QUAD8:
3088  case QUAD9:
3089  return QUAD4;
3090  case QUADSHELL4:
3091  case QUADSHELL8:
3092  case QUADSHELL9:
3093  return QUADSHELL4;
3094  case TET4:
3095  case TET10:
3096  case TET14:
3097  return TET4;
3098  case HEX8:
3099  case HEX27:
3100  case HEX20:
3101  return HEX8;
3102  case PRISM6:
3103  case PRISM15:
3104  case PRISM18:
3105  case PRISM20:
3106  case PRISM21:
3107  return PRISM6;
3108  case PYRAMID5:
3109  case PYRAMID13:
3110  case PYRAMID14:
3111  case PYRAMID18:
3112  return PYRAMID5;
3113 
3114 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
3115 
3116  case INFEDGE2:
3117  return INFEDGE2;
3118  case INFQUAD4:
3119  case INFQUAD6:
3120  return INFQUAD4;
3121  case INFHEX8:
3122  case INFHEX16:
3123  case INFHEX18:
3124  return INFHEX8;
3125  case INFPRISM6:
3126  case INFPRISM12:
3127  return INFPRISM6;
3128 
3129 #endif
3130 
3131  default:
3132  // unknown element
3133  return INVALID_ELEM;
3134  }
3135 }
3136 
3137 
3138 
3140  const bool full_ordered)
3141 {
3142  switch (et)
3143  {
3144  case NODEELEM:
3145  return NODEELEM;
3146  case EDGE2:
3147  case EDGE3:
3148  {
3149  // full_ordered not relevant
3150  return EDGE3;
3151  }
3152 
3153  case EDGE4:
3154  {
3155  // full_ordered not relevant
3156  return EDGE4;
3157  }
3158 
3159  case TRI3:
3160  case TRI6:
3161  {
3162  // full_ordered not relevant
3163  return TRI6;
3164  }
3165 
3166  case TRI7:
3167  return TRI7;
3168 
3169  // Currently there is no TRISHELL6, so similarly to other types
3170  // where this is the case, we just return the input.
3171  case TRISHELL3:
3172  return TRISHELL3;
3173 
3174  case QUAD4:
3175  case QUAD8:
3176  {
3177  if (full_ordered)
3178  return QUAD9;
3179  else
3180  return QUAD8;
3181  }
3182 
3183  case QUADSHELL4:
3184  case QUADSHELL8:
3185  {
3186  if (full_ordered)
3187  return QUADSHELL9;
3188  else
3189  return QUADSHELL8;
3190  }
3191 
3192  case QUAD9:
3193  {
3194  // full_ordered not relevant
3195  return QUAD9;
3196  }
3197 
3198  case QUADSHELL9:
3199  {
3200  // full_ordered not relevant
3201  return QUADSHELL9;
3202  }
3203 
3204  case TET4:
3205  case TET10:
3206  {
3207  // full_ordered not relevant
3208  return TET10;
3209  }
3210 
3211  case TET14:
3212  return TET14;
3213 
3214  case HEX8:
3215  case HEX20:
3216  {
3217  // see below how this correlates with INFHEX8
3218  if (full_ordered)
3219  return HEX27;
3220  else
3221  return HEX20;
3222  }
3223 
3224  case HEX27:
3225  {
3226  // full_ordered not relevant
3227  return HEX27;
3228  }
3229 
3230  case PRISM6:
3231  case PRISM15:
3232  {
3233  if (full_ordered)
3234  return PRISM18;
3235  else
3236  return PRISM15;
3237  }
3238 
3239  // full_ordered not relevant, already fully second order
3240  case PRISM18:
3241  return PRISM18;
3242  case PRISM20:
3243  return PRISM20;
3244  case PRISM21:
3245  return PRISM21;
3246  case PYRAMID18:
3247  return PYRAMID18;
3248 
3249  case PYRAMID5:
3250  case PYRAMID13:
3251  {
3252  if (full_ordered)
3253  return PYRAMID14;
3254  else
3255  return PYRAMID13;
3256  }
3257 
3258  case PYRAMID14:
3259  {
3260  // full_ordered not relevant
3261  return PYRAMID14;
3262  }
3263 
3264 
3265 
3266 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
3267 
3268  // infinite elements
3269  case INFEDGE2:
3270  {
3271  return INFEDGE2;
3272  }
3273 
3274  case INFQUAD4:
3275  case INFQUAD6:
3276  {
3277  // full_ordered not relevant
3278  return INFQUAD6;
3279  }
3280 
3281  case INFHEX8:
3282  case INFHEX16:
3283  {
3284  /*
3285  * Note that this matches with \p Hex8:
3286  * For full-ordered, \p InfHex18 and \p Hex27
3287  * belong together, and for not full-ordered,
3288  * \p InfHex16 and \p Hex20 belong together.
3289  */
3290  if (full_ordered)
3291  return INFHEX18;
3292  else
3293  return INFHEX16;
3294  }
3295 
3296  case INFHEX18:
3297  {
3298  // full_ordered not relevant
3299  return INFHEX18;
3300  }
3301 
3302  case INFPRISM6:
3303  case INFPRISM12:
3304  {
3305  // full_ordered not relevant
3306  return INFPRISM12;
3307  }
3308 
3309 #endif
3310 
3311 
3312  default:
3313  {
3314  // what did we miss?
3315  libmesh_error_msg("No second order equivalent element type for et = "
3316  << Utility::enum_to_string(et));
3317  }
3318  }
3319 }
3320 
3321 
3322 
3324 {
3325  switch (et)
3326  {
3327  case NODEELEM:
3328  return NODEELEM;
3329  case EDGE2:
3330  case EDGE3:
3331  return EDGE3;
3332 
3333  case EDGE4:
3334  return EDGE4;
3335 
3336  case TRI3:
3337  case TRI6:
3338  case TRI7:
3339  return TRI7;
3340 
3341  // Currently there is no TRISHELL6, so similarly to other types
3342  // where this is the case, we just return the input.
3343  case TRISHELL3:
3344  return TRISHELL3;
3345 
3346  case QUAD4:
3347  case QUAD8:
3348  case QUAD9:
3349  return QUAD9;
3350 
3351  case QUADSHELL4:
3352  case QUADSHELL8:
3353  case QUADSHELL9:
3354  return QUADSHELL9;
3355 
3356  case TET4:
3357  case TET10:
3358  case TET14:
3359  return TET14;
3360 
3361  case HEX8:
3362  case HEX20:
3363  case HEX27:
3364  return HEX27;
3365 
3366  // We don't strictly need the 21st node for DoFs, but some code
3367  // depends on it for e.g. refinement patterns
3368  case PRISM6:
3369  case PRISM15:
3370  case PRISM18:
3371  case PRISM20:
3372  case PRISM21:
3373  return PRISM21;
3374 
3375  case PYRAMID5:
3376  case PYRAMID13:
3377  case PYRAMID14:
3378  case PYRAMID18:
3379  return PYRAMID18;
3380 
3381 
3382 
3383 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
3384  case INFEDGE2:
3385  return INFEDGE2;
3386 
3387  case INFQUAD4:
3388  case INFQUAD6:
3389  return INFQUAD6;
3390 
3391  case INFHEX8:
3392  case INFHEX16:
3393  case INFHEX18:
3394  return INFHEX18;
3395 
3396  // Probably ought to implement INFPRISM13 and/or 14; until then
3397  // we'll just return the not-complete-order ElemType, in
3398  // accordance which what seems like bad precedent...
3399  case INFPRISM6:
3400  case INFPRISM12:
3401  return INFPRISM12;
3402 #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS
3403 
3404  default:
3405  {
3406  // what did we miss?
3407  libmesh_error_msg("No complete order equivalent element type for et = "
3408  << Utility::enum_to_string(et));
3409  }
3410  }
3411 }
3412 
3413 
3414 
3416 {
3418  return side_iterator(this->_first_side(), this->_last_side(), bsp);
3419 }
3420 
3421 
3422 
3423 
3425 {
3427  return side_iterator(this->_last_side(), this->_last_side(), bsp);
3428 }
3429 
3430 
3431 
3432 
3434 {
3435  // The default implementation builds a finite element of the correct
3436  // order and sums up the JxW contributions. This can be expensive,
3437  // so the various element types can overload this method and compute
3438  // the volume more efficiently.
3439  const FEFamily mapping_family = FEMap::map_fe_type(*this);
3440  const FEType fe_type(this->default_order(), mapping_family);
3441 
3442  std::unique_ptr<FEBase> fe (FEBase::build(this->dim(),
3443  fe_type));
3444 
3445  // Use a map with a negative Jacobian tolerance, in case we're asked
3446  // for the net volume of a tangled element
3447  fe->get_fe_map().set_jacobian_tolerance(std::numeric_limits<Real>::lowest());
3448 
3449  const std::vector<Real> & JxW = fe->get_JxW();
3450 
3451  // The default quadrature rule should integrate the mass matrix,
3452  // thus it should be plenty to compute the area
3453  QGauss qrule (this->dim(), fe_type.default_quadrature_order());
3454 
3455  fe->attach_quadrature_rule(&qrule);
3456 
3457  fe->reinit(this);
3458 
3459  Real vol=0.;
3460  for (auto jxw : JxW)
3461  vol += jxw;
3462 
3463  return vol;
3464 
3465 }
3466 
3467 
3468 
3470 {
3471  Point pmin = this->point(0);
3472  Point pmax = pmin;
3473 
3474  unsigned int n_points = this->n_nodes();
3475  for (unsigned int p=0; p != n_points; ++p)
3476  for (unsigned d=0; d<LIBMESH_DIM; ++d)
3477  {
3478  const Point & pt = this->point(p);
3479  if (pmin(d) > pt(d))
3480  pmin(d) = pt(d);
3481 
3482  if (pmax(d) < pt(d))
3483  pmax(d) = pt(d);
3484  }
3485 
3486  return BoundingBox(pmin, pmax);
3487 }
3488 
3489 Point
3490 Elem::side_vertex_average_normal(const unsigned int s) const
3491 {
3492  unsigned int dim = this->dim();
3493  const std::unique_ptr<const Elem> face = this->build_side_ptr(s);
3494  std::unique_ptr<libMesh::FEBase> fe(
3496  const std::vector<Point> & normals = fe->get_normals();
3497  std::vector<Point> ref_side_vertex_average_v = {face->reference_elem()->vertex_average()};
3498  fe->reinit(this, s, TOLERANCE, &ref_side_vertex_average_v);
3499  return normals[0];
3500 }
3501 
3502 bool Elem::is_vertex_on_parent(unsigned int c,
3503  unsigned int n) const
3504 {
3505 #ifdef LIBMESH_ENABLE_AMR
3506 
3507  unsigned int my_n_vertices = this->n_vertices();
3508  for (unsigned int n_parent = 0; n_parent != my_n_vertices;
3509  ++n_parent)
3510  if (this->node_ptr(n_parent) == this->child_ptr(c)->node_ptr(n))
3511  return true;
3512  return false;
3513 
3514 #else
3515 
3516  // No AMR?
3517  libmesh_ignore(c,n);
3518  libmesh_error_msg("ERROR: AMR disabled, how did we get here?");
3519  return true;
3520 
3521 #endif
3522 }
3523 
3524 
3525 
3526 unsigned int Elem::opposite_side(const unsigned int /*s*/) const
3527 {
3528  // If the subclass didn't rederive this, using it is an error
3529  libmesh_not_implemented();
3530 }
3531 
3532 
3533 
3534 unsigned int Elem::opposite_node(const unsigned int /*n*/,
3535  const unsigned int /*s*/) const
3536 {
3537  // If the subclass didn't rederive this, using it is an error
3538  libmesh_not_implemented();
3539 }
3540 
3541 
3542 unsigned int Elem::center_node_on_side(const unsigned short libmesh_dbg_var(side)) const
3543 {
3544  libmesh_assert_less (side, this->n_sides());
3545  return invalid_uint;
3546 }
3547 
3548 
3549 void Elem::swap2boundarysides(unsigned short s1,
3550  unsigned short s2,
3551  BoundaryInfo * boundary_info) const
3552 {
3553  std::vector<boundary_id_type> ids1, ids2;
3554  boundary_info->boundary_ids(this, s1, ids1);
3555  boundary_info->boundary_ids(this, s2, ids2);
3556  boundary_info->remove_side(this, s1);
3557  boundary_info->remove_side(this, s2);
3558  if (!ids1.empty())
3559  boundary_info->add_side(this, s2, ids1);
3560  if (!ids2.empty())
3561  boundary_info->add_side(this, s1, ids2);
3562 }
3563 
3564 
3565 void Elem::swap2boundaryedges(unsigned short e1,
3566  unsigned short e2,
3567  BoundaryInfo * boundary_info) const
3568 {
3569  std::vector<boundary_id_type> ids1, ids2;
3570  boundary_info->edge_boundary_ids(this, e1, ids1);
3571  boundary_info->edge_boundary_ids(this, e2, ids2);
3572  boundary_info->remove_edge(this, e1);
3573  boundary_info->remove_edge(this, e2);
3574  if (!ids1.empty())
3575  boundary_info->add_edge(this, e2, ids1);
3576  if (!ids2.empty())
3577  boundary_info->add_edge(this, e1, ids2);
3578 }
3579 
3580 bool
3581 Elem::is_internal(const unsigned int i) const
3582 {
3583  switch (this->dim())
3584  {
3585  case 0:
3586  return false;
3587 
3588  case 1:
3589  return !this->is_vertex(i);
3590 
3591  case 2:
3592  return !this->is_vertex(i) && !this->is_edge(i);
3593 
3594  case 3:
3595  return !this->is_vertex(i) && !this->is_edge(i) && !this->is_face(i);
3596 
3597  default:
3598  libmesh_error_msg("impossible element dimension " << std::to_string(this->dim()));
3599  return 0;
3600  }
3601 }
3602 
3603 bool
3604 Elem::positive_edge_orientation(const unsigned int i) const
3605 {
3606  libmesh_assert_less (i, this->n_edges());
3607 
3608  return this->point(this->local_edge_node(i, 0)) >
3609  this->point(this->local_edge_node(i, 1));
3610 }
3611 
3612 bool
3613 Elem::positive_face_orientation(const unsigned int i) const
3614 {
3615  libmesh_assert_less (i, this->n_faces());
3616 
3617  // Get the number of vertices N of face i. Note that for 3d elements, i.e.
3618  // elements for which this->n_faces() > 0, the number of vertices on any of
3619  // its sides (or faces) is just the number of that face's sides (or edges).
3620  auto side_i = this->side_ptr(i);
3621  const unsigned int N = side_i->n_sides();
3622 
3623  const std::vector<unsigned int> nodes = this->nodes_on_side(i);
3624 
3625  auto cmp = [&](const unsigned int & m, const unsigned int & n) -> bool
3626  { return this->point(m) < this->point(n); };
3627 
3628  const unsigned int V = std::distance(nodes.begin(),
3629  std::min_element(nodes.begin(), nodes.begin() + N, cmp));
3630 
3631  return cmp(nodes[(V + N - 1) % N], nodes[(V + 1) % N]);
3632 }
3633 
3634 } // namespace libMesh
virtual Point true_centroid() const
Definition: elem.C:592
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, bool reset=true) const
Same as the active_family_tree_by_neighbor() member, but the neighbor here may be a topological (e...
Definition: elem.C:2277
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
OStreamProxy err
bool has_neighbor(const Elem *elem) const
Definition: elem.h:2629
unsigned char mapping_data() const
Definition: elem.h:3137
virtual bool is_vertex_on_parent(unsigned int c, unsigned int n) const
Definition: elem.C:3502
static const Order type_to_default_order_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the default approximation order of...
Definition: elem.h:992
RefinementState refinement_flag() const
Definition: elem.h:3211
ElemType
Defines an enum for geometric element types.
void swap2boundaryedges(unsigned short e1, unsigned short e2, BoundaryInfo *boundary_info) const
Swaps two edges in boundary_info, if it is non-null.
Definition: elem.C:3565
void total_family_tree(T elem, std::vector< T > &family, bool reset)
Definition: elem_internal.h:67
dof_id_type dof_number(const unsigned int s, const unsigned int var, const unsigned int comp) const
Definition: dof_object.h:1032
void write_connectivity(std::ostream &out, const IOPackage iop) const
Writes the element connectivity for various IO packages to the passed ostream "out".
Definition: elem.C:1729
const Elem * parent() const
Definition: elem.h:3031
void add_scaled(const TypeVector< T2 > &, const T &)
Add a scaled value to this vector without creating a temporary.
Definition: type_vector.h:629
virtual const std::vector< std::pair< dof_id_type, dof_id_type > > bracketing_nodes(unsigned int c, unsigned int n) const
Definition: elem.C:2655
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
void print_info(std::ostream &os=libMesh::out) const
Prints relevant information about the element.
Definition: elem.C:2919
void active_family_tree_by_side(std::vector< const Elem *> &family, unsigned int side, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to side...
Definition: elem.C:2165
void remove_edge(const Elem *elem, const unsigned short int edge)
Removes all boundary conditions associated with edge edge of element elem, if any exist...
A Node is like a Point, but with more information.
Definition: node.h:52
Node ** _nodes
Pointers to the nodes we are connected to.
Definition: elem.h:2246
virtual std::vector< unsigned int > sides_on_edge(const unsigned int) const =0
static ElemType complete_order_equivalent_type(const ElemType et)
Definition: elem.C:3323
virtual Point origin() const
Definition: elem.h:1915
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition: libmesh.h:310
unsigned int n_comp(const unsigned int s, const unsigned int var) const
Definition: dof_object.h:1002
virtual void compute_map(const unsigned int dim, const std::vector< Real > &qw, const Elem *elem, bool calculate_d2phi)
Compute the jacobian and some other additional data fields.
Definition: fe_map.C:1439
std::string get_info() const
Prints relevant information about the element to a string.
Definition: elem.C:2927
static const unsigned int type_to_n_sides_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of sides on the element...
Definition: elem.h:680
void find_interior_neighbors(T this_elem, std::set< T > &neighbor_set)
const Elem * interior_parent() const
Definition: elem.C:1184
const Elem * topological_neighbor(const unsigned int i, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:1311
virtual bool is_face(const unsigned int i) const =0
bool is_semilocal(const processor_id_type my_pid) const
Definition: elem.C:853
void total_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
This class implements nodal quadrature rules for various element types.
IntRange< unsigned short > side_index_range() const
Definition: elem.h:2711
void libmesh_assert_valid_node_pointers() const
Checks for a valid id and pointers to nodes with valid ids on this element.
Definition: elem.C:1369
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i)=0
void active_family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
virtual dof_id_type key() const
Definition: elem.C:751
static constexpr Real TOLERANCE
static Point inverse_map(const unsigned int dim, const Elem *elem, const Point &p, const Real tolerance=TOLERANCE, const bool secure=true, const bool extra_checks=true)
Definition: fe_map.C:1628
void active_family_tree(T elem, std::vector< T > &active_family, bool reset=true)
Definition: elem_internal.h:90
We&#39;re using a class instead of a typedef to allow forward declarations and future flexibility...
virtual unsigned int embedding_matrix_version() const
Definition: elem.h:2052
unsigned int which_side_am_i(const Elem *e) const
This function tells you which side the boundary element e is.
Definition: elem.C:868
T cross_norm(const TypeVector< T > &b, const TypeVector< T > &c)
Calls cross_norm_sq() and takes the square root of the result.
Definition: type_vector.h:1096
RefinementState p_refinement_flag() const
Definition: elem.h:3227
IOPackage
libMesh interfaces with several different software packages for the purposes of creating, reading, and writing mesh files.
void find_interior_neighbors(std::set< const Elem *> &neighbor_set) const
This function finds all active elements (not including this one) in the parent manifold of this eleme...
Definition: elem.C:1170
static const unsigned int type_to_dim_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the geometric dimension of the ele...
Definition: elem.h:630
void family_tree_by_subneighbor(std::vector< const Elem *> &family, const Elem *neighbor, const Elem *subneighbor, bool reset=true) const
Same as the family_tree() member, but only adds elements which are next to subneighbor.
Definition: elem.C:2219
Threads::spin_mutex parent_indices_mutex
Definition: elem.C:97
void active_family_tree_by_side(T elem, std::vector< T > &family, unsigned int side, bool reset=true)
void family_tree(std::vector< const Elem *> &family, bool reset=true) const
Fills the vector family with the children of this element, recursively.
Definition: elem.C:2099
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
MeshBase & mesh
PeriodicBoundaryBase * boundary(boundary_id_type id)
void add_child(Elem *elem)
Adds a child pointer to the array of children of this element.
Definition: elem.C:2042
virtual BoundingBox loose_bounding_box() const
Definition: elem.C:3469
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const =0
unsigned int min_new_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
Definition: elem.C:2350
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
void active_family_tree(std::vector< const Elem *> &active_family, bool reset=true) const
Same as the family_tree() member, but only adds the active children.
Definition: elem.C:2131
unique_id_type unique_id() const
Definition: dof_object.h:844
void swap2boundarysides(unsigned short s1, unsigned short s2, BoundaryInfo *boundary_info) const
Swaps two sides in boundary_info, if it is non-null.
Definition: elem.C:3549
Order default_quadrature_order() const
Definition: fe_type.h:371
virtual unsigned int n_children() const =0
unsigned int p_level() const
Definition: elem.h:3109
void find_edge_neighbors(const Point &p1, const Point &p2, std::set< const Elem *> &neighbor_set) const
This function finds all active elements in the same manifold as this element which touch the current ...
Definition: elem.C:1081
side_iterator boundary_sides_end()
Definition: elem.C:3424
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
void make_links_to_me_remote()
Resets this element&#39;s neighbors&#39; appropriate neighbor pointers and its parent&#39;s and children&#39;s approp...
Definition: elem.C:1531
The libMesh namespace provides an interface to certain functionality in the library.
virtual Real hmax() const
Definition: elem.C:720
Real distance(const Point &p)
unsigned int min_p_level_by_neighbor(const Elem *neighbor, unsigned int current_min) const
Definition: elem.C:2321
void set_interior_parent(Elem *p)
Sets the pointer to the element&#39;s interior_parent.
Definition: elem.C:1246
static const unsigned int type_to_n_nodes_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of nodes in the element...
Definition: elem.h:645
bool contains_vertex_of(const Elem *e, bool mesh_connection=false) const
Definition: elem.C:932
uint8_t processor_id_type
Definition: id_types.h:104
This is the MeshBase class.
Definition: mesh_base.h:75
SimpleRange< ChildRefIter > child_ref_range()
Returns a range with all children of a parent element, usable in range-based for loops.
Definition: elem.h:2347
void add(const TypeVector< T2 > &)
Add to this vector without creating a temporary.
Definition: type_vector.h:605
bool ancestor() const
Definition: elem.C:2008
bool has_topological_neighbor(const Elem *elem, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb) const
Definition: elem.C:1348
IntRange< unsigned short > edge_index_range() const
Definition: elem.h:2693
side_iterator boundary_sides_begin()
Iterator accessor functions.
Definition: elem.C:3415
virtual Real embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval=0)
The hashword function takes an array of uint32_t&#39;s of length &#39;length&#39; and computes a single key from ...
Definition: hashword.h:158
T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
Definition: type_vector.h:1029
void family_tree_by_side(std::vector< const Elem *> &family, unsigned int side, bool reset=true) const
Same as the family_tree() member, but only adds elements which are next to side.
Definition: elem.C:2147
void replace_child(Elem *elem, unsigned int c)
Replaces the child pointer at the specified index in the child array.
Definition: elem.C:2088
void total_family_tree_by_subneighbor(std::vector< const Elem *> &family, const Elem *neighbor, const Elem *subneighbor, bool reset=true) const
Same as the family_tree_by_subneighbor() member, but also adds any subactive descendants.
Definition: elem.C:2239
TypeVector< T > unit() const
Definition: type_vector.h:1104
void libmesh_ignore(const Args &...)
void remove_links_to_me()
Resets this element&#39;s neighbors&#39; appropriate neighbor pointers and its parent&#39;s and children&#39;s approp...
Definition: elem.C:1637
virtual std::vector< std::vector< std::vector< signed char > > > & _get_parent_indices_cache() const
Elem subclasses which don&#39;t do their own child-to-parent node calculations will need to supply a stat...
Definition: elem.h:2224
virtual bool contains_point(const Point &p, Real tol=TOLERANCE) const
Definition: elem.C:2755
Real length(const unsigned int n1, const unsigned int n2) const
Definition: elem.C:740
ElemMappingType mapping_type() const
Definition: elem.h:3121
void make_links_to_me_local(unsigned int n, unsigned int neighbor_side)
Resets the neighbor_side pointers of our nth neighbor (and its descendants, if appropriate) to point ...
Definition: elem.C:1453
const Node & node_ref(const unsigned int i) const
Definition: elem.h:2530
void family_tree_by_neighbor(T elem, std::vector< T > &family, T neighbor_in, bool reset=true)
dof_id_type id() const
Definition: dof_object.h:828
virtual Real hmin() const
Definition: elem.C:700
static constexpr dof_id_type invalid_id
An invalid id to distinguish an uninitialized DofObject.
Definition: dof_object.h:482
virtual unsigned int n_nodes() const =0
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const =0
unsigned int which_node_am_i(unsigned int side, unsigned int side_node) const
This function is deprecated, call local_side_node(side, side_node) instead.
Definition: elem.C:922
static const unsigned int type_to_n_edges_map[INVALID_ELEM]
This array maps the integer representation of the ElemType enum to the number of edges on the element...
Definition: elem.h:744
unsigned int n_vars(const unsigned int s, const unsigned int vg) const
Definition: dof_object.h:967
bool contains_edge_of(const Elem *e) const
Definition: elem.C:970
unsigned int which_neighbor_am_i(const Elem *e) const
This function tells you which neighbor e is.
Definition: elem.h:2920
virtual unsigned int as_parent_node(unsigned int c, unsigned int n) const
Definition: elem.C:2384
virtual std::vector< unsigned int > edges_adjacent_to_node(const unsigned int) const =0
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:442
unsigned int n_systems() const
Definition: dof_object.h:937
virtual unsigned int opposite_node(const unsigned int n, const unsigned int s) const
Definition: elem.C:3534
virtual std::pair< unsigned short int, unsigned short int > second_order_child_vertex(const unsigned int n) const
Definition: elem.C:3062
Elem ** _elemlinks
Pointers to this element&#39;s parent and neighbors, and for lower-dimensional elements&#39; interior_parent...
Definition: elem.h:2252
void find_point_neighbors(const Point &p, std::set< const Elem *> &neighbor_set) const
This function finds all active elements (including this one) which are in the same manifold as this e...
Definition: elem.C:991
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const =0
Similar to Elem::local_side_node(), but instead of a side id, takes an edge id and a node id on that ...
The definition of the struct used for iterating over sides.
Definition: elem.h:3490
bool point_test(const Point &p, Real box_tol, Real map_tol) const
Shared private implementation used by the contains_point() and close_to_point() routines.
Definition: elem.C:2792
static std::unique_ptr< FEGenericBase > build(const unsigned int dim, const FEType &type)
Builds a specific finite element type.
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
void family_tree(T elem, std::vector< T > &family, bool reset=true)
Definition: elem_internal.h:41
libmesh_assert(ctx)
virtual Point side_vertex_average_normal(const unsigned int s) const
Definition: elem.C:3490
Threads::spin_mutex parent_bracketing_nodes_mutex
Definition: elem.C:98
const Elem * reference_elem() const
Definition: elem.C:568
void libmesh_assert_valid_neighbors() const
Checks for consistent neighbor links on this element.
Definition: elem.C:1381
virtual bool is_remote() const
Definition: elem.h:598
const std::vector< Real > & get_jacobian() const
Definition: fe_map.h:223
bool valid_unique_id() const
Definition: dof_object.h:893
This is the base class for point locators.
virtual unsigned int n_edges() const =0
ElemQuality
Defines an enum for element quality metrics.
virtual std::unique_ptr< Elem > disconnected_clone() const
Definition: elem.C:410
virtual unsigned int n_second_order_adjacent_vertices(const unsigned int n) const
Definition: elem.C:3044
SideIter _last_side()
Definition: elem.h:3479
auto norm(const T &a) -> decltype(std::abs(a))
Definition: tensor_tools.h:74
bool absolute_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
Definition: type_vector.h:972
bool positive_edge_orientation(const unsigned int i) const
Definition: elem.C:3604
void set_neighbor(const unsigned int i, Elem *n)
Assigns n as the neighbor.
Definition: elem.h:2619
static ElemType second_order_equivalent_type(const ElemType et, const bool full_ordered=true)
Definition: elem.C:3139
unsigned int which_child_am_i(const Elem *e) const
Definition: elem.h:3193
std::string enum_to_string(const T e)
void init_reference_to_physical_map(const std::vector< Point > &qp, const Elem *elem)
Definition: fe_map.C:109
void active_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, bool reset=true) const
Same as the active_family_tree() member, but only adds elements which are next to neighbor...
Definition: elem.C:2259
void total_family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, bool reset=true) const
Same as the family_tree_by_neighbor() member, but also adds any subactive descendants.
Definition: elem.C:2201
SimpleRange< NodeRefIter > node_ref_range()
Returns a range with all nodes of an element, usable in range-based for loops.
Definition: elem.h:2666
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
virtual unsigned int n_sides() const =0
bool topologically_equal(const Elem &rhs) const
Definition: elem.C:801
const Elem * neighbor_ptr(unsigned int i) const
Definition: elem.h:2599
void remove_side(const Elem *elem, const unsigned short int side)
Removes all boundary conditions associated with side side of element elem, if any exist...
void family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
virtual bool close_to_point(const Point &p, Real tol) const
Definition: elem.C:2780
unsigned int level() const
Definition: elem.h:3075
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
subdomain_id_type subdomain_id() const
Definition: elem.h:2583
bool valid_id() const
Definition: dof_object.h:885
virtual bool is_singular_node(unsigned int) const
Definition: elem.h:1839
virtual unsigned short dim() const =0
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:2508
virtual bool is_vertex(const unsigned int i) const =0
static Point map(const unsigned int dim, const Elem *elem, const Point &reference_point)
Definition: fe_map.C:2069
virtual Point master_point(const unsigned int i) const =0
static std::unique_ptr< Elem > build_with_id(const ElemType type, dof_id_type id)
Calls the build() method above with a nullptr parent, and additionally sets the newly-created Elem&#39;s ...
Definition: elem.C:556
unsigned int n_neighbors() const
Definition: elem.h:715
virtual Real quality(const ElemQuality q) const
Definition: elem.C:1772
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
Add side side of element number elem with boundary id id to the boundary information data structure...
virtual unsigned short int second_order_adjacent_vertex(const unsigned int n, const unsigned int v) const
Definition: elem.C:3052
bool subactive() const
Definition: elem.h:2960
virtual Real volume() const
Definition: elem.C:3433
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
const Elem * neighbor(boundary_id_type boundary_id, const PointLocatorBase &point_locator, const Elem *e, unsigned int side, unsigned int *neigh_side=nullptr) const
This class implements specific orders of Gauss quadrature.
void set_child(unsigned int c, Elem *elem)
Sets the pointer to the child for this element.
Definition: elem.h:3183
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const =0
unsigned int size() const
Alias for n_points() to enable use in index_range.
Definition: quadrature.h:142
virtual bool has_invertible_map(Real tol=TOLERANCE *TOLERANCE) const
Definition: elem.C:2885
IntRange< unsigned short > node_index_range() const
Definition: elem.h:2684
bool positive_face_orientation(const unsigned int i) const
Definition: elem.C:3613
unsigned int n_extra_integers() const
Returns how many extra integers are associated to the DofObject.
Definition: dof_object.h:1170
virtual bool is_vertex_on_child(unsigned int, unsigned int n) const
Definition: elem.h:775
void edge_boundary_ids(const Elem *const elem, const unsigned short int edge, std::vector< boundary_id_type > &vec_to_fill) const
void find_point_neighbors(T this_elem, std::set< T > &neighbor_set, T start_elem)
void nullify_neighbors()
Replaces this element with nullptr for all of its neighbors.
Definition: elem.C:3018
SimpleRange< NeighborPtrIter > neighbor_ptr_range()
Returns a range with all neighbors of an element, usable in range-based for loops.
Definition: elem.h:3504
virtual unsigned int n_faces() const =0
T get_extra_datum(const unsigned int index) const
Gets the value on this object of the extra datum associated with index, which should have been obtain...
Definition: dof_object.h:1146
virtual bool infinite() const =0
FEFamily
defines an enum for finite element families.
virtual unsigned int n_sub_elem() const =0
void total_family_tree(std::vector< const Elem *> &family, bool reset=true) const
Same as the family_tree() member, but also adds any subactive descendants.
Definition: elem.C:2115
void family_tree_by_neighbor(std::vector< const Elem *> &family, const Elem *neighbor, bool reset=true) const
Same as the family_tree() member, but only adds elements which are next to neighbor.
Definition: elem.C:2183
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i)=0
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:2452
virtual std::vector< std::vector< std::vector< std::vector< std::pair< unsigned char, unsigned char > > > > > & _get_bracketing_node_cache() const
Elem subclasses which don&#39;t do their own bracketing node calculations will need to supply a static ca...
Definition: elem.h:2210
virtual unsigned int opposite_side(const unsigned int s) const
Definition: elem.C:3526
bool active() const
Definition: elem.h:2942
void family_tree_by_side(T elem, std::vector< T > &family, unsigned int s, bool reset)
Class contained in FE that encapsulates mapping (i.e.
Definition: fe_map.h:47
static ElemType first_order_equivalent_type(const ElemType et)
Definition: elem.C:3070
processor_id_type processor_id() const
Definition: dof_object.h:905
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:2476
const Point & point(const unsigned int i) const
Definition: elem.h:2454
virtual Point centroid() const
Calls Elem::vertex_average() for backwards compatibility.
Definition: elem.C:576
bool operator==(const Elem &rhs) const
Definition: elem.C:769
bool has_children() const
Definition: elem.h:2980
virtual unsigned int center_node_on_side(const unsigned short side) const
Definition: elem.C:3542
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition: int_range.h:117
std::unique_ptr< Elem *[]> _children
unique_ptr to array of this element&#39;s children.
Definition: elem.h:2262
virtual bool is_child_on_edge(const unsigned int c, const unsigned int e) const
Definition: elem.C:2304
virtual bool is_edge(const unsigned int i) const =0
const Elem & get(const ElemType type_in)
void total_family_tree_by_subneighbor(T elem, std::vector< T > &family, T neighbor_in, T subneighbor, bool reset=true)
virtual std::vector< unsigned int > nodes_on_side(const unsigned int) const =0
virtual unsigned int n_nodes_in_child(unsigned int) const
Definition: elem.h:669
Point vertex_average() const
Definition: elem.C:686
static const unsigned int max_n_nodes
The maximum number of nodes any element can contain.
Definition: elem.h:656
const Elem * child_ptr(unsigned int i) const
Definition: elem.h:3164
void active_family_tree_by_topological_neighbor(T elem, std::vector< T > &family, T neighbor_in, const MeshBase &mesh, const PointLocatorBase &point_locator, const PeriodicBoundaries *pb, bool reset=true)
uint8_t dof_id_type
Definition: id_types.h:67
void add_edge(const dof_id_type elem, const unsigned short int edge, const boundary_id_type id)
Add edge edge of element number elem with boundary id id to the boundary information data structure...
const Real pi
.
Definition: libmesh.h:299
static FEFamily map_fe_type(const Elem &elem)
Definition: fe_map.C:46
virtual bool is_mid_infinite_edge_node(const unsigned int) const
Definition: elem.h:1906
Used to iterate over the sides of an element which are on the boundary of the Mesh.
bool is_internal(const unsigned int i) const
Definition: elem.C:3581
SideIter _first_side()
Side iterator helper functions.
Definition: elem.h:3471
const RemoteElem * remote_elem
Definition: remote_elem.C:57