LCOV - code coverage report
Current view: top level - src/geom - elem.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4297 (88aec6) with base 03e0ca Lines: 994 1307 76.1 %
Date: 2025-10-29 13:04:21 Functions: 70 98 71.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14