LCOV - code coverage report
Current view: top level - src/geom - elem.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4476 (4beb67) with base a68cc6 Lines: 1014 1341 75.6 %
Date: 2026-06-03 20:22:46 Functions: 71 101 70.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14