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