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