LCOV - code coverage report
Current view: top level - src/geom - elem.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4343 (6ea38c) with base 8c3130 Lines: 1249 1582 79.0 %
Date: 2026-10-13 21:47:33 Functions: 82 111 73.9 %
Legend: Lines: hit not hit

          Line data    Source code
       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/tensor_value.h"
      26             : #include "libmesh/node_elem.h"
      27             : #include "libmesh/edge_edge2.h"
      28             : #include "libmesh/edge_edge3.h"
      29             : #include "libmesh/edge_edge4.h"
      30             : #include "libmesh/edge_inf_edge2.h"
      31             : #include "libmesh/face_c0polygon.h"
      32             : #include "libmesh/face_tri3.h"
      33             : #include "libmesh/face_tri3_subdivision.h"
      34             : #include "libmesh/face_tri3_shell.h"
      35             : #include "libmesh/face_tri6.h"
      36             : #include "libmesh/face_tri7.h"
      37             : #include "libmesh/face_quad4.h"
      38             : #include "libmesh/face_quad4_shell.h"
      39             : #include "libmesh/face_quad8.h"
      40             : #include "libmesh/face_quad8_shell.h"
      41             : #include "libmesh/face_quad9.h"
      42             : #include "libmesh/face_quad9_shell.h"
      43             : #include "libmesh/face_inf_quad4.h"
      44             : #include "libmesh/face_inf_quad6.h"
      45             : #include "libmesh/cell_tet4.h"
      46             : #include "libmesh/cell_tet10.h"
      47             : #include "libmesh/cell_tet14.h"
      48             : #include "libmesh/cell_hex8.h"
      49             : #include "libmesh/cell_hex20.h"
      50             : #include "libmesh/cell_hex27.h"
      51             : #include "libmesh/cell_inf_hex8.h"
      52             : #include "libmesh/cell_inf_hex16.h"
      53             : #include "libmesh/cell_inf_hex18.h"
      54             : #include "libmesh/cell_prism6.h"
      55             : #include "libmesh/cell_prism15.h"
      56             : #include "libmesh/cell_prism18.h"
      57             : #include "libmesh/cell_prism20.h"
      58             : #include "libmesh/cell_prism21.h"
      59             : #include "libmesh/cell_inf_prism6.h"
      60             : #include "libmesh/cell_inf_prism12.h"
      61             : #include "libmesh/cell_pyramid5.h"
      62             : #include "libmesh/cell_pyramid13.h"
      63             : #include "libmesh/cell_pyramid14.h"
      64             : #include "libmesh/cell_pyramid18.h"
      65             : #include "libmesh/fe_base.h"
      66             : #include "libmesh/mesh_base.h"
      67             : #include "libmesh/quadrature_nodal.h"
      68             : #include "libmesh/quadrature_gauss.h"
      69             : #include "libmesh/remote_elem.h"
      70             : #include "libmesh/reference_elem.h"
      71             : #include "libmesh/enum_to_string.h"
      72             : #include "libmesh/threads.h"
      73             : #include "libmesh/enum_elem_quality.h"
      74             : #include "libmesh/enum_io_package.h"
      75             : #include "libmesh/enum_order.h"
      76             : #include "libmesh/elem_internal.h"
      77             : 
      78             : #ifdef LIBMESH_ENABLE_PERIODIC
      79             : #include "libmesh/mesh.h"
      80             : #include "libmesh/periodic_boundaries.h"
      81             : #endif
      82             : 
      83             : 
      84             : // C++ includes
      85             : #include <algorithm> // for std::sort
      86             : #include <array>
      87             : #include <iterator>  // for std::ostream_iterator
      88             : #include <sstream>
      89             : #include <limits>    // for std::numeric_limits<>
      90             : #include <cmath>     // for std::sqrt()
      91             : #include <memory>
      92             : #include <regex>     // for exceptions in volume()
      93             : 
      94             : 
      95             : namespace libMesh
      96             : {
      97             : 
      98             : Threads::spin_mutex parent_indices_mutex;
      99             : Threads::spin_mutex parent_bracketing_nodes_mutex;
     100             : 
     101             : // Initialize static member variables
     102             : const unsigned int Elem::type_to_dim_map [] =
     103             :   {
     104             :     1,  // EDGE2
     105             :     1,  // EDGE3
     106             :     1,  // EDGE4
     107             : 
     108             :     2,  // TRI3
     109             :     2,  // TRI6
     110             : 
     111             :     2,  // QUAD4
     112             :     2,  // QUAD8
     113             :     2,  // QUAD9
     114             : 
     115             :     3,  // TET4
     116             :     3,  // TET10
     117             : 
     118             :     3,  // HEX8
     119             :     3,  // HEX20
     120             :     3,  // HEX27
     121             : 
     122             :     3,  // PRISM6
     123             :     3,  // PRISM15
     124             :     3,  // PRISM18
     125             : 
     126             :     3,  // PYRAMID5
     127             :     3,  // PYRAMID13
     128             :     3,  // PYRAMID14
     129             : 
     130             :     1,  // INFEDGE2
     131             : 
     132             :     2,  // INFQUAD4
     133             :     2,  // INFQUAD6
     134             : 
     135             :     3,  // INFHEX8
     136             :     3,  // INFHEX16
     137             :     3,  // INFHEX18
     138             : 
     139             :     3,  // INFPRISM6
     140             :     3,  // INFPRISM12
     141             : 
     142             :     0,  // NODEELEM
     143             : 
     144             :     0,  // REMOTEELEM
     145             : 
     146             :     2,  // TRI3SUBDIVISION
     147             :     2,  // TRISHELL3
     148             :     2,  // QUADSHELL4
     149             :     2,  // QUADSHELL8
     150             : 
     151             :     2,  // TRI7
     152             :     3,  // TET14
     153             :     3,  // PRISM20
     154             :     3,  // PRISM21
     155             :     3,  // PYRAMID18
     156             : 
     157             :     2,  // QUADSHELL9
     158             : 
     159             :     2,  // C0POLYGON
     160             :     3,  // C0POLYHEDRON
     161             :   };
     162             : 
     163             : const unsigned int Elem::max_n_nodes;
     164             : 
     165             : const unsigned int Elem::type_to_n_sides_map [] =
     166             :   {
     167             :     2,  // EDGE2
     168             :     2,  // EDGE3
     169             :     2,  // EDGE4
     170             : 
     171             :     3,  // TRI3
     172             :     3,  // TRI6
     173             : 
     174             :     4,  // QUAD4
     175             :     4,  // QUAD8
     176             :     4,  // QUAD9
     177             : 
     178             :     4,  // TET4
     179             :     4,  // TET10
     180             : 
     181             :     6,  // HEX8
     182             :     6,  // HEX20
     183             :     6,  // HEX27
     184             : 
     185             :     5,  // PRISM6
     186             :     5,  // PRISM15
     187             :     5,  // PRISM18
     188             : 
     189             :     5,  // PYRAMID5
     190             :     5,  // PYRAMID13
     191             :     5,  // PYRAMID14
     192             : 
     193             :     2,  // INFEDGE2
     194             : 
     195             :     3,  // INFQUAD4
     196             :     3,  // INFQUAD6
     197             : 
     198             :     5,  // INFHEX8
     199             :     5,  // INFHEX16
     200             :     5,  // INFHEX18
     201             : 
     202             :     4,  // INFPRISM6
     203             :     4,  // INFPRISM12
     204             : 
     205             :     0,  // NODEELEM
     206             : 
     207             :     0,  // REMOTEELEM
     208             : 
     209             :     3,  // TRI3SUBDIVISION
     210             :     3,  // TRISHELL3
     211             :     4,  // QUADSHELL4
     212             :     4,  // QUADSHELL8
     213             : 
     214             :     3,  // TRI7
     215             :     4,  // TET14
     216             :     5,  // PRISM20
     217             :     5,  // PRISM21
     218             :     5,  // PYRAMID18
     219             : 
     220             :     4,  // QUADSHELL9
     221             : 
     222             :     invalid_uint,  // C0POLYGON
     223             :     invalid_uint,  // C0POLYHEDRON
     224             :   };
     225             : 
     226             : const unsigned int Elem::type_to_n_edges_map [] =
     227             :   {
     228             :     0,  // EDGE2
     229             :     0,  // EDGE3
     230             :     0,  // EDGE4
     231             : 
     232             :     3,  // TRI3
     233             :     3,  // TRI6
     234             : 
     235             :     4,  // QUAD4
     236             :     4,  // QUAD8
     237             :     4,  // QUAD9
     238             : 
     239             :     6,  // TET4
     240             :     6,  // TET10
     241             : 
     242             :     12, // HEX8
     243             :     12, // HEX20
     244             :     12, // HEX27
     245             : 
     246             :     9,  // PRISM6
     247             :     9,  // PRISM15
     248             :     9,  // PRISM18
     249             : 
     250             :     8,  // PYRAMID5
     251             :     8,  // PYRAMID13
     252             :     8,  // PYRAMID14
     253             : 
     254             :     0,  // INFEDGE2
     255             : 
     256             :     3,  // INFQUAD4
     257             :     3,  // INFQUAD6
     258             : 
     259             :     8,  // INFHEX8
     260             :     8,  // INFHEX16
     261             :     8,  // INFHEX18
     262             : 
     263             :     6,  // INFPRISM6
     264             :     6,  // INFPRISM12
     265             : 
     266             :     0,  // NODEELEM
     267             : 
     268             :     0,  // REMOTEELEM
     269             : 
     270             :     3,  // TRI3SUBDIVISION
     271             :     3,  // TRISHELL3
     272             :     4,  // QUADSHELL4
     273             :     4,  // QUADSHELL8
     274             : 
     275             :     3,  // TRI7
     276             :     6,  // TET14
     277             :     9,  // PRISM20
     278             :     9,  // PRISM21
     279             :     8,  // PYRAMID18
     280             : 
     281             :     4,  // QUADSHELL9
     282             : 
     283             :     invalid_uint,  // C0POLYGON
     284             :     invalid_uint,  // C0POLYHEDRON
     285             :   };
     286             : 
     287             : const Order Elem::type_to_default_order_map [] =
     288             :   {
     289             :     FIRST,    // EDGE2
     290             :     SECOND,   // EDGE3
     291             :     THIRD,    // EDGE4
     292             : 
     293             :     FIRST,    // TRI3
     294             :     SECOND,   // TRI6
     295             : 
     296             :     FIRST,    // QUAD4
     297             :     SECOND,   // QUAD8
     298             :     SECOND,   // QUAD9
     299             : 
     300             :     FIRST,    // TET4
     301             :     SECOND,   // TET10
     302             : 
     303             :     FIRST,    // HEX8
     304             :     SECOND,   // HEX20
     305             :     SECOND,   // HEX27
     306             : 
     307             :     FIRST,    // PRISM6
     308             :     SECOND,   // PRISM15
     309             :     SECOND,   // PRISM18
     310             : 
     311             :     FIRST,    // PYRAMID5
     312             :     SECOND,   // PYRAMID13
     313             :     SECOND,   // PYRAMID14
     314             : 
     315             :     FIRST,    // INFEDGE2
     316             : 
     317             :     FIRST,    // INFQUAD4
     318             :     SECOND,   // INFQUAD6
     319             : 
     320             :     FIRST,    // INFHEX8
     321             :     SECOND,   // INFHEX16
     322             :     SECOND,   // INFHEX18
     323             : 
     324             :     FIRST,    // INFPRISM6
     325             :     SECOND,   // INFPRISM12
     326             : 
     327             :     CONSTANT, // NODEELEM
     328             : 
     329             :     INVALID_ORDER, // REMOTEELEM
     330             : 
     331             :     FIRST,    // TRI3SUBDIVISION
     332             :     FIRST,    // TRISHELL3
     333             :     FIRST,    // QUADSHELL4
     334             :     SECOND,   // QUADSHELL8
     335             : 
     336             :     THIRD,    // TRI7
     337             :     THIRD,    // TET14
     338             :     THIRD,    // PRISM20
     339             :     THIRD,    // PRISM21
     340             :     THIRD,    // PYRAMID18
     341             : 
     342             :     SECOND,   // QUADSHELL9
     343             : 
     344             :     FIRST,    // C0POLYGON
     345             :     FIRST,    // C0POLYHEDRON
     346             :   };
     347             : 
     348             : // ------------------------------------------------------------
     349             : // Elem class member functions
     350    10113341 : std::unique_ptr<Elem> Elem::disconnected_clone() const
     351             : {
     352    10113341 :   std::unique_ptr<Elem> returnval;
     353             : 
     354    10113341 :   switch (this->type())
     355             :     {
     356       31667 :     case C0POLYGON:
     357       31667 :       returnval = std::make_unique<C0Polygon>(this->n_sides());
     358       31667 :       break;
     359             : 
     360    10081674 :     default:
     361    19839952 :       returnval = Elem::build(this->type());
     362             :     }
     363             : 
     364    10113341 :   returnval->set_id() = this->id();
     365             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     366    10113341 :   if (this->valid_unique_id())
     367      323398 :     returnval->set_unique_id(this->unique_id());
     368             : #endif
     369             : 
     370    10113341 :   const auto n_elem_ints = this->n_extra_integers();
     371    10113341 :   returnval->add_extra_integers(n_elem_ints);
     372    10130594 :   for (unsigned int i = 0; i != n_elem_ints; ++i)
     373       17253 :     returnval->set_extra_integer(i, this->get_extra_integer(i));
     374             : 
     375     9799609 :   returnval->inherit_data_from(*this);
     376             : 
     377    10113341 :   return returnval;
     378           0 : }
     379             : 
     380             : 
     381             : 
     382    67721845 : std::unique_ptr<Elem> Elem::build(const ElemType type,
     383             :                                   Elem * p)
     384             : {
     385    67721845 :   switch (type)
     386             :     {
     387             :       // 0D elements
     388      223064 :     case NODEELEM:
     389      223064 :       return std::make_unique<NodeElem>(p);
     390             : 
     391             :       // 1D elements
     392      510191 :     case EDGE2:
     393      510191 :       return std::make_unique<Edge2>(p);
     394      240882 :     case EDGE3:
     395      240882 :       return std::make_unique<Edge3>(p);
     396       51640 :     case EDGE4:
     397       51640 :       return std::make_unique<Edge4>(p);
     398             : 
     399             :       // 2D elements
     400     4517541 :     case TRI3:
     401     4517541 :       return std::make_unique<Tri3>(p);
     402       81506 :     case TRISHELL3:
     403       81506 :       return std::make_unique<TriShell3>(p);
     404       62956 :     case TRI3SUBDIVISION:
     405       62956 :       return std::make_unique<Tri3Subdivision>(p);
     406     1064976 :     case TRI6:
     407     1064976 :       return std::make_unique<Tri6>(p);
     408      590308 :     case TRI7:
     409      590308 :       return std::make_unique<Tri7>(p);
     410    25443130 :     case QUAD4:
     411    25443130 :       return std::make_unique<Quad4>(p);
     412      190772 :     case QUADSHELL4:
     413      190772 :       return std::make_unique<QuadShell4>(p);
     414      266209 :     case QUAD8:
     415      266209 :       return std::make_unique<Quad8>(p);
     416      185472 :     case QUADSHELL8:
     417      185472 :       return std::make_unique<QuadShell8>(p);
     418     3271128 :     case QUAD9:
     419     3271128 :       return std::make_unique<Quad9>(p);
     420       70479 :     case QUADSHELL9:
     421       70479 :       return std::make_unique<QuadShell9>(p);
     422             : 
     423             :     // Well, a hexagon is *a* polygon...
     424       41656 :     case C0POLYGON:
     425       41656 :       return std::make_unique<C0Polygon>(6, p);
     426             : 
     427             :     // Building a polyhedron can't currently be done without creating
     428             :     // its nodes first
     429           0 :     case C0POLYHEDRON:
     430           0 :       libmesh_not_implemented_msg
     431             :         ("Polyhedra cannot be built via Elem::build()");
     432             : 
     433             :       // 3D elements
     434    16641397 :     case TET4:
     435    16641397 :       return std::make_unique<Tet4>(p);
     436     1978527 :     case TET10:
     437     1978527 :       return std::make_unique<Tet10>(p);
     438     3879982 :     case TET14:
     439     3879982 :       return std::make_unique<Tet14>(p);
     440     3352691 :     case HEX8:
     441     3352691 :       return std::make_unique<Hex8>(p);
     442      148124 :     case HEX20:
     443      148124 :       return std::make_unique<Hex20>(p);
     444     1971521 :     case HEX27:
     445     1971521 :       return std::make_unique<Hex27>(p);
     446      384826 :     case PRISM6:
     447      384826 :       return std::make_unique<Prism6>(p);
     448      194262 :     case PRISM15:
     449      194262 :       return std::make_unique<Prism15>(p);
     450      640812 :     case PRISM18:
     451      640812 :       return std::make_unique<Prism18>(p);
     452      139023 :     case PRISM20:
     453      139023 :       return std::make_unique<Prism20>(p);
     454      279817 :     case PRISM21:
     455      279817 :       return std::make_unique<Prism21>(p);
     456      637345 :     case PYRAMID5:
     457      637345 :       return std::make_unique<Pyramid5>(p);
     458      224803 :     case PYRAMID13:
     459      224803 :       return std::make_unique<Pyramid13>(p);
     460      227059 :     case PYRAMID14:
     461      227059 :       return std::make_unique<Pyramid14>(p);
     462      202088 :     case PYRAMID18:
     463      202088 :       return std::make_unique<Pyramid18>(p);
     464             : 
     465             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     466             :       // 1D infinite elements
     467           0 :     case INFEDGE2:
     468           0 :       return std::make_unique<InfEdge2>(p);
     469             : 
     470             :       // 2D infinite elements
     471         175 :     case INFQUAD4:
     472         175 :       return std::make_unique<InfQuad4>(p);
     473         175 :     case INFQUAD6:
     474         175 :       return std::make_unique<InfQuad6>(p);
     475             : 
     476             :       // 3D infinite elements
     477        3021 :     case INFHEX8:
     478        3021 :       return std::make_unique<InfHex8>(p);
     479         255 :     case INFHEX16:
     480         255 :       return std::make_unique<InfHex16>(p);
     481        1702 :     case INFHEX18:
     482        1702 :       return std::make_unique<InfHex18>(p);
     483         255 :     case INFPRISM6:
     484         255 :       return std::make_unique<InfPrism6>(p);
     485        2075 :     case INFPRISM12:
     486        2075 :       return std::make_unique<InfPrism12>(p);
     487             : #endif
     488             : 
     489           0 :     default:
     490           0 :       libmesh_error_msg("ERROR: Undefined element type == " << Utility::enum_to_string(type));
     491             :     }
     492             : }
     493             : 
     494             : 
     495             : 
     496     7111669 : std::unique_ptr<Elem> Elem::build_with_id (const ElemType type,
     497             :                                            dof_id_type id)
     498             : {
     499             :   // Call the other build() method with nullptr parent, then set the
     500             :   // required id.
     501     7111669 :   auto temp = Elem::build(type, nullptr);
     502      186847 :   temp->set_id(id);
     503     7111669 :   return temp;
     504             : }
     505             : 
     506             : 
     507             : 
     508      418343 : const Elem * Elem::reference_elem () const
     509             : {
     510      418343 :   return &(ReferenceElem::get(this->type()));
     511             : }
     512             : 
     513             : 
     514             : 
     515       86472 : Point Elem::true_centroid() const
     516             : {
     517             :   // The base class implementation builds a finite element of the correct
     518             :   // order and computes the centroid, c=(cx, cy, cz), where:
     519             :   //
     520             :   // [cx]            [\int x dV]
     521             :   // [cy] := (1/V) * [\int y dV]
     522             :   // [cz]            [\int z dV]
     523             :   //
     524             :   // using quadrature. Note that we can expand "x" in the FE space as:
     525             :   //
     526             :   // x = \sum_i x_i \phi_i
     527             :   //
     528             :   // where x_i are the nodal positions of the element and \phi_i are the
     529             :   // associated Lagrange shape functions. This allows us to write the
     530             :   // integrals above as e.g.:
     531             :   //
     532             :   // \int x dV = \sum_i x_i \int \phi_i dV
     533             :   //
     534             :   // Defining:
     535             :   //
     536             :   // V_i := \int \phi_i dV
     537             :   //
     538             :   // we then have:
     539             :   //
     540             :   // [cx]           [\sum_i x_i V_i]
     541             :   // [cy] = (1/V) * [\sum_i y_i V_i]
     542             :   // [cz]           [\sum_i z_i V_i]
     543             :   //
     544             :   // where:
     545             :   // V = \sum_i V_i
     546             :   //
     547             :   // Derived element types can overload this method to compute
     548             :   // the centroid more efficiently when possible.
     549             : 
     550             :   // If this Elem has an elevated p_level, then we need to generate a
     551             :   // barebones copy of it with zero p_level and call true_centroid()
     552             :   // on that instead.  This workaround allows us to avoid issues with
     553             :   // calling FE::reinit() with a default_order() FEType, and then
     554             :   // having that order incorrectly boosted by p_level.
     555       86472 :   if (this->p_level())
     556             :     {
     557          73 :       auto elem_copy = this->disconnected_clone();
     558             : #ifdef LIBMESH_ENABLE_AMR
     559          71 :       elem_copy->set_p_level(0);
     560             : #endif
     561             : 
     562             :       // Set node pointers
     563        1491 :       for (auto n : this->node_index_range())
     564        1420 :         elem_copy->set_node(n, _nodes[n]);
     565             : 
     566          71 :       return elem_copy->true_centroid();
     567          67 :     }
     568             : 
     569       86401 :   const FEFamily mapping_family = FEMap::map_fe_type(*this);
     570       86401 :   const FEType fe_type(this->default_order(), mapping_family);
     571             : 
     572             :   // Build FE and attach quadrature rule.  The default quadrature rule
     573             :   // integrates the mass matrix exactly, thus it is overkill to
     574             :   // integrate the basis functions, but this is convenient.
     575       93276 :   std::unique_ptr<FEBase> fe = FEBase::build(this->dim(), fe_type);
     576       93276 :   QGauss qrule (this->dim(), fe_type.default_quadrature_order());
     577       86401 :   fe->attach_quadrature_rule(&qrule);
     578             : 
     579             :   // Pre-request required data
     580       86401 :   const auto & JxW = fe->get_JxW();
     581        6875 :   const auto & phi = fe->get_phi();
     582             : 
     583             :   // Re-compute element-specific values
     584       86401 :   fe->reinit(this);
     585             : 
     586             :   // Number of basis functions
     587       13750 :   auto N = phi.size();
     588        6875 :   libmesh_assert_equal_to(N, this->n_nodes());
     589             : 
     590             :   // Compute V_i
     591       86401 :   std::vector<Real> V(N);
     592     2570250 :   for (auto qp : index_range(JxW))
     593    37985489 :     for (auto i : make_range(N))
     594    44331225 :       V[i] += JxW[qp] * phi[i][qp];
     595             : 
     596             :   // Compute centroid
     597        6875 :   Point cp;
     598        6875 :   Real vol = 0.;
     599             : 
     600     1193097 :   for (auto i : make_range(N))
     601             :     {
     602      361692 :       cp += this->point(i) * V[i];
     603     1106696 :       vol += V[i];
     604             :     }
     605             : 
     606        6875 :   return cp / vol;
     607       72651 : }
     608             : 
     609   536533945 : Point Elem::vertex_average() const
     610             : {
     611    41917575 :   Point cp;
     612             : 
     613   536533945 :   const auto n_vertices = this->n_vertices();
     614             : 
     615  3182753884 :   for (unsigned int n=0; n<n_vertices; n++)
     616   418069090 :     cp.add (this->point(n));
     617             : 
     618   536533945 :   return (cp /= static_cast<Real>(n_vertices));
     619             : }
     620             : 
     621             : 
     622             : 
     623     1855014 : Real Elem::hmin() const
     624             : {
     625             :   // Avoid calling a virtual a lot of times
     626     1855014 :   const auto n_vertices = this->n_vertices();
     627             : 
     628             :   // Special case for NodeElem
     629     1855014 :   if (!n_vertices)
     630           0 :     return 0;
     631             : 
     632     1855014 :   Real h_min=std::numeric_limits<Real>::max();
     633             : 
     634     8842856 :   for (unsigned int n_outer=0; n_outer<n_vertices; n_outer++)
     635    17431575 :     for (unsigned int n_inner=n_outer+1; n_inner<n_vertices; n_inner++)
     636             :       {
     637     2022368 :         const auto diff = (this->point(n_outer) - this->point(n_inner));
     638             : 
     639    13609788 :         h_min = std::min(h_min, diff.norm_sq());
     640             :       }
     641             : 
     642     1855014 :   return std::sqrt(h_min);
     643             : }
     644             : 
     645             : 
     646             : 
     647   102240357 : Real Elem::hmax() const
     648             : {
     649   102240357 :   Real h_max=0;
     650             : 
     651             :   // Avoid calling a virtual a lot of times
     652   102240357 :   const auto n_vertices = this->n_vertices();
     653             : 
     654   672215660 :   for (unsigned int n_outer=0; n_outer<n_vertices; n_outer++)
     655  2143668759 :     for (unsigned int n_inner=n_outer+1; n_inner<n_vertices; n_inner++)
     656             :       {
     657   104361216 :         const auto diff = (this->point(n_outer) - this->point(n_inner));
     658             : 
     659  1808296610 :         h_max = std::max(h_max, diff.norm_sq());
     660             :       }
     661             : 
     662   108826852 :   return std::sqrt(h_max);
     663             : }
     664             : 
     665             : 
     666             : 
     667      261488 : Real Elem::length(const unsigned int n1,
     668             :                   const unsigned int n2) const
     669             : {
     670       21728 :   libmesh_assert_less ( n1, this->n_vertices() );
     671       21728 :   libmesh_assert_less ( n2, this->n_vertices() );
     672             : 
     673      283216 :   return (this->point(n1) - this->point(n2)).norm();
     674             : }
     675             : 
     676             : 
     677             : 
     678           0 : dof_id_type Elem::key () const
     679             : {
     680           0 :   const unsigned short n_n = this->n_nodes();
     681             : 
     682             :   std::array<dof_id_type, Elem::max_n_nodes> node_ids;
     683             : 
     684           0 :   for (unsigned short n=0; n != n_n; ++n)
     685           0 :     node_ids[n] = this->node_id(n);
     686             : 
     687             :   // Always sort, so that different local node numberings hash to the
     688             :   // same value.
     689           0 :   std::sort (node_ids.begin(), node_ids.begin()+n_n);
     690             : 
     691           0 :   return Utility::hashword(node_ids.data(), n_n);
     692             : }
     693             : 
     694             : 
     695             : 
     696   130998083 : bool Elem::operator == (const Elem & rhs) const
     697             : {
     698             :   // If the elements aren't the same type, they aren't equal
     699   130998083 :   if (this->type() != rhs.type())
     700           4 :     return false;
     701             : 
     702   130997941 :   const unsigned short n_n = this->n_nodes();
     703     2676504 :   libmesh_assert_equal_to(n_n, rhs.n_nodes());
     704             : 
     705             :   // Make two sorted arrays of global node ids and compare them for
     706             :   // equality.
     707             :   std::array<dof_id_type, Elem::max_n_nodes> this_ids, rhs_ids;
     708             : 
     709   450874701 :   for (unsigned short n = 0; n != n_n; n++)
     710             :     {
     711   319876760 :       this_ids[n] = this->node_id(n);
     712   326955054 :       rhs_ids[n] = rhs.node_id(n);
     713             :     }
     714             : 
     715             :   // Sort the vectors to rule out different local node numberings.
     716   130997941 :   std::sort(this_ids.begin(), this_ids.begin()+n_n);
     717   130997941 :   std::sort(rhs_ids.begin(), rhs_ids.begin()+n_n);
     718             : 
     719             :   // If the node ids match, the elements are equal!
     720   450813060 :   for (unsigned short n = 0; n != n_n; ++n)
     721   319832115 :     if (this_ids[n] != rhs_ids[n])
     722           0 :       return false;
     723     2676504 :   return true;
     724             : }
     725             : 
     726             : 
     727             : 
     728      789345 : bool Elem::topologically_equal (const Elem & rhs) const
     729             : {
     730             :   // If the elements aren't the same type, they aren't equal
     731      789345 :   if (this->type() != rhs.type())
     732           0 :     return false;
     733             : 
     734      338536 :   libmesh_assert_equal_to(this->n_nodes(), rhs.n_nodes());
     735             : 
     736     6682215 :   for (auto n : make_range(this->n_nodes()))
     737     6159614 :     if (this->node_id(n) != rhs.node_id(n))
     738           0 :       return false;
     739             : 
     740     3953178 :   for (auto neigh : make_range(this->n_neighbors()))
     741             :     {
     742     3221540 :       if (!this->neighbor_ptr(neigh))
     743             :         {
     744      420234 :           if (rhs.neighbor_ptr(neigh))
     745           6 :             return false;
     746      400258 :           continue;
     747             :         }
     748     4050500 :       if (!rhs.neighbor_ptr(neigh) ||
     749     1296766 :           this->neighbor_ptr(neigh)->id() !=
     750     1296766 :           rhs.neighbor_ptr(neigh)->id())
     751           6 :         return false;
     752             :     }
     753             : 
     754      803998 :   if (this->parent())
     755             :     {
     756       32076 :       if (!rhs.parent())
     757           0 :         return false;
     758       31776 :       if (this->parent()->id() != rhs.parent()->id())
     759           0 :         return false;
     760             :     }
     761      771922 :   else if (rhs.parent())
     762           0 :     return false;
     763             : 
     764      789204 :   if (this->interior_parent())
     765             :     {
     766           0 :       if (!rhs.interior_parent())
     767           0 :         return false;
     768           0 :       if (this->interior_parent()->id() !=
     769           0 :           rhs.interior_parent()->id())
     770           0 :         return false;
     771             :     }
     772      789204 :   else if (rhs.interior_parent())
     773           0 :     return false;
     774             : 
     775      338530 :   return true;
     776             : }
     777             : 
     778             : 
     779             : 
     780           0 : bool Elem::is_semilocal(const processor_id_type my_pid) const
     781             : {
     782           0 :   std::set<const Elem *> point_neighbors;
     783             : 
     784           0 :   this->find_point_neighbors(point_neighbors);
     785             : 
     786           0 :   for (const auto & elem : point_neighbors)
     787           0 :     if (elem->processor_id() == my_pid)
     788           0 :       return true;
     789             : 
     790           0 :   return false;
     791             : }
     792             : 
     793             : 
     794             : 
     795        7709 : unsigned int Elem::which_side_am_i (const Elem * e) const
     796             : {
     797         708 :   libmesh_assert(e);
     798             : 
     799        7709 :   const unsigned int ns = this->n_sides();
     800        7709 :   const unsigned int nn = this->n_nodes();
     801             : 
     802        7709 :   const unsigned int en = e->n_nodes();
     803             : 
     804             :   // e might be on any side until proven otherwise
     805        8417 :   std::vector<bool> might_be_side(ns, true);
     806             : 
     807       30670 :   for (unsigned int i=0; i != en; ++i)
     808             :     {
     809       25069 :       Point side_point = e->point(i);
     810        2108 :       unsigned int local_node_id = libMesh::invalid_uint;
     811             : 
     812             :       // Look for a node of this that's contiguous with node i of
     813             :       // e. Note that the exact floating point comparison of Point
     814             :       // positions is intentional, see the class documentation for
     815             :       // this function.
     816      229112 :       for (unsigned int j=0; j != nn; ++j)
     817       37848 :         if (this->point(j) == side_point)
     818        2108 :           local_node_id = j;
     819             : 
     820             :       // If a node of e isn't contiguous with some node of this, then
     821             :       // e isn't a side of this.
     822       22961 :       if (local_node_id == libMesh::invalid_uint)
     823           0 :         return libMesh::invalid_uint;
     824             : 
     825             :       // If a node of e isn't contiguous with some node on side s of
     826             :       // this, then e isn't on side s.
     827      114639 :       for (unsigned int s=0; s != ns; ++s)
     828       91678 :         if (!this->is_node_on_side(local_node_id, s))
     829        9816 :           might_be_side[s] = false;
     830             :     }
     831             : 
     832       21383 :   for (unsigned int s=0; s != ns; ++s)
     833       23314 :     if (might_be_side[s])
     834             :       {
     835             : #ifdef DEBUG
     836        1593 :         for (unsigned int s2=s+1; s2 < ns; ++s2)
     837         885 :           libmesh_assert (!might_be_side[s2]);
     838             : #endif
     839        7709 :         return s;
     840             :       }
     841             : 
     842             :   // Didn't find any matching side
     843           0 :   return libMesh::invalid_uint;
     844             : }
     845             : 
     846             : 
     847             : 
     848  1376921128 : bool Elem::contains_vertex_of(const Elem * e, bool mesh_connection) const
     849             : {
     850             :   // Our vertices are the first numbered nodes
     851  1376921128 :   const unsigned int nv = e->n_vertices();
     852  1376921128 :   const unsigned int my_nv = this->n_vertices();
     853             : 
     854             :   // Check for vertex-to-vertex containment first; contains_point() is
     855             :   // expensive
     856  4752946196 :   for (auto n : make_range(nv))
     857             :     {
     858    17155863 :       const Node * vertex = e->node_ptr(n);
     859 22780888103 :       for (auto my_n : make_range(my_nv))
     860 19404863035 :         if (&this->node_ref(my_n) == vertex)
     861     1312517 :           return true;
     862             :     }
     863             : 
     864             :   // If e is in our mesh, then we might be done testing
     865   460109670 :   if (mesh_connection)
     866             :     {
     867   460109670 :       const unsigned int l = this->level();
     868   460109670 :       const unsigned int el = e->level();
     869             : 
     870   460109670 :       if (l >= el)
     871      805530 :         return false;
     872             : 
     873             :       // We could also return false for l==el-1 iff we knew we had no
     874             :       // triangular faces, but we don't have an API to check that.
     875             :     }
     876             : 
     877             :   // Our vertices are the first numbered nodes
     878    48578624 :   for (auto n : make_range(nv))
     879    42535333 :     if (this->contains_point(e->point(n)))
     880           0 :       return true;
     881        1632 :   return false;
     882             : }
     883             : 
     884             : 
     885             : 
     886           0 : bool Elem::contains_edge_of(const Elem * e) const
     887             : {
     888           0 :   unsigned int num_contained_edges = 0;
     889             : 
     890             :   // Our vertices are the first numbered nodes
     891           0 :   for (auto n : make_range(e->n_vertices()))
     892             :     {
     893           0 :       if (this->contains_point(e->point(n)))
     894             :         {
     895           0 :           num_contained_edges++;
     896           0 :           if (num_contained_edges>=2)
     897             :             {
     898           0 :               return true;
     899             :             }
     900             :         }
     901             :     }
     902           0 :   return false;
     903             : }
     904             : 
     905             : 
     906             : 
     907      575865 : void Elem::find_point_neighbors(const Point & p,
     908             :                                 std::set<const Elem *> & neighbor_set) const
     909             : {
     910       51170 :   libmesh_assert(this->contains_point(p));
     911       51170 :   libmesh_assert(this->active());
     912             : 
     913       51170 :   neighbor_set.clear();
     914      575865 :   neighbor_set.insert(this);
     915             : 
     916      102340 :   std::set<const Elem *> untested_set, next_untested_set;
     917      575865 :   untested_set.insert(this);
     918             : 
     919             : #ifdef LIBMESH_ENABLE_AMR
     920      102340 :   std::vector<const Elem *> active_neighbor_children;
     921             : #endif // #ifdef LIBMESH_ENABLE_AMR
     922             : 
     923     1738094 :   while (!untested_set.empty())
     924             :     {
     925             :       // Loop over all the elements in the patch that haven't already
     926             :       // been tested
     927     2473563 :       for (const auto & elem : untested_set)
     928     6921039 :           for (auto current_neighbor : elem->neighbor_ptr_range())
     929             :             {
     930     5922858 :               if (current_neighbor &&
     931     5044197 :                   current_neighbor != remote_elem)    // we have a real neighbor on this side
     932             :                 {
     933      426766 :                   if (current_neighbor->active())                // ... if it is active
     934             :                     {
     935      422224 :                       auto it = neighbor_set.lower_bound(current_neighbor);
     936     8811853 :                       if ((it == neighbor_set.end() || *it != current_neighbor) &&
     937     3889688 :                           current_neighbor->contains_point(p))   // ... don't have and touches p
     938             :                         {
     939             :                           // Add it and test it
     940      671790 :                           next_untested_set.insert(current_neighbor);
     941      733691 :                           neighbor_set.emplace_hint(it, current_neighbor);
     942             :                         }
     943             :                     }
     944             : #ifdef LIBMESH_ENABLE_AMR
     945             :                   else                                 // ... the neighbor is *not* active,
     946             :                     {                                  // ... so add *all* neighboring
     947             :                                                        // active children that touch p
     948        4542 :                       active_neighbor_children.clear();
     949             :                       current_neighbor->active_family_tree_by_neighbor
     950       14099 :                         (active_neighbor_children, elem);
     951             : 
     952       42611 :                       for (const auto & current_child : active_neighbor_children)
     953             :                         {
     954        9084 :                           auto it = neighbor_set.lower_bound(current_child);
     955       55778 :                           if ((it == neighbor_set.end() || *it != current_child) &&
     956       27266 :                               current_child->contains_point(p))
     957             :                             {
     958             :                               // Add it and test it
     959        1236 :                               next_untested_set.insert(current_child);
     960        1778 :                               neighbor_set.emplace_hint(it, current_child);
     961             :                             }
     962             :                         }
     963             :                     }
     964             : #endif // #ifdef LIBMESH_ENABLE_AMR
     965             :                 }
     966             :             }
     967      101794 :       untested_set.swap(next_untested_set);
     968      101794 :       next_untested_set.clear();
     969             :     }
     970      575865 : }
     971             : 
     972             : 
     973             : 
     974    10187738 : void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set) const
     975             : {
     976    10187738 :   this->find_point_neighbors(neighbor_set, this);
     977    10187738 : }
     978             : 
     979             : 
     980             : 
     981    10187738 : void Elem::find_point_neighbors(std::set<const Elem *> & neighbor_set,
     982             :                                 const Elem * start_elem) const
     983             : {
     984    10187738 :   ElemInternal::find_point_neighbors(this, neighbor_set, start_elem);
     985    10187738 : }
     986             : 
     987             : 
     988             : 
     989           0 : void Elem::find_point_neighbors(std::set<Elem *> & neighbor_set,
     990             :                                 Elem * start_elem)
     991             : {
     992           0 :   ElemInternal::find_point_neighbors(this, neighbor_set, start_elem);
     993           0 : }
     994             : 
     995             : 
     996             : 
     997         480 : void Elem::find_edge_neighbors(const Point & p1,
     998             :                                const Point & p2,
     999             :                                std::set<const Elem *> & neighbor_set) const
    1000             : {
    1001             :   // Simple but perhaps suboptimal code: find elements containing the
    1002             :   // first point, then winnow this set down by removing elements which
    1003             :   // don't also contain the second point
    1004             : 
    1005          40 :   libmesh_assert(this->contains_point(p2));
    1006         480 :   this->find_point_neighbors(p1, neighbor_set);
    1007             : 
    1008          40 :   std::set<const Elem *>::iterator        it = neighbor_set.begin();
    1009          40 :   const std::set<const Elem *>::iterator end = neighbor_set.end();
    1010             : 
    1011        1812 :   while (it != end)
    1012             :     {
    1013             :       // As of C++11, set::erase returns an iterator to the element
    1014             :       // following the erased element, or end.
    1015        1332 :       if (!(*it)->contains_point(p2))
    1016         781 :         it = neighbor_set.erase(it);
    1017             :       else
    1018          40 :         ++it;
    1019             :     }
    1020         480 : }
    1021             : 
    1022             : 
    1023             : 
    1024           0 : void Elem::find_edge_neighbors(std::set<const Elem *> & neighbor_set) const
    1025             : {
    1026           0 :   neighbor_set.clear();
    1027           0 :   neighbor_set.insert(this);
    1028             : 
    1029           0 :   std::set<const Elem *> untested_set, next_untested_set;
    1030           0 :   untested_set.insert(this);
    1031             : 
    1032           0 :   while (!untested_set.empty())
    1033             :     {
    1034             :       // Loop over all the elements in the patch that haven't already
    1035             :       // been tested
    1036           0 :       for (const auto & elem : untested_set)
    1037             :         {
    1038           0 :           for (auto current_neighbor : elem->neighbor_ptr_range())
    1039             :             {
    1040           0 :               if (current_neighbor &&
    1041           0 :                   current_neighbor != remote_elem)    // we have a real neighbor on this side
    1042             :                 {
    1043           0 :                   if (current_neighbor->active())                // ... if it is active
    1044             :                     {
    1045           0 :                       if (this->contains_edge_of(current_neighbor) // ... and touches us
    1046           0 :                           || current_neighbor->contains_edge_of(this))
    1047             :                         {
    1048             :                           // Make sure we'll test it
    1049           0 :                           if (!neighbor_set.count(current_neighbor))
    1050           0 :                             next_untested_set.insert (current_neighbor);
    1051             : 
    1052             :                           // And add it
    1053           0 :                           neighbor_set.insert (current_neighbor);
    1054             :                         }
    1055             :                     }
    1056             : #ifdef LIBMESH_ENABLE_AMR
    1057             :                   else                                 // ... the neighbor is *not* active,
    1058             :                     {                                  // ... so add *all* neighboring
    1059             :                                                        // active children
    1060           0 :                       std::vector<const Elem *> active_neighbor_children;
    1061             : 
    1062             :                       current_neighbor->active_family_tree_by_neighbor
    1063           0 :                         (active_neighbor_children, elem);
    1064             : 
    1065           0 :                       for (const auto & current_child : active_neighbor_children)
    1066           0 :                         if (this->contains_edge_of(current_child) || current_child->contains_edge_of(this))
    1067             :                           {
    1068             :                             // Make sure we'll test it
    1069           0 :                             if (!neighbor_set.count(current_child))
    1070           0 :                               next_untested_set.insert (current_child);
    1071             : 
    1072           0 :                             neighbor_set.insert (current_child);
    1073             :                           }
    1074             :                     }
    1075             : #endif // #ifdef LIBMESH_ENABLE_AMR
    1076             :                 }
    1077             :             }
    1078             :         }
    1079           0 :       untested_set.swap(next_untested_set);
    1080           0 :       next_untested_set.clear();
    1081             :     }
    1082           0 : }
    1083             : 
    1084             : 
    1085             : 
    1086        5376 : void Elem::find_interior_neighbors(std::set<const Elem *> & neighbor_set) const
    1087             : {
    1088        5376 :   ElemInternal::find_interior_neighbors(this, neighbor_set);
    1089        5376 : }
    1090             : 
    1091             : 
    1092             : 
    1093        6253 : void Elem::find_interior_neighbors(std::set<Elem *> & neighbor_set)
    1094             : {
    1095        6253 :   ElemInternal::find_interior_neighbors(this, neighbor_set);
    1096        6253 : }
    1097             : 
    1098             : 
    1099             : 
    1100    86870497 : const Elem * Elem::interior_parent () const
    1101             : {
    1102             :   // interior parents make no sense for full-dimensional elements.
    1103    86870497 :   if (this->dim() >= LIBMESH_DIM)
    1104      837377 :       return nullptr;
    1105             : 
    1106             :   // they USED TO BE only good for level-0 elements, but we now
    1107             :   // support keeping interior_parent() valid on refined boundary
    1108             :   // elements.
    1109             :   // if (this->level() != 0)
    1110             :   // return this->parent()->interior_parent();
    1111             : 
    1112             :   // We store the interior_parent pointer after both the parent
    1113             :   // neighbor and neighbor pointers
    1114    47107132 :   Elem * interior_p = _elemlinks[1+this->n_sides()];
    1115             : 
    1116             :   // If we have an interior_parent, we USED TO assume it was a
    1117             :   // one-higher-dimensional interior element, but we now allow e.g.
    1118             :   // edge elements to have a 3D interior_parent with no
    1119             :   // intermediate 2D element.
    1120             :   // libmesh_assert (!interior_p ||
    1121             :   //                interior_p->dim() == (this->dim()+1));
    1122     2466729 :   libmesh_assert (!interior_p ||
    1123             :                   (interior_p == remote_elem) ||
    1124             :                   (interior_p->dim() > this->dim()));
    1125             : 
    1126             :   // If an element in a multi-dimensional mesh has an interior_parent
    1127             :   // link, it should be at our level or coarser, just like a neighbor
    1128             :   // link.  Our collect_families() code relies on this, but it might
    1129             :   // be tempting for users to manually assign something that breaks
    1130             :   // it.
    1131             :   //
    1132             :   // However, we *also* create temporary side elements, and we don't
    1133             :   // bother with creating ancestors for those, so they can be at level
    1134             :   // 0 even when they're sides of non-level-0 elements.
    1135     2466729 :   libmesh_assert (!interior_p ||
    1136             :                   (interior_p->level() <= this->level()) ||
    1137             :                   (this->level() == 0 &&
    1138             :                    this->id() == DofObject::invalid_id));
    1139             : 
    1140    47107132 :   return interior_p;
    1141             : }
    1142             : 
    1143             : 
    1144             : 
    1145   101288689 : Elem * Elem::interior_parent ()
    1146             : {
    1147             :   // See the const version for comments
    1148   101288689 :   if (this->dim() >= LIBMESH_DIM)
    1149      520192 :       return nullptr;
    1150             : 
    1151    77623403 :   Elem * interior_p = _elemlinks[1+this->n_sides()];
    1152             : 
    1153     3179363 :   libmesh_assert (!interior_p ||
    1154             :                   (interior_p == remote_elem) ||
    1155             :                   (interior_p->dim() > this->dim()));
    1156             : 
    1157    77623403 :   return interior_p;
    1158             : }
    1159             : 
    1160             : 
    1161             : 
    1162  4480174734 : void Elem::set_interior_parent (Elem * p)
    1163             : {
    1164             :   // interior parents make no sense for full-dimensional elements.
    1165   428367584 :   libmesh_assert (!p ||
    1166             :                   this->dim() < LIBMESH_DIM);
    1167             : 
    1168             :   // If we have an interior_parent, we USED TO assume it was a
    1169             :   // one-higher-dimensional interior element, but we now allow e.g.
    1170             :   // edge elements to have a 3D interior_parent with no
    1171             :   // intermediate 2D element.
    1172             :   // libmesh_assert (!p ||
    1173             :   //                 p->dim() == (this->dim()+1));
    1174   428367584 :   libmesh_assert (!p ||
    1175             :                   (p == remote_elem) ||
    1176             :                   (p->dim() > this->dim()));
    1177             : 
    1178  4480174734 :   _elemlinks[1+this->n_sides()] = p;
    1179  4480174734 : }
    1180             : 
    1181             : 
    1182             : 
    1183             : #ifdef LIBMESH_ENABLE_PERIODIC
    1184             : 
    1185      786435 : Elem * Elem::topological_neighbor (const unsigned int i,
    1186             :                                    MeshBase & mesh,
    1187             :                                    const PointLocatorBase & point_locator,
    1188             :                                    const PeriodicBoundaries * pb)
    1189             : {
    1190      488472 :   libmesh_assert_less (i, this->n_neighbors());
    1191             : 
    1192      687080 :   Elem * neighbor_i = this->neighbor_ptr(i);
    1193      786435 :   if (neighbor_i != nullptr)
    1194      476930 :     return neighbor_i;
    1195             : 
    1196       22252 :   if (pb)
    1197             :     {
    1198             :       // Since the neighbor is nullptr it must be on a boundary. We need
    1199             :       // see if this is a periodic boundary in which case it will have a
    1200             :       // topological neighbor
    1201       11542 :       std::vector<boundary_id_type> bc_ids;
    1202       22252 :       mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
    1203       22252 :       for (const auto & id : bc_ids)
    1204       22252 :         if (pb->boundary(id))
    1205             :           {
    1206             :             // Since the point locator inside of periodic boundaries
    1207             :             // returns a const pointer we will retrieve the proper
    1208             :             // pointer directly from the mesh object.
    1209       22252 :             const Elem * const cn = pb->neighbor(id, point_locator, this, i);
    1210       11542 :             neighbor_i = const_cast<Elem *>(cn);
    1211             : 
    1212             :             // Since coarse elements do not have more refined
    1213             :             // neighbors we need to make sure that we don't return one
    1214             :             // of these types of neighbors.
    1215       22252 :             if (neighbor_i)
    1216       24573 :               while (level() < neighbor_i->level())
    1217        2026 :                 neighbor_i = neighbor_i->parent();
    1218       11542 :             return neighbor_i;
    1219             :           }
    1220             :     }
    1221             : 
    1222           0 :   return nullptr;
    1223             : }
    1224             : 
    1225             : 
    1226             : 
    1227       47450 : const Elem * Elem::topological_neighbor (const unsigned int i,
    1228             :                                          const MeshBase & mesh,
    1229             :                                          const PointLocatorBase & point_locator,
    1230             :                                          const PeriodicBoundaries * pb) const
    1231             : {
    1232       19968 :   libmesh_assert_less (i, this->n_neighbors());
    1233             : 
    1234       31168 :   const Elem * neighbor_i = this->neighbor_ptr(i);
    1235       47450 :   if (neighbor_i != nullptr)
    1236       11098 :     return neighbor_i;
    1237             : 
    1238       31230 :   if (pb)
    1239             :     {
    1240             :       // Since the neighbor is nullptr it must be on a boundary. We need
    1241             :       // see if this is a periodic boundary in which case it will have a
    1242             :       // topological neighbor
    1243        8870 :       std::vector<boundary_id_type> bc_ids;
    1244       31230 :       mesh.get_boundary_info().boundary_ids(this, cast_int<unsigned short>(i), bc_ids);
    1245       34152 :       for (const auto & id : bc_ids)
    1246       21754 :         if (pb->boundary(id))
    1247             :           {
    1248       18832 :             neighbor_i = pb->neighbor(id, point_locator, this, i);
    1249             : 
    1250             :             // Since coarse elements do not have more refined
    1251             :             // neighbors we need to make sure that we don't return one
    1252             :             // of these types of neighbors.
    1253       18832 :             if (neighbor_i)
    1254       20819 :               while (level() < neighbor_i->level())
    1255        1836 :                 neighbor_i = neighbor_i->parent();
    1256        8134 :             return neighbor_i;
    1257             :           }
    1258             :     }
    1259             : 
    1260         736 :   return nullptr;
    1261             : }
    1262             : 
    1263             : 
    1264       20006 : bool Elem::has_topological_neighbor (const Elem * elem,
    1265             :                                      const MeshBase & mesh,
    1266             :                                      const PointLocatorBase & point_locator,
    1267             :                                      const PeriodicBoundaries * pb) const
    1268             : {
    1269             :   // First see if this is a normal "interior" neighbor
    1270       20006 :   if (has_neighbor(elem))
    1271           0 :     return true;
    1272             : 
    1273       20056 :   for (auto n : this->side_index_range())
    1274       20056 :     if (this->topological_neighbor(n, mesh, point_locator, pb))
    1275       13942 :       return true;
    1276             : 
    1277           0 :   return false;
    1278             : }
    1279             : 
    1280             : 
    1281             : #endif
    1282             : 
    1283             : #ifndef NDEBUG
    1284             : 
    1285           0 : void Elem::libmesh_assert_valid_node_pointers() const
    1286             : {
    1287           0 :   libmesh_assert(this->valid_id());
    1288           0 :   for (auto n : this->node_index_range())
    1289             :     {
    1290           0 :       libmesh_assert(this->node_ptr(n));
    1291           0 :       libmesh_assert(this->node_ptr(n)->valid_id());
    1292             :     }
    1293           0 : }
    1294             : 
    1295             : 
    1296             : 
    1297     2867360 : void Elem::libmesh_assert_valid_neighbors() const
    1298             : {
    1299    14127190 :   for (auto n : this->side_index_range())
    1300             :     {
    1301    11259830 :       const Elem * neigh = this->neighbor_ptr(n);
    1302             : 
    1303             :       // Any element might have a remote neighbor; checking
    1304             :       // to make sure that's not inaccurate is tough.
    1305    11259830 :       if (neigh == remote_elem)
    1306       10136 :         continue;
    1307             : 
    1308    11249694 :       if (neigh)
    1309             :         {
    1310             :           // Only subactive elements have subactive neighbors
    1311    10621588 :           libmesh_assert (this->subactive() || !neigh->subactive());
    1312             : 
    1313    10621588 :           const Elem * elem = this;
    1314             : 
    1315             :           // If we're subactive but our neighbor isn't, its
    1316             :           // return neighbor link will be to our first active
    1317             :           // ancestor OR to our inactive ancestor of the same
    1318             :           // level as neigh,
    1319    10621588 :           if (this->subactive() && !neigh->subactive())
    1320             :             {
    1321       60504 :               for (elem = this; !elem->active();
    1322       30252 :                    elem = elem->parent())
    1323       30252 :                 libmesh_assert(elem);
    1324             :             }
    1325             :           else
    1326             :             {
    1327    10591336 :               unsigned int rev = neigh->which_neighbor_am_i(elem);
    1328    10591336 :               libmesh_assert_less (rev, neigh->n_neighbors());
    1329             : 
    1330    10591336 :               if (this->subactive() && !neigh->subactive())
    1331             :                 {
    1332           0 :                   while (neigh->neighbor_ptr(rev) != elem)
    1333             :                     {
    1334           0 :                       libmesh_assert(elem->parent());
    1335           0 :                       elem = elem->parent();
    1336             :                     }
    1337             :                 }
    1338             :               else
    1339             :                 {
    1340    10591336 :                   const Elem * nn = neigh->neighbor_ptr(rev);
    1341    10591336 :                   libmesh_assert(nn);
    1342             : 
    1343    10920376 :                   for (; elem != nn; elem = elem->parent())
    1344      329040 :                     libmesh_assert(elem);
    1345             :                 }
    1346             :             }
    1347             :         }
    1348             :       // If we don't have a neighbor and we're not subactive, our
    1349             :       // ancestors shouldn't have any neighbors in this same
    1350             :       // direction.
    1351      628106 :       else if (!this->subactive())
    1352             :         {
    1353      616862 :           const Elem * my_parent = this->parent();
    1354      883468 :           if (my_parent &&
    1355             :               // A parent with a different dimension isn't really one of
    1356             :               // our ancestors, it means we're on a boundary mesh and this
    1357             :               // is an interior mesh element for which we're on a side.
    1358             :               // Nothing to test for in that case.
    1359      266606 :               (my_parent->dim() == this->dim()))
    1360      266606 :             libmesh_assert (!my_parent->neighbor_ptr(n));
    1361             :         }
    1362             :     }
    1363     2867360 : }
    1364             : 
    1365             : #endif // !NDEBUG
    1366             : 
    1367             : 
    1368             : 
    1369   230861545 : void Elem::make_links_to_me_local(unsigned int n, unsigned int nn)
    1370             : {
    1371       77362 :   Elem * neigh = this->neighbor_ptr(n);
    1372             : 
    1373             :   // Don't bother calling this function unless it's necessary
    1374       38681 :   libmesh_assert(neigh);
    1375       38681 :   libmesh_assert(!neigh->is_remote());
    1376             : 
    1377   230861545 :   const unsigned int this_level = this->level();
    1378   230861545 :   const unsigned int neigh_level = neigh->level();
    1379             : 
    1380             :   // We never have neighbors more refined than us
    1381       38681 :   libmesh_assert_less_equal (neigh_level, this_level);
    1382             : 
    1383             :   // We never have subactive neighbors of non subactive elements
    1384       38681 :   libmesh_assert(!neigh->subactive() || this->subactive());
    1385             : 
    1386             :   // If we have a neighbor less refined than us then it must not
    1387             :   // have any more refined descendants we could have pointed to
    1388             :   // instead.
    1389       38681 :   libmesh_assert((neigh_level == this_level) ||
    1390             :                  (neigh->active() && !this->subactive()) ||
    1391             :                  (!neigh->has_children() && this->subactive()));
    1392             : 
    1393             :   // What side of neigh are we on?  nn.
    1394             :   //
    1395             :   // We can't use the usual Elem method because we're in the middle of
    1396             :   // restoring topology.  We can't compare side_ptr nodes because
    1397             :   // users want to abuse neighbor_ptr to point to
    1398             :   // not-technically-neighbors across mesh slits.  We can't compare
    1399             :   // node locations because users want to move those
    1400             :   // not-technically-neighbors until they're
    1401             :   // not-even-geometrically-neighbors.
    1402             : 
    1403             :   // Find any elements that might need to point to elem
    1404       77362 :   std::vector<Elem *> neigh_family;
    1405             : #ifdef LIBMESH_ENABLE_AMR
    1406   230861545 :   neigh->total_family_tree_by_side(neigh_family, nn);
    1407             : #else
    1408             :   neigh_family.push_back(neigh);
    1409             : #endif
    1410             : 
    1411             :   // Pull objects out of the loop to reduce heap operations
    1412   230861545 :   std::unique_ptr<Elem> my_side, neigh_side;
    1413             : 
    1414             :   // And point them to elem
    1415   525821636 :   for (auto & neigh_family_member : neigh_family)
    1416             :     {
    1417             :       // Only subactive elements point to other subactive elements
    1418   294960091 :       const bool member_subactive = neigh_family_member->subactive();
    1419   294960091 :       if (this->subactive() && !member_subactive)
    1420       14232 :         continue;
    1421             : 
    1422             :       // neigh (and possibly some of its family) might be at a lower
    1423             :       // level than us, with a neighbor at that lower level.  We
    1424             :       // would exit early if neigh was at a lower level, except we do
    1425             :       // want to handle neighbor links from subactive descendents.
    1426   294958239 :       const unsigned int member_level = neigh_family_member->level();
    1427   294958239 :       if (member_level < this_level)
    1428     1968026 :         continue;
    1429             : 
    1430             :       // Ideally, the neighbor link ought to either be correct
    1431             :       // already or ought to be to remote_elem.
    1432             :       //
    1433             :       // However, if we're redistributing a newly created elem,
    1434             :       // after an AMR step but before find_neighbors has fixed up
    1435             :       // neighbor links, we might have an out of date neighbor
    1436             :       // link to elem's parent instead.
    1437             : #ifdef LIBMESH_ENABLE_AMR
    1438       51061 :       libmesh_assert((neigh_family_member->neighbor_ptr(nn) &&
    1439             :                       (neigh_family_member->neighbor_ptr(nn)->active() ||
    1440             :                        this->is_ancestor_of(neigh_family_member->neighbor_ptr(nn)) ||
    1441             :                        neigh_family_member->neighbor_ptr(nn)->is_ancestor_of(this))) ||
    1442             :                      (neigh_family_member->neighbor_ptr(nn) == remote_elem) ||
    1443             :                      ((this->refinement_flag() == JUST_REFINED) &&
    1444             :                       (this->parent() != nullptr) &&
    1445             :                       (neigh_family_member->neighbor_ptr(nn) == this->parent())));
    1446             : #else
    1447             :       libmesh_assert((neigh_family_member->neighbor_ptr(nn) == this) ||
    1448             :                      (neigh_family_member->neighbor_ptr(nn) == remote_elem));
    1449             : #endif
    1450             : 
    1451             :       // Some of neigh's family might be at a higher (finer) level
    1452             :       // than us, and might need to point back to one of our children
    1453             :       // rather than to us.
    1454   292990213 :       if (member_level > this_level)
    1455             :         {
    1456    64073502 :           if (this->ancestor())
    1457    63238571 :             continue;
    1458             : 
    1459      822551 :           if (member_subactive && this->has_children())
    1460       15036 :             continue;
    1461             :         }
    1462             : 
    1463             :       // If neigh is at a coarser level than us, some of neigh's
    1464             :       // subactive family just won't line up with us!
    1465   229724226 :       if (neigh_level < this_level &&
    1466           0 :           member_level > neigh_level)
    1467             :         {
    1468           0 :           libmesh_assert(member_subactive);
    1469             : 
    1470       25044 :           this->side_ptr(my_side, n);
    1471       25044 :           neigh_family_member->side_ptr(neigh_side, nn);
    1472             : 
    1473       25044 :           if (*my_side != *neigh_side)
    1474       16996 :             continue;
    1475             :         }
    1476             : 
    1477   229707230 :       neigh_family_member->set_neighbor(nn, this);
    1478             :     }
    1479   461645728 : }
    1480             : 
    1481             : 
    1482    36156743 : void Elem::make_links_to_me_remote()
    1483             : {
    1484        1801 :   libmesh_assert_not_equal_to (this, remote_elem);
    1485             : 
    1486             :   // We need to have handled any children first
    1487             : #if defined(LIBMESH_ENABLE_AMR) && defined(DEBUG)
    1488        1801 :   if (this->has_children())
    1489         268 :     for (auto & child : this->child_ref_range())
    1490         208 :       libmesh_assert_equal_to (&child, remote_elem);
    1491             : #endif
    1492             : 
    1493             :   // Remotify any neighbor links
    1494   183281867 :   for (auto neigh : this->neighbor_ptr_range())
    1495             :     {
    1496   147125124 :       if (neigh && neigh != remote_elem)
    1497             :         {
    1498             :           // My neighbor should never be more refined than me; my real
    1499             :           // neighbor would have been its parent in that case.
    1500        3916 :           libmesh_assert_greater_equal (this->level(), neigh->level());
    1501             : 
    1502   141875551 :           if (this->level() == neigh->level() &&
    1503    70596529 :               neigh->has_neighbor(this))
    1504             :             {
    1505             : #ifdef LIBMESH_ENABLE_AMR
    1506             :               // My neighbor may have descendants which also consider me a
    1507             :               // neighbor
    1508        7832 :               std::vector<Elem *> family;
    1509    70599818 :               neigh->total_family_tree_by_neighbor (family, this);
    1510             : 
    1511             :               // FIXME - There's a lot of ugly const_casts here; we
    1512             :               // may want to make remote_elem non-const
    1513   141207431 :               for (auto & n : family)
    1514             :                 {
    1515        3916 :                   libmesh_assert (n);
    1516    70607613 :                   if (n == remote_elem)
    1517           0 :                     continue;
    1518    70607613 :                   unsigned int my_s = n->which_neighbor_am_i(this);
    1519        3916 :                   libmesh_assert_less (my_s, n->n_neighbors());
    1520        3916 :                   libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
    1521    70607613 :                   n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
    1522             :                 }
    1523             : #else
    1524             :               unsigned int my_s = neigh->which_neighbor_am_i(this);
    1525             :               libmesh_assert_less (my_s, neigh->n_neighbors());
    1526             :               libmesh_assert_equal_to (neigh->neighbor_ptr(my_s), this);
    1527             :               neigh->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
    1528             : #endif
    1529             :             }
    1530             : #ifdef LIBMESH_ENABLE_AMR
    1531             :           // Even if my neighbor doesn't link back to me, it might
    1532             :           // have subactive descendants which do
    1533           0 :           else if (neigh->has_children())
    1534             :             {
    1535             :               // If my neighbor at the same level doesn't have me as a
    1536             :               // neighbor, I must be subactive
    1537           0 :               libmesh_assert(this->level() > neigh->level() ||
    1538             :                              this->subactive());
    1539             : 
    1540             :               // My neighbor must have some ancestor of mine as a
    1541             :               // neighbor
    1542           0 :               Elem * my_ancestor = this->parent();
    1543           0 :               libmesh_assert(my_ancestor);
    1544        1760 :               while (!neigh->has_neighbor(my_ancestor))
    1545             :                 {
    1546           0 :                   my_ancestor = my_ancestor->parent();
    1547           0 :                   libmesh_assert(my_ancestor);
    1548             :                 }
    1549             : 
    1550             :               // My neighbor may have descendants which consider me a
    1551             :               // neighbor
    1552           0 :               std::vector<Elem *> family;
    1553        1760 :               neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
    1554             : 
    1555        2874 :               for (auto & n : family)
    1556             :                 {
    1557           0 :                   libmesh_assert (n);
    1558        1114 :                   if (n->is_remote())
    1559           0 :                     continue;
    1560        1114 :                   unsigned int my_s = n->which_neighbor_am_i(this);
    1561           0 :                   libmesh_assert_less (my_s, n->n_neighbors());
    1562           0 :                   libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
    1563             :                   // TODO: we may want to make remote_elem non-const.
    1564        1114 :                   n->set_neighbor(my_s, const_cast<RemoteElem *>(remote_elem));
    1565             :                 }
    1566             :             }
    1567             : #endif
    1568             :         }
    1569             :     }
    1570             : 
    1571             : #ifdef LIBMESH_ENABLE_AMR
    1572             :   // Remotify parent's child link
    1573        3602 :   Elem * my_parent = this->parent();
    1574    26999795 :   if (my_parent &&
    1575             :       // As long as it's not already remote
    1576    63154737 :       my_parent != remote_elem &&
    1577             :       // And it's a real parent, not an interior parent
    1578    26997994 :       this->dim() == my_parent->dim())
    1579             :     {
    1580    26997994 :       unsigned int me = my_parent->which_child_am_i(this);
    1581         672 :       libmesh_assert_equal_to (my_parent->child_ptr(me), this);
    1582    26997994 :       my_parent->set_child(me, const_cast<RemoteElem *>(remote_elem));
    1583             :     }
    1584             : #endif
    1585    36156743 : }
    1586             : 
    1587             : 
    1588         813 : void Elem::remove_links_to_me()
    1589             : {
    1590          31 :   libmesh_assert_not_equal_to (this, remote_elem);
    1591             : 
    1592             :   // We need to have handled any children first
    1593             : #ifdef LIBMESH_ENABLE_AMR
    1594          31 :   libmesh_assert (!this->has_children());
    1595             : #endif
    1596             : 
    1597             :   // Nullify any neighbor links
    1598        4065 :   for (auto neigh : this->neighbor_ptr_range())
    1599             :     {
    1600        3252 :       if (neigh && neigh != remote_elem)
    1601             :         {
    1602             :           // My neighbor should never be more refined than me; my real
    1603             :           // neighbor would have been its parent in that case.
    1604          47 :           libmesh_assert_greater_equal (this->level(), neigh->level());
    1605             : 
    1606        2504 :           if (this->level() == neigh->level() &&
    1607        1205 :               neigh->has_neighbor(this))
    1608             :             {
    1609             : #ifdef LIBMESH_ENABLE_AMR
    1610             :               // My neighbor may have descendants which also consider me a
    1611             :               // neighbor
    1612          94 :               std::vector<Elem *> family;
    1613        1252 :               neigh->total_family_tree_by_neighbor (family, this);
    1614             : 
    1615        2504 :               for (auto & n : family)
    1616             :                 {
    1617          47 :                   libmesh_assert (n);
    1618        1252 :                   if (n->is_remote())
    1619           0 :                     continue;
    1620        1252 :                   unsigned int my_s = n->which_neighbor_am_i(this);
    1621          47 :                   libmesh_assert_less (my_s, n->n_neighbors());
    1622          47 :                   libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
    1623        1252 :                   n->set_neighbor(my_s, nullptr);
    1624             :                 }
    1625             : #else
    1626             :               unsigned int my_s = neigh->which_neighbor_am_i(this);
    1627             :               libmesh_assert_less (my_s, neigh->n_neighbors());
    1628             :               libmesh_assert_equal_to (neigh->neighbor_ptr(my_s), this);
    1629             :               neigh->set_neighbor(my_s, nullptr);
    1630             : #endif
    1631             :             }
    1632             : #ifdef LIBMESH_ENABLE_AMR
    1633             :           // Even if my neighbor doesn't link back to me, it might
    1634             :           // have subactive descendants which do
    1635           0 :           else if (neigh->has_children())
    1636             :             {
    1637             :               // If my neighbor at the same level doesn't have me as a
    1638             :               // neighbor, I must be subactive
    1639           0 :               libmesh_assert(this->level() > neigh->level() ||
    1640             :                              this->subactive());
    1641             : 
    1642             :               // My neighbor must have some ancestor of mine as a
    1643             :               // neighbor
    1644           0 :               Elem * my_ancestor = this->parent();
    1645           0 :               libmesh_assert(my_ancestor);
    1646           0 :               while (!neigh->has_neighbor(my_ancestor))
    1647             :                 {
    1648           0 :                   my_ancestor = my_ancestor->parent();
    1649           0 :                   libmesh_assert(my_ancestor);
    1650             :                 }
    1651             : 
    1652             :               // My neighbor may have descendants which consider me a
    1653             :               // neighbor
    1654           0 :               std::vector<Elem *> family;
    1655           0 :               neigh->total_family_tree_by_subneighbor (family, my_ancestor, this);
    1656             : 
    1657           0 :               for (auto & n : family)
    1658             :                 {
    1659           0 :                   libmesh_assert (n);
    1660           0 :                   if (n->is_remote())
    1661           0 :                     continue;
    1662           0 :                   unsigned int my_s = n->which_neighbor_am_i(this);
    1663           0 :                   libmesh_assert_less (my_s, n->n_neighbors());
    1664           0 :                   libmesh_assert_equal_to (n->neighbor_ptr(my_s), this);
    1665           0 :                   n->set_neighbor(my_s, nullptr);
    1666             :                 }
    1667             :             }
    1668             : #endif
    1669             :         }
    1670             :     }
    1671             : 
    1672             : #ifdef LIBMESH_ENABLE_AMR
    1673             :   // We can't currently delete a child with a parent!
    1674          31 :   libmesh_assert (!this->parent());
    1675             : #endif
    1676         813 : }
    1677             : 
    1678             : 
    1679             : 
    1680      178350 : void Elem::write_connectivity (std::ostream & out_stream,
    1681             :                                const IOPackage iop) const
    1682             : {
    1683       16310 :   libmesh_assert (out_stream.good());
    1684       16310 :   libmesh_assert(_nodes);
    1685       16310 :   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
    1686             : 
    1687      178350 :   switch (iop)
    1688             :     {
    1689       16185 :     case TECPLOT:
    1690             :       {
    1691             :         // This connectivity vector will be used repeatedly instead
    1692             :         // of being reconstructed inside the loop.
    1693       32370 :         std::vector<dof_id_type> conn;
    1694      498180 :         for (auto sc : make_range(this->n_sub_elem()))
    1695             :           {
    1696      176850 :             this->connectivity(sc, TECPLOT, conn);
    1697             : 
    1698      176850 :             std::copy(conn.begin(),
    1699             :                       conn.end(),
    1700       16185 :                       std::ostream_iterator<dof_id_type>(out_stream, " "));
    1701             : 
    1702      176850 :             out_stream << '\n';
    1703             :           }
    1704       16185 :         return;
    1705             :       }
    1706             : 
    1707         125 :     case UCD:
    1708             :       {
    1709       13500 :         for (auto i : this->node_index_range())
    1710       13000 :           out_stream << this->node_id(i)+1 << "\t";
    1711             : 
    1712        1500 :         out_stream << '\n';
    1713        1500 :         return;
    1714             :       }
    1715             : 
    1716           0 :     default:
    1717           0 :       libmesh_error_msg("Unsupported IO package " << iop);
    1718             :     }
    1719             : }
    1720             : 
    1721             : 
    1722             : 
    1723     1417981 : Real Elem::quality (const ElemQuality q) const
    1724             : {
    1725     1417981 :   switch (q)
    1726             :     {
    1727             :       // Return the maximum ratio of edge lengths, or zero if that
    1728             :       // maximum would otherwise be infinity.
    1729       33297 :     case EDGE_LENGTH_RATIO:
    1730             :       {
    1731       33297 :         if (this->dim() < 2)
    1732           7 :           return 1;
    1733             : 
    1734       35986 :         std::vector<Real> edge_lengths(this->n_edges());
    1735      274215 :         for (auto e : index_range(edge_lengths))
    1736      461889 :           edge_lengths[e] = (this->point(this->local_edge_node(e,1)) -
    1737      461889 :                              this->point(this->local_edge_node(e,0))).norm();
    1738             : 
    1739        2773 :         auto [min, max] =
    1740       33213 :           std::minmax_element(edge_lengths.begin(), edge_lengths.end());
    1741             : 
    1742       33213 :         if (*min == 0.)
    1743           0 :           return 0.;
    1744             :         else
    1745       33213 :           return *max / *min;
    1746             :       }
    1747             : 
    1748      267652 :     case MIN_ANGLE:
    1749             :     case MAX_ANGLE:
    1750             :       {
    1751             :         // 1D elements don't have interior angles, so just return some
    1752             :         // dummy value in that case.
    1753      267652 :         if (this->dim() < 2)
    1754          14 :           return 0.;
    1755             : 
    1756             :         // Initialize return values
    1757      267484 :         Real min_angle = std::numeric_limits<Real>::max();
    1758      267484 :         Real max_angle = -std::numeric_limits<Real>::max();
    1759             : 
    1760     3031040 :         for (auto n : this->node_index_range())
    1761             :           {
    1762             :             // Get list of edge ids adjacent to this node.
    1763     2763556 :             const auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
    1764             : 
    1765             :             // Skip any nodes with fewer than 2 adjacent edges. You
    1766             :             // need at least two adjacent edges to form an interior
    1767             :             // element angle.
    1768      460364 :             auto N = adjacent_edge_ids.size();
    1769     2763556 :             if (N < 2)
    1770      131946 :               continue;
    1771             : 
    1772             :             // Consider all possible pairs of edges adjacent to node n
    1773     3515652 :             for (unsigned int first = 0; first < N-1; ++first)
    1774     5850332 :               for (unsigned int second = first+1; second < N; ++second)
    1775             :                 {
    1776             :                   // Get ids of first and second edges
    1777     3808532 :                   auto first_edge = adjacent_edge_ids[first];
    1778     3515748 :                   auto second_edge = adjacent_edge_ids[second];
    1779             : 
    1780             :                   // Get node ids of first and second edge
    1781     3515748 :                   auto first_edge_node_0 = this->local_edge_node(first_edge, 0);
    1782     3515748 :                   auto first_edge_node_1 = this->local_edge_node(first_edge, 1);
    1783     3515748 :                   auto second_edge_node_0 = this->local_edge_node(second_edge, 0);
    1784     3515748 :                   auto second_edge_node_1 = this->local_edge_node(second_edge, 1);
    1785             : 
    1786             :                   // Orient both edges so that edge node 0 == n
    1787     3515748 :                   if (first_edge_node_0 != n)
    1788      201378 :                     std::swap(first_edge_node_0, first_edge_node_1);
    1789     3515748 :                   if (second_edge_node_0 != n)
    1790       95984 :                     std::swap(second_edge_node_0, second_edge_node_1);
    1791             : 
    1792      292784 :                   libmesh_assert_equal_to(first_edge_node_0, n);
    1793      292784 :                   libmesh_assert_equal_to(second_edge_node_0, n);
    1794             : 
    1795             :                   // Locally oriented edge vectors
    1796             :                   Point
    1797      585568 :                     first_ev = this->point(first_edge_node_1) - this->point(first_edge_node_0),
    1798      292784 :                     second_ev = this->point(second_edge_node_1) - this->point(second_edge_node_0);
    1799             : 
    1800             :                   // Angle between them in the range [0, pi]
    1801     3515748 :                   Real theta = std::acos(first_ev.unit() * second_ev.unit());
    1802             : 
    1803             :                   // Track min and max angles seen
    1804     3515748 :                   min_angle = std::min(theta, min_angle);
    1805     3515748 :                   max_angle = std::max(theta, max_angle);
    1806             :                 }
    1807             :           }
    1808             : 
    1809             :         // Return requested extreme value (in degrees)
    1810      267484 :         return Real(180)/libMesh::pi * ((q == MIN_ANGLE) ? min_angle : max_angle);
    1811             :       }
    1812             : 
    1813      257764 :     case MIN_DIHEDRAL_ANGLE:
    1814             :     case MAX_DIHEDRAL_ANGLE:
    1815             :       {
    1816             :         // For 1D and 2D elements, just call this function with MIN,MAX_ANGLE instead.
    1817      257764 :         if (this->dim() < 3)
    1818        8680 :           return this->quality((q == MIN_DIHEDRAL_ANGLE) ? MIN_ANGLE : MAX_ANGLE);
    1819             : 
    1820             :         // Initialize return values
    1821      251812 :         Real min_angle = std::numeric_limits<Real>::max();
    1822      251812 :         Real max_angle = -std::numeric_limits<Real>::max();
    1823             : 
    1824             :         // Algorithm for computing dihedral angles:
    1825             :         // .) Loop over the edges, use the edge_sides_map to get the
    1826             :         //    two sides adjacent to the edge.
    1827             :         // .) For each adjacent side, use the side_nodes_map to get the
    1828             :         //    list of three (or more) node ids on that side.
    1829             :         // .) Use the node ids to compute the (approximate) inward
    1830             :         //    normal for the side.  Note: this is approximate since 3D
    1831             :         //    elements with four-sided faces and quadratic tetrahedra
    1832             :         //    do not necessarily have planar faces.
    1833             :         // .) Compute the dihedral angle for the current edge, compare
    1834             :         //    it to the current min and max dihedral angles.
    1835     1954672 :         for (auto e : this->edge_index_range())
    1836             :           {
    1837             :             // Get list of edge ids adjacent to this node.
    1838     1844772 :             const auto adjacent_side_ids = this->sides_on_edge(e);
    1839             : 
    1840             :             // All 3D elements should have exactly two sides adjacent to each edge.
    1841      141912 :             libmesh_assert_equal_to(adjacent_side_ids.size(), 2);
    1842             : 
    1843             :             // Get lists of node ids on each side
    1844     1844772 :             const auto side_0_node_ids = this->nodes_on_side(adjacent_side_ids[0]);
    1845     1702860 :             const auto side_1_node_ids = this->nodes_on_side(adjacent_side_ids[1]);
    1846             : 
    1847             :             // All 3D elements have at least three nodes on each side
    1848      141912 :             libmesh_assert_greater_equal(side_0_node_ids.size(), 3);
    1849      141912 :             libmesh_assert_greater_equal(side_1_node_ids.size(), 3);
    1850             : 
    1851             :             // Construct (approximate) inward normal on each adjacent side
    1852             :             const auto side_0_normal =
    1853     1844772 :               (this->point(side_0_node_ids[2]) - this->point(side_0_node_ids[0])).cross
    1854     1844772 :               (this->point(side_0_node_ids[1]) - this->point(side_0_node_ids[0])).unit();
    1855             :             const auto side_1_normal =
    1856     1844772 :               (this->point(side_1_node_ids[2]) - this->point(side_1_node_ids[0])).cross
    1857     1844772 :               (this->point(side_1_node_ids[1]) - this->point(side_1_node_ids[0])).unit();
    1858             : 
    1859             :             // Compute dihedral angle between the planes.
    1860             :             // Using the absolute value ensures that we get the same result
    1861             :             // even if the orientation of one of the planes is flipped, i.e.
    1862             :             // it always gives us a value in the range [0, pi/2].
    1863             :             // https://en.wikipedia.org/wiki/Dihedral_angle
    1864     1702860 :             Real theta = std::acos(std::abs(side_0_normal * side_1_normal));
    1865             : 
    1866             :             // Track min and max angles seen
    1867     1702860 :             min_angle = std::min(theta, min_angle);
    1868     1702860 :             max_angle = std::max(theta, max_angle);
    1869             :           }
    1870             : 
    1871             :         // Return requested extreme value (in degrees)
    1872      251812 :         return Real(180)/libMesh::pi * ((q == MIN_DIHEDRAL_ANGLE) ? min_angle : max_angle);
    1873             :       }
    1874             : 
    1875      231202 :     case JACOBIAN:
    1876             :     case SCALED_JACOBIAN:
    1877             :       {
    1878             :         // 1D elements don't have interior corners, so this metric
    1879             :         // does not really apply to them.
    1880      231202 :         const auto N = this->dim();
    1881      231202 :         if (N < 2)
    1882          14 :           return 1.;
    1883             : 
    1884             :         // Initialize return value
    1885      231034 :         Real min_node_area = std::numeric_limits<Real>::max();
    1886             : 
    1887     2520086 :         for (auto n : this->node_index_range())
    1888             :           {
    1889             :             // Get list of edge ids adjacent to this node.
    1890     2289052 :             auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
    1891             : 
    1892             :             // Skip any nodes that don't have dim() adjacent edges. In 2D,
    1893             :             // you need at least two adjacent edges to compute the cross
    1894             :             // product, and in 3D, you need at least three adjacent edges
    1895             :             // to compute the scalar triple product. The only element
    1896             :             // type which has an unusual topology in this regard is the
    1897             :             // Pyramid element in 3D, where 4 edges meet at the apex node.
    1898             :             // For now, we just skip this node when computing the JACOBIAN
    1899             :             // metric for Pyramids.
    1900     2479786 :             if (adjacent_edge_ids.size() != N)
    1901      108744 :               continue;
    1902             : 
    1903             :             // Construct oriented edges
    1904      984988 :             std::vector<Point> oriented_edges(N);
    1905     3910064 :             for (auto i : make_range(N))
    1906             :               {
    1907     3168612 :                 auto node_0 = this->local_edge_node(adjacent_edge_ids[i], 0);
    1908     3168612 :                 auto node_1 = this->local_edge_node(adjacent_edge_ids[i], 1);
    1909     2925076 :                 if (node_0 != n)
    1910      120978 :                   std::swap(node_0, node_1);
    1911     3412148 :                 oriented_edges[i] = this->point(node_1) - this->point(node_0);
    1912             :               }
    1913             : 
    1914             :             // Compute unscaled area (2D) or volume (3D) using the
    1915             :             // cross product (2D) or scalar triple product (3D) of the
    1916             :             // oriented edges. We take the absolute value so that we
    1917             :             // don't have to worry about the sign of the area.
    1918      984988 :             Real node_area = (N == 2) ?
    1919       29888 :               cross_norm(oriented_edges[0], oriented_edges[1]) :
    1920      955100 :               std::abs(triple_product(oriented_edges[0], oriented_edges[1], oriented_edges[2]));
    1921             : 
    1922             :             // Divide by (non-zero) edge lengths if computing scaled Jacobian.
    1923             :             // If any length is zero, then set node_area to zero. This means that
    1924             :             // e.g. degenerate quadrilaterals will have a zero SCALED_JACOBIAN metric.
    1925      984988 :             if (q == SCALED_JACOBIAN)
    1926     2018392 :               for (auto i : make_range(N))
    1927             :                 {
    1928     1509770 :                   Real len_i = oriented_edges[i].norm();
    1929     1509770 :                   node_area = (len_i == 0.) ? 0. : (node_area / len_i);
    1930             :                 }
    1931             : 
    1932             :             // Update minimum
    1933      984988 :             min_node_area = std::min(node_area, min_node_area);
    1934             :           }
    1935             : 
    1936      231034 :         return min_node_area;
    1937             :       }
    1938             : 
    1939             :       // Relative size metric: min over the corner nodes of min(tau,
    1940             :       // 1/tau), where tau is the ratio of the corner's nodal Jacobian
    1941             :       // determinant to that of the ideal (regular) element of the same
    1942             :       // volume -- ReferenceElem::ideal_target(), rescaled to this
    1943             :       // element's volume via the volume ratio. tau = 1 at every corner
    1944             :       // of an element whose Jacobian is uniform (any affine element:
    1945             :       // parallelogram, box, or regular simplex, at any scale), so the
    1946             :       // metric is 1; non-uniform (tapered/sheared) elements score below
    1947             :       // 1, and a degenerate corner drives it to 0.
    1948      108472 :     case SIZE:
    1949             :       {
    1950             :         // 1D elements don't have interior corners, so this metric does
    1951             :         // not really apply to them.
    1952      108472 :         const auto N = this->dim();
    1953      108472 :         if (N < 2)
    1954           0 :           return 1.;
    1955             : 
    1956      108472 :         const Real vol = this->volume();
    1957      108472 :         if (vol == 0.)
    1958           0 :           return 0.;
    1959             : 
    1960             :         // Ideal (regular) element of the same type; its Jacobian is
    1961             :         // uniform. We compare nodal determinants after rescaling it to
    1962             :         // this element's volume, i.e. multiply by ideal_vol / this_vol.
    1963      126488 :         const auto ideal_pair = ReferenceElem::ideal_target(this->type());
    1964        9008 :         const Elem & ideal = *ideal_pair.first;
    1965      108472 :         const Real vol_ratio = ideal.volume() / vol;
    1966             : 
    1967             :         // Nodal Jacobian determinant at node n of element el (the same
    1968             :         // construction as the JACOBIAN metric above).
    1969      771976 :         auto nodal_det = [](const Elem & el, const unsigned int n,
    1970             :                             const std::vector<unsigned int> & edge_ids,
    1971      153568 :                             const unsigned int dim)
    1972             :         {
    1973      925544 :           std::vector<Point> e(dim);
    1974     3673992 :           for (unsigned int i = 0; i != dim; ++i)
    1975             :             {
    1976     2976608 :               auto n0 = el.local_edge_node(edge_ids[i], 0);
    1977     2976608 :               auto n1 = el.local_edge_node(edge_ids[i], 1);
    1978     2748448 :               if (n0 != n)
    1979      114080 :                 std::swap(n0, n1);
    1980     3204768 :               e[i] = el.point(n1) - el.point(n0);
    1981             :             }
    1982      925544 :           return (dim == 2) ? cross_norm(e[0], e[1])
    1983     1825096 :                             : std::abs(triple_product(e[0], e[1], e[2]));
    1984             :         };
    1985             : 
    1986      108472 :         Real size = 1.;
    1987        9008 :         bool have_corner = false;
    1988     1173260 :         for (auto n : this->node_index_range())
    1989             :           {
    1990             :             // Skip any nodes that don't have dim() adjacent edges (see
    1991             :             // the JACOBIAN metric above for the Pyramid apex caveat).
    1992     1064788 :             const auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
    1993     1153348 :             if (adjacent_edge_ids.size() != N)
    1994       50168 :               continue;
    1995       38392 :             have_corner = true;
    1996             : 
    1997      462772 :             const Real a  = nodal_det(*this, n, adjacent_edge_ids, N);
    1998      462772 :             const Real aw = nodal_det(ideal, n, adjacent_edge_ids, N);
    1999             : 
    2000             :             // Degenerate corner: worst quality.
    2001      462772 :             if (a == 0. || aw == 0.)
    2002           0 :               return 0.;
    2003             : 
    2004      462772 :             const Real tau = (a / aw) * vol_ratio;
    2005      887152 :             size = std::min(size, std::min(tau, Real(1) / tau));
    2006             :           }
    2007             : 
    2008      108472 :         return have_corner ? size : 0.;
    2009             :       }
    2010             : 
    2011             :       // Maximum condition number of the nodal Jacobian over the corner
    2012             :       // nodes, measured against the ideal (regular) element rather than
    2013             :       // the reference element. At each corner the physical nodal
    2014             :       // Jacobian A and the ideal nodal Jacobian W (taken from the same
    2015             :       // corner of ReferenceElem::ideal_target) give the weighted
    2016             :       // Jacobian A W^{-1}, whose Frobenius condition number, via the
    2017             :       // corner metric tensors T_A = A^T A and T_W = W^T W (which also
    2018             :       // handles a lower-dimensional element embedded in 3D), is
    2019             :       //   kappa = sqrt(tr(T_A T_W^{-1}) * tr(T_W T_A^{-1})) / N.
    2020             :       // This is 1 for a corner similar to the ideal one -- so an
    2021             :       // equilateral triangle or regular tetrahedron scores 1, not just
    2022             :       // a right-angled corner -- and grows with distortion. A
    2023             :       // degenerate corner has an infinite condition number, reported as
    2024             :       // 0 (0 stands in for infinity, cf. EDGE_LENGTH_RATIO).
    2025      108330 :     case CONDITION:
    2026             :       {
    2027             :         // 1D elements don't have interior corners, so this metric does
    2028             :         // not really apply to them.
    2029      108330 :         const auto N = this->dim();
    2030      108330 :         if (N < 2)
    2031           0 :           return 1.;
    2032             : 
    2033             :         // Ideal (regular) element of the same type; W is its nodal
    2034             :         // Jacobian. Its scale is irrelevant here (the condition number
    2035             :         // is scale invariant), so the reference-volume sizing is fine.
    2036      126338 :         const auto ideal_pair = ReferenceElem::ideal_target(this->type());
    2037        9004 :         const Elem & ideal = *ideal_pair.first;
    2038             : 
    2039             :         // Corner metric tensor T = A^T A at node n of element el, padded
    2040             :         // with the identity in unused dimensions so that RealTensor's
    2041             :         // 3x3 inverse yields the correct NxN inverse.
    2042      770368 :         auto metric_tensor = [](const Elem & el, const unsigned int n,
    2043             :                                 const std::vector<unsigned int> & edge_ids,
    2044      153472 :                                 const unsigned int dim)
    2045             :         {
    2046     1000576 :           std::vector<Point> e(dim);
    2047     3667744 :           for (unsigned int i = 0; i != dim; ++i)
    2048             :             {
    2049     2971936 :               auto n0 = el.local_edge_node(edge_ids[i], 0);
    2050     2971936 :               auto n1 = el.local_edge_node(edge_ids[i], 1);
    2051     2743904 :               if (n0 != n)
    2052      114016 :                 std::swap(n0, n1);
    2053     3199968 :               e[i] = el.point(n1) - el.point(n0);
    2054             :             }
    2055      847104 :           RealTensor T(1, 0, 0,  0, 1, 0,  0, 0, 1);
    2056     3667744 :           for (unsigned int i = 0; i != dim; ++i)
    2057    10920384 :             for (unsigned int j = 0; j != dim; ++j)
    2058     9535968 :               T(i, j) = e[i] * e[j];
    2059     1000576 :           return T;
    2060             :         };
    2061             : 
    2062             :         // kappa >= 1 for every matrix, so 1 is both the ideal value and
    2063             :         // a safe floor for the running maximum.
    2064      108330 :         Real max_cond = 1.;
    2065             : 
    2066     1172266 :         for (auto n : this->node_index_range())
    2067             :           {
    2068             :             // Skip any nodes that don't have dim() adjacent edges (see
    2069             :             // the JACOBIAN metric above for the Pyramid apex caveat).
    2070     1063936 :             const auto adjacent_edge_ids = this->edges_adjacent_to_node(n);
    2071     1152472 :             if (adjacent_edge_ids.size() != N)
    2072       50168 :               continue;
    2073             : 
    2074      461920 :             const RealTensor Ta = metric_tensor(*this, n, adjacent_edge_ids, N);
    2075             : 
    2076             :             // Degenerate corner: infinite condition number.
    2077      461920 :             if (Ta.det() == 0.)
    2078           0 :               return 0.;
    2079             : 
    2080      500288 :             const RealTensor Tw = metric_tensor(ideal, n, adjacent_edge_ids, N);
    2081      500288 :             const RealTensor Ta_inv = Ta.inverse();
    2082      461920 :             const RealTensor Tw_inv = Tw.inverse();
    2083             : 
    2084             :             // num1 = tr(T_A T_W^{-1}), num2 = tr(T_W T_A^{-1}) over the
    2085             :             // NxN blocks (both symmetric, so summed as elementwise dot
    2086             :             // products).
    2087       38368 :             Real num1 = 0., num2 = 0.;
    2088     1833872 :             for (auto i : make_range(N))
    2089     5460192 :               for (auto j : make_range(N))
    2090             :                 {
    2091     4088240 :                   num1 += Ta(i, j) * Tw_inv(i, j);
    2092     4088240 :                   num2 += Tw(i, j) * Ta_inv(i, j);
    2093             :                 }
    2094             : 
    2095      592964 :             max_cond = std::max(max_cond, std::sqrt(num1 * num2) / N);
    2096             :           }
    2097             : 
    2098      108330 :         return max_cond;
    2099             :       }
    2100             : 
    2101             :       // Return 1 if we made it here
    2102      411264 :     default:
    2103             :       {
    2104      411471 :         libmesh_do_once( libmesh_here();
    2105             : 
    2106             :                          libMesh::err << "ERROR: quality metric "
    2107             :                          << Utility::enum_to_string(q)
    2108             :                          << " not implemented on element type "
    2109             :                          << Utility::enum_to_string(this->type())
    2110             :                          << std::endl
    2111             :                          << "Returning 1."
    2112             :                          << std::endl; );
    2113             : 
    2114       34272 :         return 1.;
    2115             :       }
    2116             :     }
    2117             : }
    2118             : 
    2119             : 
    2120             : 
    2121   138187255 : bool Elem::ancestor() const
    2122             : {
    2123             : #ifdef LIBMESH_ENABLE_AMR
    2124             : 
    2125             :   // Use a fast, DistributedMesh-safe definition
    2126             :   const bool is_ancestor =
    2127    86729329 :     !this->active() && !this->subactive();
    2128             : 
    2129             :   // But check for inconsistencies if we have time
    2130             : #ifdef DEBUG
    2131     5382328 :   if (!is_ancestor && this->has_children())
    2132             :     {
    2133      518656 :       for (auto & c : this->child_ref_range())
    2134             :         {
    2135      415616 :           if (&c != remote_elem)
    2136             :             {
    2137      415568 :               libmesh_assert(!c.active());
    2138      415568 :               libmesh_assert(!c.ancestor());
    2139             :             }
    2140             :         }
    2141             :     }
    2142             : #endif // DEBUG
    2143             : 
    2144   138187255 :   return is_ancestor;
    2145             : 
    2146             : #else
    2147             :   return false;
    2148             : #endif
    2149             : }
    2150             : 
    2151             : 
    2152             : 
    2153             : #ifdef LIBMESH_ENABLE_AMR
    2154             : 
    2155      144494 : void Elem::add_child (Elem * elem)
    2156             : {
    2157      144494 :   const unsigned int nc = this->n_children();
    2158             : 
    2159      144494 :   if (!_children)
    2160             :     {
    2161       37737 :       _children = std::make_unique<Elem *[]>(nc);
    2162             : 
    2163      180795 :       for (unsigned int c = 0; c != nc; c++)
    2164        5724 :         this->set_child(c, nullptr);
    2165             :     }
    2166             : 
    2167      360525 :   for (unsigned int c = 0; c != nc; c++)
    2168             :     {
    2169      374815 :       if (this->_children[c] == nullptr || this->_children[c] == remote_elem)
    2170             :         {
    2171        5724 :           libmesh_assert_equal_to (this, elem->parent());
    2172        5724 :           this->set_child(c, elem);
    2173      144494 :           return;
    2174             :         }
    2175             :     }
    2176             : 
    2177           0 :   libmesh_error_msg("Error: Tried to add a child to an element with full children array");
    2178             : }
    2179             : 
    2180             : 
    2181             : 
    2182    50245814 : void Elem::add_child (Elem * elem, unsigned int c)
    2183             : {
    2184       49532 :   if (!this->has_children())
    2185             :     {
    2186     6189715 :       const unsigned int nc = this->n_children();
    2187     6203381 :       _children = std::make_unique<Elem *[]>(nc);
    2188             : 
    2189    31152681 :       for (unsigned int i = 0; i != nc; i++)
    2190       49180 :         this->set_child(i, nullptr);
    2191             :     }
    2192             : 
    2193       49532 :   libmesh_assert (this->_children[c] == nullptr || this->child_ptr(c) == remote_elem);
    2194       49532 :   libmesh_assert (elem == remote_elem || this == elem->parent());
    2195             : 
    2196       49532 :   this->set_child(c, elem);
    2197    50245814 : }
    2198             : 
    2199             : 
    2200             : 
    2201      231063 : void Elem::replace_child (Elem * elem, unsigned int c)
    2202             : {
    2203       24104 :   libmesh_assert(this->has_children());
    2204             : 
    2205       24104 :   libmesh_assert(this->child_ptr(c));
    2206             : 
    2207       24104 :   this->set_child(c, elem);
    2208      231063 : }
    2209             : 
    2210             : 
    2211             : 
    2212        9501 : void Elem::family_tree (std::vector<const Elem *> & family,
    2213             :                           bool reset) const
    2214             : {
    2215        9501 :   ElemInternal::family_tree(this, family, reset);
    2216        9501 : }
    2217             : 
    2218             : 
    2219             : 
    2220           0 : void Elem::family_tree (std::vector<Elem *> & family,
    2221             :                         bool reset)
    2222             : {
    2223           0 :   ElemInternal::family_tree(this, family, reset);
    2224           0 : }
    2225             : 
    2226             : 
    2227             : 
    2228       46589 : void Elem::total_family_tree (std::vector<const Elem *> & family,
    2229             :                               bool reset) const
    2230             : {
    2231       46589 :   ElemInternal::total_family_tree(this, family, reset);
    2232       46589 : }
    2233             : 
    2234             : 
    2235             : 
    2236    32349676 : void Elem::total_family_tree (std::vector<Elem *> & family,
    2237             :                               bool reset)
    2238             : {
    2239    32349676 :   ElemInternal::total_family_tree(this, family, reset);
    2240    32349676 : }
    2241             : 
    2242             : 
    2243             : 
    2244     1032935 : void Elem::active_family_tree (std::vector<const Elem *> & active_family,
    2245             :                                bool reset) const
    2246             : {
    2247     1032935 :   ElemInternal::active_family_tree(this, active_family, reset);
    2248     1032935 : }
    2249             : 
    2250             : 
    2251             : 
    2252           0 : void Elem::active_family_tree (std::vector<Elem *> & active_family,
    2253             :                                bool reset)
    2254             : {
    2255           0 :   ElemInternal::active_family_tree(this, active_family, reset);
    2256           0 : }
    2257             : 
    2258             : 
    2259             : 
    2260           0 : void Elem::family_tree_by_side (std::vector<const Elem *> & family,
    2261             :                                 unsigned int side,
    2262             :                                 bool reset) const
    2263             : {
    2264           0 :   ElemInternal::family_tree_by_side(this, family, side, reset);
    2265           0 : }
    2266             : 
    2267             : 
    2268             : 
    2269           0 : void Elem:: family_tree_by_side (std::vector<Elem *> & family,
    2270             :                                  unsigned int side,
    2271             :                                  bool reset)
    2272             : {
    2273           0 :   ElemInternal::family_tree_by_side(this, family, side, reset);
    2274           0 : }
    2275             : 
    2276             : 
    2277             : 
    2278           0 : void Elem::total_family_tree_by_side (std::vector<const Elem *> & family,
    2279             :                                       unsigned int side,
    2280             :                                       bool reset) const
    2281             : {
    2282           0 :   ElemInternal::total_family_tree_by_side(this, family, side, reset);
    2283           0 : }
    2284             : 
    2285             : 
    2286             : 
    2287   230861545 : void Elem::total_family_tree_by_side (std::vector<Elem *> & family,
    2288             :                                       unsigned int side,
    2289             :                                       bool reset)
    2290             : {
    2291   230861545 :   ElemInternal::total_family_tree_by_side(this, family, side, reset);
    2292   230861545 : }
    2293             : 
    2294             : 
    2295             : 
    2296      591279 : void Elem::active_family_tree_by_side (std::vector<const Elem *> & family,
    2297             :                                        unsigned int side,
    2298             :                                        bool reset) const
    2299             : {
    2300      591279 :   ElemInternal::active_family_tree_by_side(this, family, side, reset);
    2301      591279 : }
    2302             : 
    2303             : 
    2304             : 
    2305           0 : void Elem::active_family_tree_by_side (std::vector<Elem *> & family,
    2306             :                                        unsigned int side,
    2307             :                                        bool reset)
    2308             : {
    2309           0 :   ElemInternal::active_family_tree_by_side(this, family, side, reset);
    2310           0 : }
    2311             : 
    2312             : 
    2313             : 
    2314           0 : void Elem::family_tree_by_neighbor (std::vector<const Elem *> & family,
    2315             :                                     const Elem * neighbor,
    2316             :                                     bool reset) const
    2317             : {
    2318           0 :   ElemInternal::family_tree_by_neighbor(this, family, neighbor, reset);
    2319           0 : }
    2320             : 
    2321             : 
    2322             : 
    2323           0 : void Elem::family_tree_by_neighbor (std::vector<Elem *> & family,
    2324             :                                     Elem * neighbor,
    2325             :                                     bool reset)
    2326             : {
    2327           0 :   ElemInternal::family_tree_by_neighbor(this, family, neighbor, reset);
    2328           0 : }
    2329             : 
    2330             : 
    2331             : 
    2332           0 : void Elem::total_family_tree_by_neighbor (std::vector<const Elem *> & family,
    2333             :                                           const Elem * neighbor,
    2334             :                                           bool reset) const
    2335             : {
    2336           0 :   ElemInternal::total_family_tree_by_neighbor(this, family, neighbor, reset);
    2337           0 : }
    2338             : 
    2339             : 
    2340             : 
    2341    70601070 : void Elem::total_family_tree_by_neighbor (std::vector<Elem *> & family,
    2342             :                                           Elem * neighbor,
    2343             :                                           bool reset)
    2344             : {
    2345    70601070 :   ElemInternal::total_family_tree_by_neighbor(this, family, neighbor, reset);
    2346    70601070 : }
    2347             : 
    2348             : 
    2349             : 
    2350           0 : void Elem::family_tree_by_subneighbor (std::vector<const Elem *> & family,
    2351             :                                        const Elem * neighbor,
    2352             :                                        const Elem * subneighbor,
    2353             :                                        bool reset) const
    2354             : {
    2355           0 :   ElemInternal::family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
    2356           0 : }
    2357             : 
    2358             : 
    2359             : 
    2360           0 : void Elem::family_tree_by_subneighbor (std::vector<Elem *> & family,
    2361             :                                        Elem * neighbor,
    2362             :                                        Elem * subneighbor,
    2363             :                                        bool reset)
    2364             : {
    2365           0 :   ElemInternal::family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
    2366           0 : }
    2367             : 
    2368             : 
    2369             : 
    2370           0 : void Elem::total_family_tree_by_subneighbor (std::vector<const Elem *> & family,
    2371             :                                              const Elem * neighbor,
    2372             :                                              const Elem * subneighbor,
    2373             :                                              bool reset) const
    2374             : {
    2375           0 :   ElemInternal::total_family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
    2376           0 : }
    2377             : 
    2378             : 
    2379             : 
    2380        2874 : void Elem::total_family_tree_by_subneighbor (std::vector<Elem *> & family,
    2381             :                                              Elem * neighbor,
    2382             :                                              Elem * subneighbor,
    2383             :                                              bool reset)
    2384             : {
    2385        2874 :   ElemInternal::total_family_tree_by_subneighbor(this, family, neighbor, subneighbor, reset);
    2386        2874 : }
    2387             : 
    2388             : 
    2389             : 
    2390    42396543 : void Elem::active_family_tree_by_neighbor (std::vector<const Elem *> & family,
    2391             :                                            const Elem * neighbor,
    2392             :                                            bool reset) const
    2393             : {
    2394    42396543 :   ElemInternal::active_family_tree_by_neighbor(this, family, neighbor, reset);
    2395    42396543 : }
    2396             : 
    2397             : 
    2398             : 
    2399        2736 : void Elem::active_family_tree_by_neighbor (std::vector<Elem *> & family,
    2400             :                                            Elem * neighbor,
    2401             :                                            bool reset)
    2402             : {
    2403        2736 :   ElemInternal::active_family_tree_by_neighbor(this, family, neighbor, reset);
    2404        2736 : }
    2405             : 
    2406             : 
    2407             : 
    2408       26334 : void Elem::active_family_tree_by_topological_neighbor (std::vector<const Elem *> & family,
    2409             :                                                        const Elem * neighbor,
    2410             :                                                        const MeshBase & mesh,
    2411             :                                                        const PointLocatorBase & point_locator,
    2412             :                                                        const PeriodicBoundaries * pb,
    2413             :                                                        bool reset) const
    2414             : {
    2415       26334 :   ElemInternal::active_family_tree_by_topological_neighbor(this, family, neighbor,
    2416             :                                                            mesh, point_locator, pb,
    2417             :                                                            reset);
    2418       26334 : }
    2419             : 
    2420             : 
    2421             : 
    2422           0 : void Elem::active_family_tree_by_topological_neighbor (std::vector<Elem *> & family,
    2423             :                                                        Elem * neighbor,
    2424             :                                                        const MeshBase & mesh,
    2425             :                                                        const PointLocatorBase & point_locator,
    2426             :                                                        const PeriodicBoundaries * pb,
    2427             :                                                        bool reset)
    2428             : {
    2429           0 :   ElemInternal::active_family_tree_by_topological_neighbor(this, family, neighbor,
    2430             :                                                            mesh, point_locator, pb,
    2431             :                                                            reset);
    2432           0 : }
    2433             : 
    2434             : 
    2435    27663040 : bool Elem::is_child_on_edge(const unsigned int c,
    2436             :                             const unsigned int e) const
    2437             : {
    2438    16936768 :   libmesh_assert_less (c, this->n_children());
    2439    16936768 :   libmesh_assert_less (e, this->n_edges());
    2440             : 
    2441    43551954 :   std::unique_ptr<const Elem> my_edge = this->build_edge_ptr(e);
    2442    26615186 :   std::unique_ptr<const Elem> child_edge = this->child_ptr(c)->build_edge_ptr(e);
    2443             : 
    2444             :   // We're assuming that an overlapping child edge has the same
    2445             :   // number and orientation as its parent
    2446    43251682 :   return (child_edge->node_id(0) == my_edge->node_id(0) ||
    2447    58092742 :           child_edge->node_id(1) == my_edge->node_id(1));
    2448     9678418 : }
    2449             : 
    2450             : 
    2451             : 
    2452    15961514 : unsigned int Elem::min_p_level_by_neighbor(const Elem * neighbor_in,
    2453             :                                            unsigned int current_min) const
    2454             : {
    2455     1450032 :   libmesh_assert(!this->subactive());
    2456     1450032 :   libmesh_assert(neighbor_in->active());
    2457             : 
    2458             :   // If we're an active element this is simple
    2459     1450032 :   if (this->active())
    2460    17193708 :     return std::min(current_min, this->p_level());
    2461             : 
    2462       21019 :   libmesh_assert(has_neighbor(neighbor_in));
    2463             : 
    2464             :   // The p_level() of an ancestor element is already the minimum
    2465             :   // p_level() of its children - so if that's high enough, we don't
    2466             :   // need to examine any children.
    2467      218366 :   if (current_min <= this->p_level())
    2468       21019 :     return current_min;
    2469             : 
    2470           0 :   unsigned int min_p_level = current_min;
    2471             : 
    2472           0 :   for (auto & c : this->child_ref_range())
    2473           0 :     if (&c != remote_elem && c.has_neighbor(neighbor_in))
    2474             :       min_p_level =
    2475           0 :         c.min_p_level_by_neighbor(neighbor_in, min_p_level);
    2476             : 
    2477           0 :   return min_p_level;
    2478             : }
    2479             : 
    2480             : 
    2481     2145470 : unsigned int Elem::min_new_p_level_by_neighbor(const Elem * neighbor_in,
    2482             :                                                unsigned int current_min) const
    2483             : {
    2484       95716 :   libmesh_assert(!this->subactive());
    2485       95716 :   libmesh_assert(neighbor_in->active());
    2486             : 
    2487             :   // If we're an active element this is simple
    2488       95716 :   if (this->active())
    2489             :     {
    2490     1428913 :       unsigned int new_p_level = this->p_level();
    2491     1493213 :       if (this->p_refinement_flag() == Elem::REFINE)
    2492          16 :         new_p_level += 1;
    2493     1428913 :       if (this->p_refinement_flag() == Elem::COARSEN)
    2494             :         {
    2495           4 :           libmesh_assert_greater (new_p_level, 0);
    2496         218 :           new_p_level -= 1;
    2497             :         }
    2498     1428913 :       return std::min(current_min, new_p_level);
    2499             :     }
    2500             : 
    2501       31416 :   libmesh_assert(has_neighbor(neighbor_in));
    2502             : 
    2503      716557 :   unsigned int min_p_level = current_min;
    2504             : 
    2505     3600199 :   for (auto & c : this->child_ref_range())
    2506     3012242 :     if (&c != remote_elem && c.has_neighbor(neighbor_in))
    2507             :       min_p_level =
    2508     1428913 :         c.min_new_p_level_by_neighbor(neighbor_in, min_p_level);
    2509             : 
    2510      716557 :   return min_p_level;
    2511             : }
    2512             : 
    2513             : 
    2514             : 
    2515   192875749 : unsigned int Elem::as_parent_node (unsigned int child,
    2516             :                                    unsigned int child_node) const
    2517             : {
    2518   192875749 :   const unsigned int nc = this->n_children();
    2519     8507910 :   libmesh_assert_less(child, nc);
    2520             : 
    2521             :   // Cached return values, indexed first by embedding_matrix version,
    2522             :   // then by child number, then by child node number.
    2523             :   std::vector<std::vector<std::vector<signed char>>> &
    2524   192875749 :     cached_parent_indices = this->_get_parent_indices_cache();
    2525             : 
    2526   192875749 :   unsigned int em_vers = this->embedding_matrix_version();
    2527             : 
    2528             :   // We may be updating the cache on one thread, and while that
    2529             :   // happens we can't safely access the cache from other threads.
    2530    17015820 :   Threads::spin_mutex::scoped_lock lock(parent_indices_mutex);
    2531             : 
    2532   201383659 :   if (em_vers >= cached_parent_indices.size())
    2533        5898 :     cached_parent_indices.resize(em_vers+1);
    2534             : 
    2535   209891569 :   if (child >= cached_parent_indices[em_vers].size())
    2536             :     {
    2537        5902 :       const signed char nn = cast_int<signed char>(this->n_nodes());
    2538             : 
    2539        6118 :       cached_parent_indices[em_vers].resize(nc);
    2540             : 
    2541       35363 :       for (unsigned int c = 0; c != nc; ++c)
    2542             :         {
    2543       29461 :           const unsigned int ncn = this->n_nodes_in_child(c);
    2544       31569 :           cached_parent_indices[em_vers][c].resize(ncn);
    2545      300082 :           for (unsigned int cn = 0; cn != ncn; ++cn)
    2546             :             {
    2547     1288292 :               for (signed char n = 0; n != nn; ++n)
    2548             :                 {
    2549             :                   const Real em_val = this->embedding_matrix
    2550     1288292 :                     (c, cn, n);
    2551     1288292 :                   if (em_val == 1)
    2552             :                     {
    2553       93530 :                       cached_parent_indices[em_vers][c][cn] = n;
    2554       87502 :                       break;
    2555             :                     }
    2556             : 
    2557     1200790 :                   if (em_val != 0)
    2558             :                     {
    2559      195727 :                       cached_parent_indices[em_vers][c][cn] =
    2560             :                         -1;
    2561      183119 :                       break;
    2562             :                     }
    2563             : 
    2564             :                   // We should never see an all-zero embedding matrix
    2565             :                   // row
    2566       34690 :                   libmesh_assert_not_equal_to (n+1, nn);
    2567             :                 }
    2568             :             }
    2569             :         }
    2570             :     }
    2571             : 
    2572             :   const signed char cache_val =
    2573   209891569 :     cached_parent_indices[em_vers][child][child_node];
    2574   192875749 :   if (cache_val == -1)
    2575     5359552 :     return libMesh::invalid_uint;
    2576             : 
    2577    74871487 :   return cached_parent_indices[em_vers][child][child_node];
    2578             : }
    2579             : 
    2580             : 
    2581             : 
    2582             : const std::vector<std::pair<unsigned char, unsigned char>> &
    2583   111235358 : Elem::parent_bracketing_nodes(unsigned int child,
    2584             :                               unsigned int child_node) const
    2585             : {
    2586             :   // Indexed first by embedding matrix type, then by child id, then by
    2587             :   // child node, then by bracketing pair
    2588             :   std::vector<std::vector<std::vector<std::vector<std::pair<unsigned char, unsigned char>>>>> &
    2589   111235358 :     cached_bracketing_nodes = this->_get_bracketing_node_cache();
    2590             : 
    2591   111235358 :   const unsigned int em_vers = this->embedding_matrix_version();
    2592             : 
    2593             :   // We may be updating the cache on one thread, and while that
    2594             :   // happens we can't safely access the cache from other threads.
    2595    11625076 :   Threads::spin_mutex::scoped_lock lock(parent_bracketing_nodes_mutex);
    2596             : 
    2597   117047896 :   if (cached_bracketing_nodes.size() <= em_vers)
    2598        5269 :     cached_bracketing_nodes.resize(em_vers+1);
    2599             : 
    2600   111235358 :   const unsigned int nc = this->n_children();
    2601             : 
    2602             :   // If we haven't cached the bracketing nodes corresponding to this
    2603             :   // embedding matrix yet, let's do so now.
    2604   122860434 :   if (cached_bracketing_nodes[em_vers].size() < nc)
    2605             :     {
    2606             :       // If we're a second-order element but we're not a full-order
    2607             :       // element, then some of our bracketing nodes may not exist
    2608             :       // except on the equivalent full-order element.  Let's build an
    2609             :       // equivalent full-order element and make a copy of its cache to
    2610             :       // use.
    2611        8515 :       if (this->default_order() != FIRST &&
    2612        3242 :           second_order_equivalent_type(this->type(), /*full_ordered=*/ true) != this->type())
    2613             :         {
    2614             :           // Check that we really are the non-full-order type
    2615           8 :           libmesh_assert_equal_to
    2616             :             (second_order_equivalent_type (this->type(), false),
    2617             :              this->type());
    2618             : 
    2619             :           // Build the full-order type
    2620             :           ElemType full_type =
    2621         165 :             second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
    2622         173 :           std::unique_ptr<Elem> full_elem = Elem::build(full_type);
    2623             : 
    2624             :           // This won't work for elements with multiple
    2625             :           // embedding_matrix versions, but every such element is full
    2626             :           // order anyways.
    2627           8 :           libmesh_assert_equal_to(em_vers, 0);
    2628             : 
    2629             :           // Make sure its cache has been built.  We temporarily
    2630             :           // release our mutex lock so that the inner call can
    2631             :           // re-acquire it.
    2632           8 :           lock.release();
    2633         165 :           full_elem->parent_bracketing_nodes(0,0);
    2634             : 
    2635             :           // And then we need to lock again, so that if someone *else*
    2636             :           // grabbed our lock before we did we don't risk accessing
    2637             :           // cached_bracketing_nodes while they're working on it.
    2638             :           // Threading is hard.
    2639           8 :           lock.acquire(parent_bracketing_nodes_mutex);
    2640             : 
    2641             :           // Copy its cache
    2642             :           cached_bracketing_nodes =
    2643         165 :             full_elem->_get_bracketing_node_cache();
    2644             : 
    2645             :           // Now we don't need to build the cache ourselves.
    2646         181 :           return cached_bracketing_nodes[em_vers][child][child_node];
    2647         149 :         }
    2648             : 
    2649        5300 :       cached_bracketing_nodes[em_vers].resize(nc);
    2650             : 
    2651        5108 :       const unsigned int nn = this->n_nodes();
    2652             : 
    2653             :       // We have to examine each child
    2654       29097 :       for (unsigned int c = 0; c != nc; ++c)
    2655             :         {
    2656       23989 :           const unsigned int ncn = this->n_nodes_in_child(c);
    2657             : 
    2658       25777 :           cached_bracketing_nodes[em_vers][c].resize(ncn);
    2659             : 
    2660             :           // We have to examine each node in that child
    2661      208186 :           for (unsigned int n = 0; n != ncn; ++n)
    2662             :             {
    2663             :               // If this child node isn't a vertex or an infinite
    2664             :               // child element's mid-infinite-edge node, then we need
    2665             :               // to find bracketing nodes on the child.
    2666      184197 :               if (!this->is_vertex_on_child(c, n)
    2667             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    2668       16175 :                   && !this->is_mid_infinite_edge_node(n)
    2669             : #endif
    2670             :                   )
    2671             :                 {
    2672             :                   // Use the embedding matrix to find the child node
    2673             :                   // location in parent master element space
    2674        2572 :                   Point bracketed_pt;
    2675             : 
    2676     1041788 :                   for (unsigned int pn = 0; pn != nn; ++pn)
    2677             :                     {
    2678             :                       const Real em_val =
    2679      968286 :                         this->embedding_matrix(c,n,pn);
    2680             : 
    2681       34140 :                       libmesh_assert_not_equal_to (em_val, 1);
    2682      968286 :                       if (em_val != 0.)
    2683      356334 :                         bracketed_pt.add_scaled(this->master_point(pn), em_val);
    2684             :                     }
    2685             : 
    2686             :                   // Check each pair of nodes on the child which are
    2687             :                   // also both parent nodes
    2688     1041788 :                   for (unsigned int n1 = 0; n1 != ncn; ++n1)
    2689             :                     {
    2690      968286 :                       if (n1 == n)
    2691      610786 :                         continue;
    2692             : 
    2693             :                       unsigned int parent_n1 =
    2694      894784 :                         this->as_parent_node(c,n1);
    2695             : 
    2696      894784 :                       if (parent_n1 == libMesh::invalid_uint)
    2697      518524 :                         continue;
    2698             : 
    2699      357500 :                       Point p1 = this->master_point(parent_n1);
    2700             : 
    2701     3773206 :                       for (unsigned int n2 = n1+1; n2 < nn; ++n2)
    2702             :                         {
    2703     3503924 :                           if (n2 == n)
    2704     2808158 :                             continue;
    2705             : 
    2706             :                           unsigned int parent_n2 =
    2707     3234642 :                             this->as_parent_node(c,n2);
    2708             : 
    2709     3234642 :                           if (parent_n2 == libMesh::invalid_uint)
    2710     2450212 :                             continue;
    2711             : 
    2712      695766 :                           Point p2 = this->master_point(parent_n2);
    2713             : 
    2714       25444 :                           Point pmid = (p1 + p2)/2;
    2715             : 
    2716       25444 :                           if (pmid == bracketed_pt)
    2717             :                             {
    2718       97470 :                               cached_bracketing_nodes[em_vers][c][n].emplace_back(parent_n1, parent_n2);
    2719       88218 :                               break;
    2720             :                             }
    2721             :                           else
    2722       22360 :                             libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
    2723             :                         }
    2724             :                     }
    2725             :                 }
    2726             :               // If this child node is a parent node, we need to
    2727             :               // find bracketing nodes on the parent.
    2728             :               else
    2729             :                 {
    2730      110695 :                   unsigned int parent_node = this->as_parent_node(c,n);
    2731             : 
    2732        4202 :                   Point bracketed_pt;
    2733             : 
    2734             :                   // If we're not a parent node, use the embedding
    2735             :                   // matrix to find the child node location in parent
    2736             :                   // master element space
    2737      110695 :                   if (parent_node == libMesh::invalid_uint)
    2738             :                     {
    2739      351898 :                       for (unsigned int pn = 0; pn != nn; ++pn)
    2740             :                         {
    2741             :                           const Real em_val =
    2742      302681 :                             this->embedding_matrix(c,n,pn);
    2743             : 
    2744       11828 :                           libmesh_assert_not_equal_to (em_val, 1);
    2745      302681 :                           if (em_val != 0.)
    2746      151178 :                             bracketed_pt.add_scaled(this->master_point(pn), em_val);
    2747             :                         }
    2748             :                     }
    2749             :                   // If we're a parent node then we need no arithmetic
    2750             :                   else
    2751       61478 :                     bracketed_pt = this->master_point(parent_node);
    2752             : 
    2753     1053222 :                   for (unsigned int n1 = 0; n1 != nn; ++n1)
    2754             :                     {
    2755      942527 :                       if (n1 == parent_node)
    2756       61478 :                         continue;
    2757             : 
    2758      881049 :                       Point p1 = this->master_point(n1);
    2759             : 
    2760     4831850 :                       for (unsigned int n2 = n1+1; n2 < nn; ++n2)
    2761             :                         {
    2762     4105098 :                           if (n2 == parent_node)
    2763       10792 :                             continue;
    2764             : 
    2765     3813036 :                           Point pmid = (p1 + this->master_point(n2))/2;
    2766             : 
    2767      140116 :                           if (pmid == bracketed_pt)
    2768             :                             {
    2769      171241 :                               cached_bracketing_nodes[em_vers][c][n].emplace_back(n1, n2);
    2770        5648 :                               break;
    2771             :                             }
    2772             :                           else
    2773      134468 :                             libmesh_assert(!pmid.absolute_fuzzy_equals(bracketed_pt));
    2774             :                         }
    2775             :                     }
    2776             :                 }
    2777             :             }
    2778             :         }
    2779             :     }
    2780             : 
    2781   128672783 :   return cached_bracketing_nodes[em_vers][child][child_node];
    2782             : }
    2783             : 
    2784             : 
    2785             : const std::vector<std::pair<dof_id_type, dof_id_type>>
    2786   120818012 : Elem::bracketing_nodes(unsigned int child,
    2787             :                        unsigned int child_node) const
    2788             : {
    2789     6234618 :   std::vector<std::pair<dof_id_type, dof_id_type>> returnval;
    2790             : 
    2791             :   const std::vector<std::pair<unsigned char, unsigned char>> & pbc =
    2792   120818012 :     this->parent_bracketing_nodes(child,child_node);
    2793             : 
    2794   254626622 :   for (const auto & pb : pbc)
    2795             :     {
    2796   133808610 :       const unsigned short n_n = this->n_nodes();
    2797   133808610 :       if (pb.first < n_n && pb.second < n_n)
    2798   147273666 :         returnval.emplace_back(this->node_id(pb.first), this->node_id(pb.second));
    2799             :       else
    2800             :         {
    2801             :           // We must be on a non-full-order higher order element...
    2802       33008 :           libmesh_assert_not_equal_to(this->default_order(), FIRST);
    2803       33008 :           libmesh_assert_not_equal_to
    2804             :             (second_order_equivalent_type (this->type(), true),
    2805             :              this->type());
    2806       33008 :           libmesh_assert_equal_to
    2807             :             (second_order_equivalent_type (this->type(), false),
    2808             :              this->type());
    2809             : 
    2810             :           // And that's a shame, because this is a nasty search:
    2811             : 
    2812             :           // Build the full-order type
    2813             :           ElemType full_type =
    2814      908404 :             second_order_equivalent_type(this->type(), /*full_ordered=*/ true);
    2815      941412 :           std::unique_ptr<Elem> full_elem = Elem::build(full_type);
    2816             : 
    2817      908404 :           dof_id_type pt1 = DofObject::invalid_id;
    2818      908404 :           dof_id_type pt2 = DofObject::invalid_id;
    2819             : 
    2820             :           // Find the bracketing nodes by figuring out what
    2821             :           // already-created children will have them.
    2822             : 
    2823             :           // This only doesn't break horribly because we add children
    2824             :           // and nodes in straightforward + hierarchical orders...
    2825     4993928 :           for (unsigned int c=0; c <= child; ++c)
    2826             :             {
    2827      147320 :               libmesh_assert(this->child_ptr(c));
    2828     4085524 :               if (this->child_ptr(c) == remote_elem)
    2829           0 :                 continue;
    2830             : 
    2831    73004408 :               for (auto n : make_range(this->n_nodes_in_child(c)))
    2832             :                 {
    2833    66036404 :                   if (c == child && n == child_node)
    2834       33008 :                     break;
    2835             : 
    2836    67475880 :                   if (pb.first == full_elem->as_parent_node(c,n))
    2837             :                     {
    2838             :                       // We should be consistent
    2839       99160 :                       if (pt1 != DofObject::invalid_id)
    2840       66330 :                         libmesh_assert_equal_to(pt1, this->child_ptr(c)->node_id(n));
    2841             : 
    2842     2846778 :                       pt1 = this->child_ptr(c)->node_id(n);
    2843             :                     }
    2844             : 
    2845    67475880 :                   if (pb.second == full_elem->as_parent_node(c,n))
    2846             :                     {
    2847             :                       // We should be consistent
    2848       72088 :                       if (pt2 != DofObject::invalid_id)
    2849       40682 :                         libmesh_assert_equal_to(pt2, this->child_ptr(c)->node_id(n));
    2850             : 
    2851     2068296 :                       pt2 = this->child_ptr(c)->node_id(n);
    2852             :                     }
    2853             :                 }
    2854             :             }
    2855             : 
    2856             :           // We should *usually* find all bracketing nodes by the time
    2857             :           // we query them (again, because of the child & node add
    2858             :           // order)
    2859             :           //
    2860             :           // The exception is if we're a HEX20, in which case we will
    2861             :           // find pairs of vertex nodes and edge nodes bracketing the
    2862             :           // new central node but we *won't* find the pairs of face
    2863             :           // nodes which we would have had on a HEX27.  In that case
    2864             :           // we'll still have enough bracketing nodes for a
    2865             :           // topological lookup, but we won't be able to make the
    2866             :           // following assertions.
    2867      908404 :           if (this->type() != HEX20)
    2868             :             {
    2869       15920 :               libmesh_assert_not_equal_to (pt1, DofObject::invalid_id);
    2870       15920 :               libmesh_assert_not_equal_to (pt2, DofObject::invalid_id);
    2871             :             }
    2872             : 
    2873      908404 :           if (pt1 != DofObject::invalid_id &&
    2874      903549 :               pt2 != DofObject::invalid_id)
    2875      864709 :             returnval.emplace_back(pt1, pt2);
    2876      842388 :         }
    2877             :     }
    2878             : 
    2879   120818012 :   return returnval;
    2880             : }
    2881             : #endif // #ifdef LIBMESH_ENABLE_AMR
    2882             : 
    2883             : 
    2884             : 
    2885             : 
    2886   146656638 : bool Elem::contains_point (const Point & p, Real tol) const
    2887             : {
    2888             :   // We currently allow the user to enlarge the bounding box by
    2889             :   // providing a tol > TOLERANCE (so this routine is identical to
    2890             :   // Elem::close_to_point()), but print a warning so that the
    2891             :   // user can eventually switch his code over to calling close_to_point()
    2892             :   // instead, which is intended to be used for this purpose.
    2893   146656638 :   if (tol > TOLERANCE)
    2894             :     {
    2895           0 :       libmesh_do_once(libMesh::err
    2896             :                       << "WARNING: Resizing bounding box to match user-specified tolerance!\n"
    2897             :                       << "In the future, calls to Elem::contains_point() with tol > TOLERANCE\n"
    2898             :                       << "will be more optimized, but should not be used\n"
    2899             :                       << "to search for points 'close to' elements!\n"
    2900             :                       << "Instead, use Elem::close_to_point() for this purpose.\n"
    2901             :                       << std::endl;);
    2902           0 :       return this->point_test(p, tol, tol);
    2903             :     }
    2904             :   else
    2905   146656638 :     return this->point_test(p, TOLERANCE, tol);
    2906             : }
    2907             : 
    2908             : 
    2909             : 
    2910             : 
    2911     6059349 : bool Elem::close_to_point (const Point & p, Real tol) const
    2912             : {
    2913             :   // This test uses the user's passed-in tolerance for the
    2914             :   // bounding box test as well, thereby allowing the routine to
    2915             :   // find points which are not only "in" the element, but also
    2916             :   // "nearby" to within some tolerance.
    2917     6059349 :   return this->point_test(p, tol, tol);
    2918             : }
    2919             : 
    2920             : 
    2921             : 
    2922             : 
    2923   152715987 : bool Elem::point_test(const Point & p, Real box_tol, Real map_tol) const
    2924             : {
    2925     7579350 :   libmesh_assert_greater (box_tol, 0.);
    2926     7579350 :   libmesh_assert_greater (map_tol, 0.);
    2927             : 
    2928             :   // This is a great optimization on first order elements, but it
    2929             :   // could return false negatives on higher orders
    2930   152715987 :   if (this->default_order() == FIRST)
    2931             :     {
    2932             :       // Check to make sure the element *could* contain this point, so we
    2933             :       // can avoid an expensive inverse_map call if it doesn't.
    2934             :       bool
    2935             : #if LIBMESH_DIM > 2
    2936     3293746 :         point_above_min_z = false,
    2937     3293746 :         point_below_max_z = false,
    2938             : #endif
    2939             : #if LIBMESH_DIM > 1
    2940     3293746 :         point_above_min_y = false,
    2941     3293746 :         point_below_max_y = false,
    2942             : #endif
    2943     3293746 :         point_above_min_x = false,
    2944     3293746 :         point_below_max_x = false;
    2945             : 
    2946             :       // For relative bounding box checks in physical space
    2947    62447328 :       const Real my_hmax = this->hmax();
    2948             : 
    2949   494789637 :       for (auto & n : this->node_ref_range())
    2950             :         {
    2951   432342309 :           point_above_min_x = point_above_min_x || (n(0) - my_hmax*box_tol <= p(0));
    2952   432342309 :           point_below_max_x = point_below_max_x || (n(0) + my_hmax*box_tol >= p(0));
    2953             : #if LIBMESH_DIM > 1
    2954   432342309 :           point_above_min_y = point_above_min_y || (n(1) - my_hmax*box_tol <= p(1));
    2955   432342309 :           point_below_max_y = point_below_max_y || (n(1) + my_hmax*box_tol >= p(1));
    2956             : #endif
    2957             : #if LIBMESH_DIM > 2
    2958   432342309 :           point_above_min_z = point_above_min_z || (n(2) - my_hmax*box_tol <= p(2));
    2959   432342309 :           point_below_max_z = point_below_max_z || (n(2) + my_hmax*box_tol >= p(2));
    2960             : #endif
    2961             :         }
    2962             : 
    2963    62447328 :       if (
    2964             : #if LIBMESH_DIM > 2
    2965     3293746 :           !point_above_min_z ||
    2966     3176240 :           !point_below_max_z ||
    2967             : #endif
    2968             : #if LIBMESH_DIM > 1
    2969    40278562 :           !point_above_min_y ||
    2970     2095221 :           !point_below_max_y ||
    2971             : #endif
    2972    18053619 :           !point_above_min_x ||
    2973      885412 :           !point_below_max_x)
    2974     2565832 :         return false;
    2975             :     }
    2976             : 
    2977             :   // To be on the safe side, we converge the inverse_map() iteration
    2978             :   // to a slightly tighter tolerance than that requested by the
    2979             :   // user...
    2980   103738658 :   const Point mapped_point = FEMap::inverse_map(this->dim(),
    2981             :                                                 this,
    2982             :                                                 p,
    2983             :                                                 0.1*map_tol, // <- this is |dx| tolerance, the Newton residual should be ~ |dx|^2
    2984             :                                                 /*secure=*/ false,
    2985     9928898 :                                                 /*extra_checks=*/ false);
    2986             : 
    2987             :   // Check that the refspace point maps back to p!  This is only necessary
    2988             :   // for 1D and 2D elements, 3D elements always live in 3D.
    2989             :   //
    2990             :   // TODO: The contains_point() function could most likely be implemented
    2991             :   // more efficiently in the element sub-classes themselves, at least for
    2992             :   // the linear element types.
    2993    98725140 :   if (this->dim() < 3)
    2994             :     {
    2995    30397000 :       Point xyz = FEMap::map(this->dim(), this, mapped_point);
    2996             : 
    2997             :       // Compute the distance between the original point and the re-mapped point.
    2998             :       // They should be in the same place.
    2999    28098632 :       Real dist = (xyz - p).norm();
    3000             : 
    3001             : 
    3002             :       // If dist is larger than some fraction of the tolerance, then return false.
    3003             :       // This can happen when e.g. a 2D element is living in 3D, and
    3004             :       // FEMap::inverse_map() maps p onto the projection of the element,
    3005             :       // effectively "tricking" on_reference_element().
    3006    30397000 :       if (dist > this->hmax() * map_tol)
    3007        8440 :         return false;
    3008             :     }
    3009             : 
    3010    98716700 :   return this->on_reference_element(mapped_point, map_tol);
    3011             : }
    3012             : 
    3013             : 
    3014             : 
    3015             : 
    3016       78600 : bool Elem::has_invertible_map(Real /*tol*/) const
    3017             : {
    3018       85150 :   QNodal qnodal {this->dim()};
    3019       91700 :   FEMap fe_map;
    3020        6550 :   auto & jac = fe_map.get_jacobian();
    3021             : 
    3022             :   // We have a separate check for is_singular_node() below, so in this
    3023             :   // case its "OK" to do nodal quadrature on pyramids.
    3024       78600 :   qnodal.allow_nodal_pyramid_quadrature = true;
    3025       78600 :   qnodal.init(*this);
    3026        6550 :   auto & qp = qnodal.get_points();
    3027        6550 :   libmesh_assert_equal_to(qp.size(), this->n_nodes());
    3028             : 
    3029       85150 :   std::vector<Point> one_point(1);
    3030       85150 :   std::vector<Real> one_weight(1,1);
    3031     1086900 :   for (auto i : index_range(qp))
    3032             :     {
    3033     1008300 :       if (this->is_singular_node(i))
    3034        8448 :         continue;
    3035             : 
    3036      999084 :       one_point[0] = qp[i];
    3037             : 
    3038      999084 :       fe_map.init_reference_to_physical_map(this->dim(), one_point, this);
    3039      999084 :       fe_map.compute_map(this->dim(), one_weight, this, false);
    3040             : 
    3041      999084 :       if (jac[0] <= 0)
    3042           0 :         return false;
    3043             :     }
    3044             : 
    3045       13100 :   return true;
    3046       65500 : }
    3047             : 
    3048             : 
    3049             : 
    3050           0 : void Elem::print_info (std::ostream & os) const
    3051             : {
    3052           0 :   os << this->get_info()
    3053           0 :      << std::endl;
    3054           0 : }
    3055             : 
    3056             : 
    3057             : 
    3058           0 : std::string Elem::get_info () const
    3059             : {
    3060           0 :   std::ostringstream oss;
    3061             : 
    3062             :   oss << "  Elem Information"                                      << '\n'
    3063           0 :       << "   id()=";
    3064             : 
    3065           0 :   if (this->valid_id())
    3066           0 :     oss << this->id();
    3067             :   else
    3068           0 :     oss << "invalid";
    3069             : 
    3070             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
    3071           0 :   oss << ", unique_id()=";
    3072           0 :   if (this->valid_unique_id())
    3073           0 :     oss << this->unique_id();
    3074             :   else
    3075           0 :     oss << "invalid";
    3076             : #endif
    3077             : 
    3078           0 :   oss << ", subdomain_id()=" << this->subdomain_id();
    3079           0 :   oss << ", processor_id()=" << this->processor_id()               << '\n';
    3080             : 
    3081           0 :   oss << "   type()="    << Utility::enum_to_string(this->type())  << '\n'
    3082           0 :       << "   dim()="     << this->dim()                            << '\n'
    3083           0 :       << "   n_nodes()=" << this->n_nodes()                        << '\n';
    3084             : 
    3085           0 :   oss << "   mapping=" << Utility::enum_to_string(this->mapping_type()) << '\n';
    3086             : 
    3087           0 :   for (auto n : this->node_index_range())
    3088             :     {
    3089           0 :       oss << "    " << n << this->node_ref(n);
    3090           0 :       if (this->mapping_type() == RATIONAL_BERNSTEIN_MAP)
    3091             :         {
    3092           0 :           const unsigned char datum_index = this->mapping_data();
    3093           0 :           oss << "    weight=" <<
    3094           0 :             this->node_ref(n).get_extra_datum<Real>(datum_index) << '\n';
    3095             :         }
    3096             :     }
    3097             : 
    3098           0 :   oss << "   n_sides()=" << this->n_sides()                        << '\n';
    3099             : 
    3100           0 :   for (auto s : this->side_index_range())
    3101             :     {
    3102           0 :       oss << "    neighbor(" << s << ")=";
    3103           0 :       if (this->neighbor_ptr(s))
    3104           0 :         oss << this->neighbor_ptr(s)->id() << '\n';
    3105             :       else
    3106           0 :         oss << "nullptr\n";
    3107             :     }
    3108             : 
    3109           0 :   if (!this->infinite())
    3110             :     {
    3111           0 :     oss << "   hmin()=" << this->hmin()
    3112           0 :         << ", hmax()=" << this->hmax()                             << '\n'
    3113           0 :         << "   volume()=" << this->volume()                        << '\n';
    3114             :     }
    3115           0 :   oss << "   active()=" << this->active()
    3116           0 :     << ", ancestor()=" << this->ancestor()
    3117           0 :     << ", subactive()=" << this->subactive()
    3118           0 :     << ", has_children()=" << this->has_children()               << '\n'
    3119           0 :     << "   parent()=";
    3120           0 :   if (this->parent())
    3121           0 :     oss << this->parent()->id() << '\n';
    3122             :   else
    3123           0 :     oss << "nullptr\n";
    3124           0 :   oss << "   level()=" << this->level()
    3125           0 :       << ", p_level()=" << this->p_level()                         << '\n'
    3126             : #ifdef LIBMESH_ENABLE_AMR
    3127           0 :       << "   refinement_flag()=" << Utility::enum_to_string(this->refinement_flag())        << '\n'
    3128           0 :       << "   p_refinement_flag()=" << Utility::enum_to_string(this->p_refinement_flag())    << '\n'
    3129             : #endif
    3130             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    3131           0 :       << "   infinite()=" << this->infinite()    << '\n';
    3132           0 :   if (this->infinite())
    3133           0 :     oss << "   origin()=" << this->origin()    << '\n'
    3134             : #endif
    3135             :       ;
    3136             : 
    3137           0 :   oss << "   DoFs=";
    3138           0 :   for (auto s : make_range(this->n_systems()))
    3139           0 :     for (auto v : make_range(this->n_vars(s)))
    3140           0 :       for (auto c : make_range(this->n_comp(s,v)))
    3141           0 :         oss << '(' << s << '/' << v << '/' << this->dof_number(s,v,c) << ") ";
    3142             : 
    3143             : 
    3144           0 :   return oss.str();
    3145           0 : }
    3146             : 
    3147             : 
    3148             : 
    3149           0 : void Elem::nullify_neighbors ()
    3150             : {
    3151             :   // Tell any of my neighbors about my death...
    3152             :   // Looks strange, huh?
    3153           0 :   for (auto n : this->side_index_range())
    3154             :     {
    3155           0 :       Elem * current_neighbor = this->neighbor_ptr(n);
    3156           0 :       if (current_neighbor && current_neighbor != remote_elem)
    3157             :         {
    3158             :           // Note:  it is possible that I see the neighbor
    3159             :           // (which is coarser than me)
    3160             :           // but they don't see me, so avoid that case.
    3161           0 :           if (current_neighbor->level() == this->level())
    3162             :             {
    3163           0 :               const unsigned int w_n_a_i = current_neighbor->which_neighbor_am_i(this);
    3164           0 :               libmesh_assert_less (w_n_a_i, current_neighbor->n_neighbors());
    3165           0 :               current_neighbor->set_neighbor(w_n_a_i, nullptr);
    3166           0 :               this->set_neighbor(n, nullptr);
    3167             :             }
    3168             :         }
    3169             :     }
    3170           0 : }
    3171             : 
    3172             : 
    3173             : 
    3174             : 
    3175           0 : unsigned int Elem::n_second_order_adjacent_vertices (const unsigned int) const
    3176             : {
    3177             :   // for linear elements, always return 0
    3178           0 :   return 0;
    3179             : }
    3180             : 
    3181             : 
    3182             : 
    3183           0 : unsigned short int Elem::second_order_adjacent_vertex (const unsigned int,
    3184             :                                                        const unsigned int) const
    3185             : {
    3186             :   // for linear elements, always return 0
    3187           0 :   return 0;
    3188             : }
    3189             : 
    3190             : 
    3191             : 
    3192             : std::pair<unsigned short int, unsigned short int>
    3193           0 : Elem::second_order_child_vertex (const unsigned int) const
    3194             : {
    3195             :   // for linear elements, always return 0
    3196           0 :   return std::pair<unsigned short int, unsigned short int>(0,0);
    3197             : }
    3198             : 
    3199             : 
    3200             : 
    3201      272662 : ElemType Elem::first_order_equivalent_type (const ElemType et)
    3202             : {
    3203       26532 :   switch (et)
    3204             :     {
    3205          28 :     case NODEELEM:
    3206          28 :       return NODEELEM;
    3207        3118 :     case EDGE2:
    3208             :     case EDGE3:
    3209             :     case EDGE4:
    3210        3118 :       return EDGE2;
    3211         480 :     case TRI3:
    3212             :     case TRI6:
    3213             :     case TRI7:
    3214         480 :       return TRI3;
    3215           0 :     case TRISHELL3:
    3216           0 :       return TRISHELL3;
    3217       22338 :     case QUAD4:
    3218             :     case QUAD8:
    3219             :     case QUAD9:
    3220       22338 :       return QUAD4;
    3221           0 :     case QUADSHELL4:
    3222             :     case QUADSHELL8:
    3223             :     case QUADSHELL9:
    3224           0 :       return QUADSHELL4;
    3225           0 :     case TET4:
    3226             :     case TET10:
    3227             :     case TET14:
    3228           0 :       return TET4;
    3229           0 :     case HEX8:
    3230             :     case HEX27:
    3231             :     case HEX20:
    3232           0 :       return HEX8;
    3233         480 :     case PRISM6:
    3234             :     case PRISM15:
    3235             :     case PRISM18:
    3236             :     case PRISM20:
    3237             :     case PRISM21:
    3238         480 :       return PRISM6;
    3239           0 :     case PYRAMID5:
    3240             :     case PYRAMID13:
    3241             :     case PYRAMID14:
    3242             :     case PYRAMID18:
    3243           0 :       return PYRAMID5;
    3244             : 
    3245             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    3246             : 
    3247          16 :     case INFEDGE2:
    3248          16 :       return INFEDGE2;
    3249          72 :     case INFQUAD4:
    3250             :     case INFQUAD6:
    3251          72 :       return INFQUAD4;
    3252           0 :     case INFHEX8:
    3253             :     case INFHEX16:
    3254             :     case INFHEX18:
    3255           0 :       return INFHEX8;
    3256           0 :     case INFPRISM6:
    3257             :     case INFPRISM12:
    3258           0 :       return INFPRISM6;
    3259             : 
    3260             : #endif
    3261             : 
    3262           0 :     default:
    3263             :       // unknown element
    3264           0 :       return INVALID_ELEM;
    3265             :     }
    3266             : }
    3267             : 
    3268             : 
    3269             : // Most of our elements have the same topology on every side, but the
    3270             : // prisms and pyramids have both triangular and quadrilateral faces, and
    3271             : // a 2D or 3D infinite element's side 0 is its finite base while the rest
    3272             : // are infinite.  The polygons and polyhedra have one side type but no
    3273             : // fixed side count, so they can answer here too while their side index
    3274             : // goes unchecked; ask an actual Elem when you have one.
    3275       99551 : ElemType Elem::side_type (const ElemType t,
    3276             :                           const unsigned int s)
    3277             : {
    3278       50961 :   libmesh_assert_less (s, type_to_n_sides_map[t]);
    3279             : 
    3280       99551 :   switch (t)
    3281             :     {
    3282          36 :     case EDGE2:
    3283             :     case EDGE3:
    3284             :     case EDGE4:
    3285          36 :       return NODEELEM;
    3286        3710 :     case TRI3:
    3287             :     case TRISHELL3:
    3288             :     case QUAD4:
    3289             :     case QUADSHELL4:
    3290             :       // A polygon's sides are all edges and a polyhedron's are all
    3291             :       // polygons, however many a given element turns out to have
    3292             :     case C0POLYGON:
    3293        3710 :       return EDGE2;
    3294        5712 :     case TRI6:
    3295             :     case TRI7:
    3296             :     case QUAD8:
    3297             :     case QUADSHELL8:
    3298             :     case QUAD9:
    3299             :     case QUADSHELL9:
    3300        5712 :       return EDGE3;
    3301        6144 :     case TET4:
    3302        6144 :       return TRI3;
    3303       10752 :     case TET10:
    3304       10752 :       return TRI6;
    3305       12288 :     case TET14:
    3306       12288 :       return TRI7;
    3307         480 :     case HEX8:
    3308         480 :       return QUAD4;
    3309         864 :     case HEX20:
    3310         864 :       return QUAD8;
    3311         960 :     case HEX27:
    3312         960 :       return QUAD9;
    3313             :       // Sides 0 and 4 of a prism are its triangles
    3314        1536 :     case PRISM6:
    3315        1536 :       return (s == 0 || s == 4) ? TRI3 : QUAD4;
    3316        2112 :     case PRISM15:
    3317        2112 :       return (s == 0 || s == 4) ? TRI6 : QUAD8;
    3318        2208 :     case PRISM18:
    3319        2208 :       return (s == 0 || s == 4) ? TRI6 : QUAD9;
    3320        4544 :     case PRISM20:
    3321             :     case PRISM21:
    3322        4544 :       return (s == 0 || s == 4) ? TRI7 : QUAD9;
    3323             :       // Side 4 of a pyramid is its quadrilateral base
    3324        4416 :     case PYRAMID5:
    3325        4416 :       return (s < 4) ? TRI3 : QUAD4;
    3326        5952 :     case PYRAMID13:
    3327        5952 :       return (s < 4) ? TRI6 : QUAD8;
    3328        6048 :     case PYRAMID14:
    3329        6048 :       return (s < 4) ? TRI6 : QUAD9;
    3330        6432 :     case PYRAMID18:
    3331        6432 :       return (s < 4) ? TRI7 : QUAD9;
    3332          72 :     case C0POLYHEDRON:
    3333          72 :       return C0POLYGON;
    3334             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    3335             :       // An InfEdge2's sides are its end nodes, like any other 1D element's
    3336           0 :     case INFEDGE2:
    3337           0 :       return NODEELEM;
    3338             :       // A 2D or 3D infinite element's side 0 is the finite base it was
    3339             :       // built from; its remaining sides run out to infinity with it
    3340           9 :     case INFQUAD4:
    3341           9 :       return (s == 0) ? EDGE2 : INFEDGE2;
    3342           9 :     case INFQUAD6:
    3343           9 :       return (s == 0) ? EDGE3 : INFEDGE2;
    3344          15 :     case INFHEX8:
    3345          15 :       return (s == 0) ? QUAD4 : INFQUAD4;
    3346          15 :     case INFHEX16:
    3347          15 :       return (s == 0) ? QUAD8 : INFQUAD6;
    3348          15 :     case INFHEX18:
    3349          15 :       return (s == 0) ? QUAD9 : INFQUAD6;
    3350          12 :     case INFPRISM6:
    3351          12 :       return (s == 0) ? TRI3 : INFQUAD4;
    3352          12 :     case INFPRISM12:
    3353          12 :       return (s == 0) ? TRI6 : INFQUAD6;
    3354             : #endif
    3355           0 :     default:
    3356           0 :       libmesh_error_msg("No side type for element type " << Utility::enum_to_string(t));
    3357             :     }
    3358             : 
    3359             :   return INVALID_ELEM;
    3360             : }
    3361             : 
    3362             : 
    3363             : 
    3364             : // This reads the same constexpr side_nodes_map tables the element
    3365             : // classes use for their virtual local_side_node(), so that code which
    3366             : // knows an element type but has no Elem to call a virtual function on --
    3367             : // building a side of an element that doesn't exist yet, or a device
    3368             : // kernel that has only the type -- can still get at the reference
    3369             : // element topology.
    3370             : //
    3371             : // The polygons and polyhedra have no such table to read, and the
    3372             : // infinite elements' maps have no caller here yet, so both error out:
    3373             : // asking for a topology we can't answer is a programming error rather
    3374             : // than something to signal with a return value.
    3375             : // A finite element's edges all have the same type, unlike its sides,
    3376             : // which differ on the prisms and pyramids, so this takes no edge index.
    3377             : // The infinite elements are the exception -- the edges of their finite
    3378             : // base are not the ones running out to infinity -- and like the rest of
    3379             : // the static topology lookups they are left to their virtual overrides.
    3380      182252 : ElemType Elem::edge_type (const ElemType t)
    3381             : {
    3382      182252 :   switch (t)
    3383             :     {
    3384             :       // 1D elements have no edges
    3385           0 :     case EDGE2:
    3386             :     case EDGE3:
    3387             :     case EDGE4:
    3388           0 :       return INVALID_ELEM;
    3389             :       // A 2D element's edges are its sides
    3390        5660 :     case TRI3:
    3391             :     case TRISHELL3:
    3392             :     case TRI6:
    3393             :     case TRI7:
    3394             :     case QUAD4:
    3395             :     case QUADSHELL4:
    3396             :     case QUAD8:
    3397             :     case QUADSHELL8:
    3398             :     case QUAD9:
    3399             :     case QUADSHELL9:
    3400             :     case C0POLYGON:
    3401        5660 :       return side_type(t, 0);
    3402             :       // A first-order 3D element's edges hold their two vertices
    3403       49872 :     case TET4:
    3404             :     case HEX8:
    3405             :     case PRISM6:
    3406             :     case PYRAMID5:
    3407             :     case C0POLYHEDRON:
    3408       49872 :       return EDGE2;
    3409             :       // and a second-order element's add the midpoint
    3410      126720 :     case TET10:
    3411             :     case TET14:
    3412             :     case HEX20:
    3413             :     case HEX27:
    3414             :     case PRISM15:
    3415             :     case PRISM18:
    3416             :     case PRISM20:
    3417             :     case PRISM21:
    3418             :     case PYRAMID13:
    3419             :     case PYRAMID14:
    3420             :     case PYRAMID18:
    3421      126720 :       return EDGE3;
    3422           0 :     default:
    3423           0 :       libmesh_error_msg("No edge type for element type " << Utility::enum_to_string(t));
    3424             :     }
    3425             : 
    3426             :   return INVALID_ELEM;
    3427             : }
    3428             : 
    3429             : 
    3430             : 
    3431      546336 : unsigned int Elem::local_side_node (const ElemType t,
    3432             :                                     const unsigned int side,
    3433             :                                     const unsigned int side_node)
    3434             : {
    3435             :   // The nodes on a side are the nodes of the side's own element type, so
    3436             :   // we compose the two lookups here rather than tabulating side node
    3437             :   // counts a second time.  That also keeps us inside the meaningful part
    3438             :   // of a row: the prisms' and pyramids' triangular sides carry fewer
    3439             :   // nodes than their quadrilateral ones, and their rows are padded out
    3440             :   // to the longer length
    3441       45528 :   libmesh_assert_less (side, type_to_n_sides_map[t]);
    3442       45528 :   libmesh_assert_less (side_node, type_to_n_nodes_map[side_type(t, side)]);
    3443             : 
    3444      546336 :   switch (t)
    3445             :     {
    3446             :       // A 1D element's sides are its end nodes
    3447          24 :     case EDGE2:
    3448             :     case EDGE3:
    3449             :     case EDGE4:
    3450          24 :       return side;
    3451             :       // The shell elements are numbered like the elements they shadow
    3452        4608 :     case TRI3:
    3453             :     case TRISHELL3:
    3454        4608 :       return Tri3::side_nodes_map[side][side_node];
    3455        3456 :     case TRI6:
    3456        3456 :       return Tri6::side_nodes_map[side][side_node];
    3457        3456 :     case TRI7:
    3458        3456 :       return Tri7::side_nodes_map[side][side_node];
    3459        3072 :     case QUAD4:
    3460             :     case QUADSHELL4:
    3461        3072 :       return Quad4::side_nodes_map[side][side_node];
    3462        4608 :     case QUAD8:
    3463             :     case QUADSHELL8:
    3464        4608 :       return Quad8::side_nodes_map[side][side_node];
    3465        4608 :     case QUAD9:
    3466             :     case QUADSHELL9:
    3467        4608 :       return Quad9::side_nodes_map[side][side_node];
    3468       55296 :     case TET4:
    3469       55296 :       return Tet4::side_nodes_map[side][side_node];
    3470      110592 :     case TET10:
    3471      110592 :       return Tet10::side_nodes_map[side][side_node];
    3472      129024 :     case TET14:
    3473      129024 :       return Tet14::side_nodes_map[side][side_node];
    3474        4608 :     case HEX8:
    3475        4608 :       return Hex8::side_nodes_map[side][side_node];
    3476        9216 :     case HEX20:
    3477        9216 :       return Hex20::side_nodes_map[side][side_node];
    3478       10368 :     case HEX27:
    3479       10368 :       return Hex27::side_nodes_map[side][side_node];
    3480        6912 :     case PRISM6:
    3481        6912 :       return Prism6::side_nodes_map[side][side_node];
    3482       13824 :     case PRISM15:
    3483       13824 :       return Prism15::side_nodes_map[side][side_node];
    3484       14976 :     case PRISM18:
    3485       14976 :       return Prism18::side_nodes_map[side][side_node];
    3486       15744 :     case PRISM20:
    3487       15744 :       return Prism20::side_nodes_map[side][side_node];
    3488       15744 :     case PRISM21:
    3489       15744 :       return Prism21::side_nodes_map[side][side_node];
    3490       18432 :     case PYRAMID5:
    3491       18432 :       return Pyramid5::side_nodes_map[side][side_node];
    3492       36864 :     case PYRAMID13:
    3493       36864 :       return Pyramid13::side_nodes_map[side][side_node];
    3494       38016 :     case PYRAMID14:
    3495       38016 :       return Pyramid14::side_nodes_map[side][side_node];
    3496       42624 :     case PYRAMID18:
    3497       42624 :       return Pyramid18::side_nodes_map[side][side_node];
    3498           0 :     default:
    3499           0 :       libmesh_error_msg("No static side node map for element type " << Utility::enum_to_string(t));
    3500             :     }
    3501             : 
    3502             :   return invalid_uint;
    3503             : }
    3504             : 
    3505             : 
    3506             : 
    3507             : // A 2D element's edges are its sides -- Face::local_edge_node() defines
    3508             : // the two to be the same thing -- so we answer those from the side map
    3509             : // and keep one copy of the 2D numbering.  1D elements have no edges to
    3510             : // ask about, and like local_side_node() above we error rather than
    3511             : // return a flag for a type we have no table for.
    3512      401280 : unsigned int Elem::local_edge_node (const ElemType t,
    3513             :                                     const unsigned int edge,
    3514             :                                     const unsigned int edge_node)
    3515             : {
    3516       33440 :   libmesh_assert_less (edge, type_to_n_edges_map[t]);
    3517       33440 :   libmesh_assert_less (edge_node, type_to_n_nodes_map[edge_type(t)]);
    3518             : 
    3519      401280 :   switch (t)
    3520             :     {
    3521       11904 :     case TRI3:
    3522             :     case TRISHELL3:
    3523             :     case TRI6:
    3524             :     case TRI7:
    3525             :     case QUAD4:
    3526             :     case QUADSHELL4:
    3527             :     case QUAD8:
    3528             :     case QUADSHELL8:
    3529             :     case QUAD9:
    3530             :     case QUADSHELL9:
    3531       11904 :       return local_side_node(t, edge, edge_node);
    3532       55296 :     case TET4:
    3533       55296 :       return Tet4::edge_nodes_map[edge][edge_node];
    3534       82944 :     case TET10:
    3535       82944 :       return Tet10::edge_nodes_map[edge][edge_node];
    3536       82944 :     case TET14:
    3537       82944 :       return Tet14::edge_nodes_map[edge][edge_node];
    3538        4608 :     case HEX8:
    3539        4608 :       return Hex8::edge_nodes_map[edge][edge_node];
    3540        6912 :     case HEX20:
    3541        6912 :       return Hex20::edge_nodes_map[edge][edge_node];
    3542        6912 :     case HEX27:
    3543        6912 :       return Hex27::edge_nodes_map[edge][edge_node];
    3544        6912 :     case PRISM6:
    3545        6912 :       return Prism6::edge_nodes_map[edge][edge_node];
    3546       10368 :     case PRISM15:
    3547       10368 :       return Prism15::edge_nodes_map[edge][edge_node];
    3548       10368 :     case PRISM18:
    3549       10368 :       return Prism18::edge_nodes_map[edge][edge_node];
    3550       10368 :     case PRISM20:
    3551       10368 :       return Prism20::edge_nodes_map[edge][edge_node];
    3552       10368 :     case PRISM21:
    3553       10368 :       return Prism21::edge_nodes_map[edge][edge_node];
    3554       18432 :     case PYRAMID5:
    3555       18432 :       return Pyramid5::edge_nodes_map[edge][edge_node];
    3556       27648 :     case PYRAMID13:
    3557       27648 :       return Pyramid13::edge_nodes_map[edge][edge_node];
    3558       27648 :     case PYRAMID14:
    3559       27648 :       return Pyramid14::edge_nodes_map[edge][edge_node];
    3560       27648 :     case PYRAMID18:
    3561       27648 :       return Pyramid18::edge_nodes_map[edge][edge_node];
    3562           0 :     default:
    3563           0 :       libmesh_error_msg("No static edge node map for element type " << Utility::enum_to_string(t));
    3564             :     }
    3565             : 
    3566             :   return invalid_uint;
    3567             : }
    3568             : 
    3569             : 
    3570             : 
    3571     3516844 : ElemType Elem::second_order_equivalent_type (const ElemType et,
    3572             :                                              const bool full_ordered)
    3573             : {
    3574     3516844 :   switch (et)
    3575             :     {
    3576           2 :     case NODEELEM:
    3577           2 :       return NODEELEM;
    3578        3806 :     case EDGE2:
    3579             :     case EDGE3:
    3580             :       {
    3581             :         // full_ordered not relevant
    3582        3806 :         return EDGE3;
    3583             :       }
    3584             : 
    3585           0 :     case EDGE4:
    3586             :       {
    3587             :         // full_ordered not relevant
    3588           0 :         return EDGE4;
    3589             :       }
    3590             : 
    3591       21150 :     case TRI3:
    3592             :     case TRI6:
    3593             :       {
    3594             :         // full_ordered not relevant
    3595       21150 :         return TRI6;
    3596             :       }
    3597             : 
    3598           0 :     case TRI7:
    3599           0 :       return TRI7;
    3600             : 
    3601             :       // Currently there is no TRISHELL6, so similarly to other types
    3602             :       // where this is the case, we just return the input.
    3603           0 :     case TRISHELL3:
    3604           0 :       return TRISHELL3;
    3605             : 
    3606       33454 :     case QUAD4:
    3607             :     case QUAD8:
    3608             :       {
    3609       33454 :         if (full_ordered)
    3610        2590 :           return QUAD9;
    3611             :         else
    3612         466 :           return QUAD8;
    3613             :       }
    3614             : 
    3615        8802 :     case QUADSHELL4:
    3616             :     case QUADSHELL8:
    3617             :       {
    3618        8802 :         if (full_ordered)
    3619         896 :           return QUADSHELL9;
    3620             :         else
    3621         448 :           return QUADSHELL8;
    3622             :       }
    3623             : 
    3624         258 :     case QUAD9:
    3625             :       {
    3626             :         // full_ordered not relevant
    3627         258 :         return QUAD9;
    3628             :       }
    3629             : 
    3630           2 :     case QUADSHELL9:
    3631             :       {
    3632             :         // full_ordered not relevant
    3633           2 :         return QUADSHELL9;
    3634             :       }
    3635             : 
    3636     1802795 :     case TET4:
    3637             :     case TET10:
    3638             :       {
    3639             :         // full_ordered not relevant
    3640     1802795 :         return TET10;
    3641             :       }
    3642             : 
    3643           0 :     case TET14:
    3644           0 :       return TET14;
    3645             : 
    3646      662376 :     case HEX8:
    3647             :     case HEX20:
    3648             :       {
    3649             :         // see below how this correlates with INFHEX8
    3650      662376 :         if (full_ordered)
    3651       43424 :           return HEX27;
    3652             :         else
    3653       17090 :           return HEX20;
    3654             :       }
    3655             : 
    3656         460 :     case HEX27:
    3657             :       {
    3658             :         // full_ordered not relevant
    3659         460 :         return HEX27;
    3660             :       }
    3661             : 
    3662      456152 :     case PRISM6:
    3663             :     case PRISM15:
    3664             :       {
    3665      456152 :         if (full_ordered)
    3666       29598 :           return PRISM18;
    3667             :         else
    3668       14786 :           return PRISM15;
    3669             :       }
    3670             : 
    3671             :     // full_ordered not relevant, already fully second order
    3672          12 :     case PRISM18:
    3673          12 :       return PRISM18;
    3674           0 :     case PRISM20:
    3675           0 :       return PRISM20;
    3676           0 :     case PRISM21:
    3677           0 :       return PRISM21;
    3678           0 :     case PYRAMID18:
    3679           0 :       return PYRAMID18;
    3680             : 
    3681      518939 :     case PYRAMID5:
    3682             :     case PYRAMID13:
    3683             :       {
    3684      518939 :         if (full_ordered)
    3685        7322 :           return PYRAMID14;
    3686             :         else
    3687       14592 :           return PYRAMID13;
    3688             :       }
    3689             : 
    3690           0 :     case PYRAMID14:
    3691             :       {
    3692             :         // full_ordered not relevant
    3693           0 :         return PYRAMID14;
    3694             :       }
    3695             : 
    3696             : 
    3697             : 
    3698             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    3699             : 
    3700             :       // infinite elements
    3701           0 :     case INFEDGE2:
    3702             :       {
    3703           0 :         return INFEDGE2;
    3704             :       }
    3705             : 
    3706           5 :     case INFQUAD4:
    3707             :     case INFQUAD6:
    3708             :       {
    3709             :         // full_ordered not relevant
    3710           5 :         return INFQUAD6;
    3711             :       }
    3712             : 
    3713        1032 :     case INFHEX8:
    3714             :     case INFHEX16:
    3715             :       {
    3716             :         /*
    3717             :          * Note that this matches with \p Hex8:
    3718             :          * For full-ordered, \p InfHex18 and \p Hex27
    3719             :          * belong together, and for not full-ordered,
    3720             :          * \p InfHex16 and \p Hex20 belong together.
    3721             :          */
    3722        1032 :         if (full_ordered)
    3723         452 :           return INFHEX18;
    3724             :         else
    3725         226 :           return INFHEX16;
    3726             :       }
    3727             : 
    3728           4 :     case INFHEX18:
    3729             :       {
    3730             :         // full_ordered not relevant
    3731           4 :         return INFHEX18;
    3732             :       }
    3733             : 
    3734           5 :     case INFPRISM6:
    3735             :     case INFPRISM12:
    3736             :       {
    3737             :         // full_ordered not relevant
    3738           5 :         return INFPRISM12;
    3739             :       }
    3740             : 
    3741             : #endif
    3742             : 
    3743             : 
    3744           0 :     default:
    3745             :       {
    3746             :         // what did we miss?
    3747           0 :         libmesh_error_msg("No second order equivalent element type for et =  "
    3748             :                           << Utility::enum_to_string(et));
    3749             :       }
    3750             :     }
    3751             : }
    3752             : 
    3753             : 
    3754             : 
    3755     5741251 : ElemType Elem::complete_order_equivalent_type (const ElemType et)
    3756             : {
    3757     5741251 :   switch (et)
    3758             :     {
    3759           0 :     case NODEELEM:
    3760           0 :       return NODEELEM;
    3761        1278 :     case EDGE2:
    3762             :     case EDGE3:
    3763        1278 :       return EDGE3;
    3764             : 
    3765           0 :     case EDGE4:
    3766           0 :       return EDGE4;
    3767             : 
    3768        7086 :     case TRI3:
    3769             :     case TRI6:
    3770             :     case TRI7:
    3771        7086 :       return TRI7;
    3772             : 
    3773             :       // Currently there is no TRISHELL6, so similarly to other types
    3774             :       // where this is the case, we just return the input.
    3775           0 :     case TRISHELL3:
    3776           0 :       return TRISHELL3;
    3777             : 
    3778         900 :     case QUAD4:
    3779             :     case QUAD8:
    3780             :     case QUAD9:
    3781         900 :       return QUAD9;
    3782             : 
    3783           0 :     case QUADSHELL4:
    3784             :     case QUADSHELL8:
    3785             :     case QUADSHELL9:
    3786           0 :       return QUADSHELL9;
    3787             : 
    3788     5477767 :     case TET4:
    3789             :     case TET10:
    3790             :     case TET14:
    3791     5477767 :       return TET14;
    3792             : 
    3793         316 :     case HEX8:
    3794             :     case HEX20:
    3795             :     case HEX27:
    3796         316 :       return HEX27;
    3797             : 
    3798             :     // We don't strictly need the 21st node for DoFs, but some code
    3799             :     // depends on it for e.g. refinement patterns
    3800       33449 :     case PRISM6:
    3801             :     case PRISM15:
    3802             :     case PRISM18:
    3803             :     case PRISM20:
    3804             :     case PRISM21:
    3805       33449 :       return PRISM21;
    3806             : 
    3807      220455 :     case PYRAMID5:
    3808             :     case PYRAMID13:
    3809             :     case PYRAMID14:
    3810             :     case PYRAMID18:
    3811      220455 :       return PYRAMID18;
    3812             : 
    3813             : 
    3814             : 
    3815             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    3816           0 :     case INFEDGE2:
    3817           0 :       return INFEDGE2;
    3818             : 
    3819           0 :     case INFQUAD4:
    3820             :     case INFQUAD6:
    3821           0 :       return INFQUAD6;
    3822             : 
    3823           0 :     case INFHEX8:
    3824             :     case INFHEX16:
    3825             :     case INFHEX18:
    3826           0 :       return INFHEX18;
    3827             : 
    3828             :     // Probably ought to implement INFPRISM13 and/or 14; until then
    3829             :     // we'll just return the not-complete-order ElemType, in
    3830             :     // accordance which what seems like bad precedent...
    3831           0 :     case INFPRISM6:
    3832             :     case INFPRISM12:
    3833           0 :       return INFPRISM12;
    3834             : #endif // LIBMESH_ENABLE_INFINITE_ELEMENTS
    3835             : 
    3836           0 :     default:
    3837             :       {
    3838             :         // what did we miss?
    3839           0 :         libmesh_error_msg("No complete order equivalent element type for et =  "
    3840             :                           << Utility::enum_to_string(et));
    3841             :       }
    3842             :     }
    3843             : }
    3844             : 
    3845             : 
    3846             : 
    3847           0 : Elem::side_iterator Elem::boundary_sides_begin()
    3848             : {
    3849           0 :   Predicates::BoundarySide<SideIter> bsp;
    3850           0 :   return side_iterator(this->_first_side(), this->_last_side(), bsp);
    3851             : }
    3852             : 
    3853             : 
    3854             : 
    3855             : 
    3856           0 : Elem::side_iterator Elem::boundary_sides_end()
    3857             : {
    3858           0 :   Predicates::BoundarySide<SideIter> bsp;
    3859           0 :   return side_iterator(this->_last_side(), this->_last_side(), bsp);
    3860             : }
    3861             : 
    3862             : 
    3863             : 
    3864             : 
    3865      157903 : Real Elem::volume () const
    3866             : {
    3867             :   // The default implementation builds a finite element of the correct
    3868             :   // order and sums up the JxW contributions.  This can be expensive,
    3869             :   // so the various element types can overload this method and compute
    3870             :   // the volume more efficiently.
    3871      157903 :   const FEFamily mapping_family = FEMap::map_fe_type(*this);
    3872      157903 :   const FEType fe_type(this->default_order(), mapping_family);
    3873             : 
    3874      157903 :   std::unique_ptr<FEBase> fe (FEBase::build(this->dim(),
    3875      175588 :                                             fe_type));
    3876             : 
    3877             :   // Use a map with a negative Jacobian tolerance, in case we're asked
    3878             :   // for the net volume of a tangled element
    3879       17685 :   fe->get_fe_map().set_jacobian_tolerance(std::numeric_limits<Real>::lowest());
    3880             : 
    3881       41928 :   const std::vector<Real> & JxW = fe->get_JxW();
    3882             : 
    3883             :   // The default quadrature rule should integrate the mass matrix,
    3884             :   // thus it should be plenty to compute the area
    3885      157903 :   QGauss qrule (this->dim(), fe_type.default_quadrature_order());
    3886             : 
    3887      157903 :   fe->attach_quadrature_rule(&qrule);
    3888             : 
    3889      157903 :   fe->reinit(this);
    3890             : 
    3891       17685 :   Real vol=0.;
    3892     6519764 :   for (auto jxw : JxW)
    3893     6361861 :     vol += jxw;
    3894             : 
    3895      175588 :   return vol;
    3896             : 
    3897      128003 : }
    3898             : 
    3899             : 
    3900             : 
    3901    40845840 : BoundingBox Elem::loose_bounding_box () const
    3902             : {
    3903    40845840 :   Point pmin = this->point(0);
    3904    40845840 :   Point pmax = pmin;
    3905             : 
    3906    40845840 :   unsigned int n_points = this->n_nodes();
    3907   215185789 :   for (unsigned int p=0; p != n_points; ++p)
    3908   697359796 :     for (unsigned d=0; d<LIBMESH_DIM; ++d)
    3909             :       {
    3910    76107846 :         const Point & pt = this->point(p);
    3911   523019847 :         if (pmin(d) > pt(d))
    3912    34581741 :           pmin(d) = pt(d);
    3913             : 
    3914   523019847 :         if (pmax(d) < pt(d))
    3915    83026046 :           pmax(d) = pt(d);
    3916             :       }
    3917             : 
    3918    43950588 :   return BoundingBox(pmin, pmax);
    3919             : }
    3920             : 
    3921             : Point
    3922        9399 : Elem::side_vertex_average_normal(const unsigned int s) const
    3923             : {
    3924        9399 :   unsigned int dim = this->dim();
    3925        9399 :   const std::unique_ptr<const Elem> face = this->build_side_ptr(s);
    3926             :   std::unique_ptr<libMesh::FEBase> fe(
    3927        9717 :       libMesh::FEBase::build(dim, libMesh::FEType(this->default_order())));
    3928         318 :   fe->add_p_level_in_reinit(false); // Yes, really use the default order
    3929         795 :   const std::vector<Point> & normals = fe->get_normals();
    3930        9399 :   std::vector<Point> ref_side_vertex_average_v = {face->reference_elem()->vertex_average()};
    3931        9399 :   fe->reinit(this, s, TOLERANCE, &ref_side_vertex_average_v);
    3932       18798 :   return normals[0];
    3933        8763 : }
    3934             : 
    3935     3431002 : bool Elem::is_vertex_on_parent(unsigned int c,
    3936             :                                unsigned int n) const
    3937             : {
    3938             : #ifdef LIBMESH_ENABLE_AMR
    3939             : 
    3940     3431002 :   unsigned int my_n_vertices = this->n_vertices();
    3941    17136072 :   for (unsigned int n_parent = 0; n_parent != my_n_vertices;
    3942             :        ++n_parent)
    3943    16890944 :     if (this->node_ptr(n_parent) == this->child_ptr(c)->node_ptr(n))
    3944       54947 :       return true;
    3945      256846 :   return false;
    3946             : 
    3947             : #else
    3948             : 
    3949             :   // No AMR?
    3950             :   libmesh_ignore(c,n);
    3951             :   libmesh_error_msg("ERROR: AMR disabled, how did we get here?");
    3952             :   return true;
    3953             : 
    3954             : #endif
    3955             : }
    3956             : 
    3957             : 
    3958             : 
    3959           0 : unsigned int Elem::opposite_side(const unsigned int /*s*/) const
    3960             : {
    3961             :   // If the subclass didn't rederive this, using it is an error
    3962           0 :   libmesh_not_implemented();
    3963             : }
    3964             : 
    3965             : 
    3966             : 
    3967           0 : unsigned int Elem::opposite_node(const unsigned int /*n*/,
    3968             :                                  const unsigned int /*s*/) const
    3969             : {
    3970             :   // If the subclass didn't rederive this, using it is an error
    3971           0 :   libmesh_not_implemented();
    3972             : }
    3973             : 
    3974             : 
    3975       37659 : unsigned int Elem::center_node_on_side(const unsigned short libmesh_dbg_var(side)) const
    3976             : {
    3977        3160 :   libmesh_assert_less (side, this->n_sides());
    3978       37659 :   return invalid_uint;
    3979             : }
    3980             : 
    3981             : 
    3982      188382 : void Elem::swap2boundarysides(unsigned short s1,
    3983             :                               unsigned short s2,
    3984             :                               BoundaryInfo * boundary_info) const
    3985             : {
    3986       18964 :   std::vector<boundary_id_type> ids1, ids2;
    3987      188382 :   boundary_info->boundary_ids(this, s1, ids1);
    3988      188382 :   boundary_info->boundary_ids(this, s2, ids2);
    3989      188382 :   boundary_info->remove_side(this, s1);
    3990      188382 :   boundary_info->remove_side(this, s2);
    3991      188382 :   if (!ids1.empty())
    3992        7713 :     boundary_info->add_side(this, s2, ids1);
    3993      188382 :   if (!ids2.empty())
    3994        4392 :     boundary_info->add_side(this, s1, ids2);
    3995      188382 : }
    3996             : 
    3997             : 
    3998      370518 : void Elem::swap2boundaryedges(unsigned short e1,
    3999             :                               unsigned short e2,
    4000             :                               BoundaryInfo * boundary_info) const
    4001             : {
    4002       38012 :   std::vector<boundary_id_type> ids1, ids2;
    4003      370518 :   boundary_info->edge_boundary_ids(this, e1, ids1);
    4004      370518 :   boundary_info->edge_boundary_ids(this, e2, ids2);
    4005      370518 :   boundary_info->remove_edge(this, e1);
    4006      370518 :   boundary_info->remove_edge(this, e2);
    4007      370518 :   if (!ids1.empty())
    4008           0 :     boundary_info->add_edge(this, e2, ids1);
    4009      370518 :   if (!ids2.empty())
    4010           0 :     boundary_info->add_edge(this, e1, ids2);
    4011      370518 : }
    4012             : 
    4013             : bool
    4014     8106214 : Elem::is_internal(const unsigned int i) const
    4015             : {
    4016     8106214 :   switch (this->dim())
    4017             :   {
    4018           1 :     case 0:
    4019           1 :       return false;
    4020             : 
    4021         216 :     case 1:
    4022         216 :       return !this->is_vertex(i);
    4023             : 
    4024     7990185 :     case 2:
    4025     7990185 :       return !this->is_vertex(i) && !this->is_edge(i);
    4026             : 
    4027      115801 :     case 3:
    4028      115801 :       return !this->is_vertex(i) && !this->is_edge(i) && !this->is_face(i);
    4029             : 
    4030           0 :     default:
    4031           0 :       libmesh_error_msg("impossible element dimension " << std::to_string(this->dim()));
    4032             :       return 0;
    4033             :   }
    4034             : }
    4035             : 
    4036             : bool
    4037   830337916 : Elem::positive_edge_orientation(const unsigned int i) const
    4038             : {
    4039    65776489 :   libmesh_assert_less (i, this->n_edges());
    4040             : 
    4041   830337916 :   return this->point(this->local_edge_node(i, 0)) >
    4042   896114405 :          this->point(this->local_edge_node(i, 1));
    4043             : }
    4044             : 
    4045             : bool
    4046   348944750 : Elem::positive_face_orientation(const unsigned int i) const
    4047             : {
    4048   348944750 :   return this->face_orientation(i) % 2;
    4049             : }
    4050             : 
    4051             : 
    4052             : unsigned int
    4053  2089125692 : Elem::face_orientation(const unsigned int i) const
    4054             : {
    4055   169079362 :   libmesh_assert_less (i, this->n_faces());
    4056             : 
    4057             :   // Get the number of vertices N of face i. Note that for 3d elements, i.e.
    4058             :   // elements for which this->n_faces() > 0, the number of vertices on any of
    4059             :   // its sides (or faces) is just the number of that face's sides (or edges).
    4060  2089125692 :   const unsigned int N = Elem::type_to_n_sides_map[this->side_type(i)];
    4061             : 
    4062  2089125692 :   const std::vector<unsigned int> nodes = this->nodes_on_side(i);
    4063             : 
    4064  6778589630 :   auto cmp = [&](const unsigned int & m, const unsigned int & n) -> bool
    4065 10153343812 :              { return this->point(m) < this->point(n); };
    4066             : 
    4067  2089125692 :   const unsigned int v = std::distance(nodes.begin(),
    4068  2089125692 :                          std::min_element(nodes.begin(), nodes.begin() + N, cmp));
    4069             : 
    4070             :   // v is the position of the least vertex. Compare its neighbors just
    4071             :   // before and after it, cyclically: the face is positively oriented iff
    4072             :   // the lesser neighbor precedes v, i.e. the vertices run backward from
    4073             :   // the least vertex through the face's node map.
    4074  2765443140 :   return 2 * v + cmp(nodes[(v - 1 + N) % N], nodes[(v + 1) % N]);
    4075             : }
    4076             : 
    4077             : std::vector<unsigned int>
    4078  1711184772 : Elem::oriented_face_vertices(const unsigned int i) const
    4079             : {
    4080  1711184772 :   const unsigned int N = Elem::type_to_n_sides_map[this->side_type(i)];
    4081  1711184772 :   const unsigned int orientation = this->face_orientation(i);
    4082  1711184772 :   const unsigned int least = orientation / 2;
    4083             : 
    4084             :   // A positively oriented face has the lesser neighbor before the least
    4085             :   // vertex in its side node map
    4086  1711184772 :   const bool backward = orientation % 2;
    4087             : 
    4088  1711184772 :   std::vector<unsigned int> vertices(N);
    4089  7674821190 :   for (const auto k : make_range(N))
    4090  5963636418 :     vertices[k] = this->local_side_node(i, (least + (backward ? N - k : k)) % N);
    4091             : 
    4092  1711184772 :   return vertices;
    4093             : }
    4094             : 
    4095             : bool
    4096      143208 : Elem::relative_edge_face_order(const unsigned int e, const unsigned int s) const
    4097             : {
    4098           0 :   libmesh_assert_less (e, this->n_edges());
    4099           0 :   libmesh_assert_less (s, this->n_faces());
    4100           0 :   libmesh_assert (is_edge_on_side(e, s));
    4101             : 
    4102      143208 :   const unsigned int N = Elem::type_to_n_sides_map[this->side_type(s)];
    4103             : 
    4104             :   unsigned int v;
    4105      255312 :   for (v = 0; v < N; v++)
    4106      255312 :     if (this->local_side_node(s, v) == this->local_edge_node(e, 0))
    4107           0 :       break;
    4108             : 
    4109           0 :   libmesh_assert (this->local_side_node(s, (v + 1) % N) ==
    4110             :                   this->local_edge_node(e, 1) ||
    4111             :                   this->local_side_node(s, (v - 1 + N) % N) ==
    4112             :                   this->local_edge_node(e, 1));
    4113             : 
    4114      143208 :   return this->local_side_node(s, (v + 1) % N) ==
    4115      143208 :          this->local_edge_node(e, 1);
    4116             : }
    4117             : 
    4118             : } // namespace libMesh

Generated by: LCOV version 1.14