LCOV - code coverage report
Current view: top level - include/mesh - mesh_base.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4411 (aefcbc) with base 893689 Lines: 139 152 91.4 %
Date: 2026-07-27 16:32:15 Functions: 123 232 53.0 %
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             : 
      20             : #ifndef LIBMESH_MESH_BASE_H
      21             : #define LIBMESH_MESH_BASE_H
      22             : 
      23             : // Local Includes
      24             : #include "libmesh/dof_object.h" // for invalid_processor_id
      25             : #include "libmesh/enum_order.h"
      26             : #include "libmesh/int_range.h"
      27             : #include "libmesh/libmesh_common.h"
      28             : #include "libmesh/multi_predicates.h"
      29             : #include "libmesh/point_locator_base.h"
      30             : #include "libmesh/variant_filter_iterator.h"
      31             : #include "libmesh/parallel_object.h"
      32             : #include "libmesh/simple_range.h"
      33             : 
      34             : // C++ Includes
      35             : #include <cstddef>
      36             : #include <string>
      37             : #include <memory>
      38             : 
      39             : #include "libmesh/vector_value.h"
      40             : 
      41             : namespace libMesh
      42             : {
      43             : // Forward declarations
      44             : class BoundaryInfo;
      45             : class Elem;
      46             : class GhostingFunctor;
      47             : class Node;
      48             : class Point;
      49             : class Partitioner;
      50             : class PeriodicBoundary;
      51             : class PeriodicBoundaries;
      52             : 
      53             : template <typename T>
      54             : class SparseMatrix;
      55             : 
      56             : enum ElemType : int;
      57             : enum ElemMappingType : unsigned char;
      58             : 
      59             : template <class MT>
      60             : class MeshInput;
      61             : 
      62             : template <typename iterator_type, typename object_type>
      63             : class StoredRange;
      64             : 
      65             : /**
      66             :  * This is the \p MeshBase class. This class provides all the data necessary
      67             :  * to describe a geometric entity.  It allows for the description of a
      68             :  * \p dim dimensional object that lives in \p LIBMESH_DIM-dimensional space.
      69             :  * \par
      70             :  * A mesh is made of nodes and elements, and this class provides data
      71             :  * structures to store and access both.  A mesh may be partitioned into a
      72             :  * number of subdomains, and this class provides that functionality.
      73             :  * Furthermore, this class provides functions for reading and writing a
      74             :  * mesh to disk in various formats.
      75             :  *
      76             :  * \author Benjamin S. Kirk
      77             :  * \date 2002
      78             :  * \brief Base class for Mesh.
      79             :  */
      80             : class MeshBase : public ParallelObject
      81             : {
      82             : public:
      83             : 
      84             :   /**
      85             :    * Constructor.  Takes \p dim, the dimension of the mesh.
      86             :    * The mesh dimension can be changed (and may automatically be
      87             :    * changed by mesh generation/loading) later.
      88             :    */
      89             :   MeshBase (const Parallel::Communicator & comm_in,
      90             :             unsigned char dim=1);
      91             : 
      92             :   /**
      93             :    * Copy-constructor.
      94             :    */
      95             :   MeshBase (const MeshBase & other_mesh);
      96             : 
      97             :   /**
      98             :    * Move-constructor - deleted because after a theoretical move-construction
      99             :    * and then destruction of the moved-from object, the moved \p BoundaryInfo
     100             :    * would hold an invalid reference to the moved-from mesh
     101             :    */
     102             :   MeshBase(MeshBase &&) = delete;
     103             : 
     104             :   /**
     105             :    * Copy and move assignment are not allowed because MeshBase
     106             :    * subclasses manually manage memory (Elems and Nodes) and therefore
     107             :    * the default versions of these operators would leak memory.  Since
     108             :    * we don't want to maintain non-default copy and move assignment
     109             :    * operators at this time, the safest and most self-documenting
     110             :    * approach is to delete them.
     111             :    *
     112             :    * If you need to copy a Mesh, use the clone() method.
     113             :    */
     114             :   MeshBase & operator= (const MeshBase &) = delete;
     115             :   MeshBase & operator= (MeshBase && other_mesh);
     116             : 
     117             :   /**
     118             :    * Shim to allow operator = (&&) to behave like a virtual function
     119             :    * without having to be one.
     120             :    */
     121             :   virtual MeshBase & assign(MeshBase && other_mesh) = 0;
     122             : 
     123             :   /**
     124             :    * This tests for exactly-equal data in all the senses that a
     125             :    * mathematician would care about (element connectivity, nodal
     126             :    * coordinates), but in the senses a programmer would care about it
     127             :    * allows for non-equal equivalence in some ways (we accept
     128             :    * different Elem/Node addresses in memory) but not others (we do
     129             :    * not accept different subclass types, nor even different Elem/Node
     130             :    * ids).
     131             :    *
     132             :    * Though this method is non-virtual, its implementation calls the
     133             :    * virtual function \p subclass_first_difference_from() to test for
     134             :    * equality of subclass-specific data as well.
     135             :    */
     136             :   bool operator== (const MeshBase & other_mesh) const;
     137             : 
     138             :   bool operator!= (const MeshBase & other_mesh) const
     139             :   {
     140             :     return !(*this == other_mesh);
     141             :   }
     142             : 
     143             :   /**
     144             :    * This behaves like libmesh_assert(*this == other_mesh), but gives
     145             :    * a more useful accounting of the first difference found, if the
     146             :    * assertion fails.
     147             :    */
     148             :   void assert_equal_to (const MeshBase & other_mesh,
     149             :                         std::string_view failure_context) const;
     150             : 
     151             :   /**
     152             :    * This behaves the same as operator==, but only for the local and
     153             :    * ghosted aspects of the mesh; i.e. operator== is true iff local
     154             :    * equality is true on every rank.
     155             :    */
     156             :   bool locally_equals (const MeshBase & other_mesh) const;
     157             : 
     158             :   /**
     159             :    * Virtual "copy constructor".  The copy will be of the same
     160             :    * subclass as \p this, and will satisfy "copy == this" when it is
     161             :    * created.
     162             :    */
     163             :   virtual std::unique_ptr<MeshBase> clone() const = 0;
     164             : 
     165             :   /**
     166             :    * Destructor.
     167             :    */
     168             :   virtual ~MeshBase ();
     169             : 
     170             :   /**
     171             :    * A partitioner to use at each partitioning
     172             :    */
     173      450221 :   virtual std::unique_ptr<Partitioner> & partitioner() { return _partitioner; }
     174             : 
     175             :   /**
     176             :    * The information about boundary ids on the mesh
     177             :    */
     178      780791 :   const BoundaryInfo & get_boundary_info() const { return *boundary_info; }
     179             : 
     180             :   /**
     181             :    * Writable information about boundary ids on the mesh
     182             :    */
     183     1386597 :   BoundaryInfo & get_boundary_info() { return *boundary_info; }
     184             : 
     185             :   /**
     186             :    * Deletes all the element and node data that is currently stored.
     187             :    *
     188             :    * elem and node extra_integer data is nevertheless *retained* here,
     189             :    * for better compatibility between that feature and older code's
     190             :    * use of MeshBase::clear()
     191             :    */
     192             :   virtual void clear ();
     193             : 
     194             :   /**
     195             :    * Deletes all the element data that is currently stored.
     196             :    *
     197             :    * No Node is removed from the mesh, however even NodeElem elements
     198             :    * are deleted, so the remaining Nodes will be considered "unused"
     199             :    * and cleared unless they are reconnected to new elements before
     200             :    * the next preparation step.
     201             :    *
     202             :    * This does not affect BoundaryInfo data; any boundary information
     203             :    * associated elements should already be cleared.
     204             :    */
     205             :   virtual void clear_elems () = 0;
     206             : 
     207             :   /**
     208             :    * \returns \p true if the mesh is marked as having undergone all of
     209             :    * the preparation done in a call to \p prepare_for_use, \p false
     210             :    * otherwise.
     211             :    */
     212             :   bool is_prepared () const;
     213             : 
     214             :   /**
     215             :    * \returns the \p Preparation structure with details about in what
     216             :    * ways \p this mesh is currently prepared or unprepared.  This
     217             :    * structure may change in the future when cache designs change.
     218             :    */
     219             :   struct Preparation;
     220             : 
     221       39836 :   Preparation preparation () const
     222      129239 :   { return _preparation; }
     223             : 
     224             : #ifdef LIBMESH_ENABLE_DEPRECATED
     225             :   /**
     226             :    * Tells this we have done some operation where we should no longer
     227             :    * consider ourself prepared.  This is a very coarse setting; it is
     228             :    * generally more efficient to mark finer-grained settings instead.
     229             :    *
     230             :    * This method name is now deprecated, in part to match the less
     231             :    * awkward unset_has_ names of the more fine-grained methods, in
     232             :    * part as a way to prompt older user codes to use the more
     233             :    * fine-grained methods where they can, to speed up the
     234             :    * complete_preparation() calls afterward.
     235             :    */
     236             :   void set_isnt_prepared()
     237             :   { libmesh_deprecated(); _preparation = false; }
     238             : #endif // LIBMESH_ENABLE_DEPRECATED
     239             : 
     240             :   /**
     241             :    * Tells this we have done some operation where we should no longer
     242             :    * consider ourself prepared.  This is a very coarse setting; it is
     243             :    * generally more efficient to mark finer-grained settings instead.
     244             :    */
     245             :   void unset_is_prepared();
     246             : 
     247             :   /**
     248             :    * Tells this we have done some operation creating unpartitioned
     249             :    * elements.
     250             :    *
     251             :    * User code which adds elements to this mesh must either partition
     252             :    * them too or call this method.
     253             :    */
     254           0 :   void unset_is_partitioned()
     255           0 :   { _preparation.is_partitioned = false; }
     256             : 
     257             :   /**
     258             :    * Tells this we have done some operation (e.g. adding objects to a
     259             :    * distributed mesh on one processor only) which can lose
     260             :    * synchronization of id counts.
     261             :    *
     262             :    * User code which does distributed additions of nodes or elements
     263             :    * must call either this method or \p update_parallel_id_counts().
     264             :    */
     265             :   void unset_has_synched_id_counts()
     266             :   { _preparation.has_synched_id_counts = false; }
     267             : 
     268             :   /**
     269             :    * Tells this we have done some operation (e.g. adding elements
     270             :    * without setting their neighbor pointers, or adding disjoint
     271             :    * neighbor boundary pairs) which requires neighbor pointers to be
     272             :    * determined later.
     273             :    *
     274             :    * User code which adds new elements to this mesh must call this
     275             :    * function or manually set neighbor pointer from and to those
     276             :    * elements.
     277             :    */
     278          16 :   void unset_has_neighbor_ptrs()
     279        4708 :   { _preparation.has_neighbor_ptrs = false; }
     280             : 
     281             :   /**
     282             :    * Tells this we have done some operation (e.g. adding elements with
     283             :    * a new dimension or subdomain value) which may invalidate cached
     284             :    * summaries of element data.
     285             :    *
     286             :    * User code which adds new elements to this mesh must call this
     287             :    * function.
     288             :    */
     289          22 :   void unset_has_cached_elem_data()
     290      346512 :   { _preparation.has_cached_elem_data = false; }
     291             : 
     292             :   /**
     293             :    * Tells this we have done some operation (e.g. refining elements
     294             :    * with interior parents) which requires interior parent pointers to
     295             :    * be found later.
     296             :    *
     297             :    * Most user code will not need to call this method; any user code
     298             :    * that manipulates interior parents or their boundary elements may
     299             :    * be an exception.
     300             :    */
     301             :   void unset_has_interior_parent_ptrs()
     302             :   { _preparation.has_interior_parent_ptrs = false; }
     303             : 
     304             :   /**
     305             :    * Tells this we have done some operation (e.g. repartitioning)
     306             :    * which may have left elements as ghosted which on a distributed
     307             :    * mesh should be remote.
     308             :    *
     309             :    * User code should probably never need to use this; we can set it
     310             :    * in Partitioner.  Any user code which manually repartitions
     311             :    * elements on distributed meshes may need to call this manually, in
     312             :    * addition to manually communicating elements with newly-created
     313             :    * ghosting requirements.
     314             :    */
     315           0 :   void unset_has_removed_remote_elements()
     316           0 :   { _preparation.has_removed_remote_elements = false; }
     317             : 
     318             :   /**
     319             :    * Tells this we have done some operation (e.g. coarsening)
     320             :    * which may have left orphaned nodes in need of removal.
     321             :    *
     322             :    * Most user code should probably never need to use this; we can set
     323             :    * it in MeshRefinement.  User code which deletes elements without
     324             :    * carefully deleting orphaned nodes should call this manually.
     325             :    */
     326           0 :   void unset_has_removed_orphaned_nodes()
     327           0 :   { _preparation.has_removed_orphaned_nodes = false; }
     328             : 
     329             :   /**
     330             :    * Tells this we have done some operation (e.g. adding or removing
     331             :    * elements) which may require a reinit() of custom ghosting
     332             :    * functors.
     333             :    *
     334             :    * User code which adds or removes elements should call this method.
     335             :    * User code which moves nodes ... should probably call this method,
     336             :    * in case ghosting functors depending on position exist?
     337             :    */
     338          94 :   void unset_has_reinit_ghosting_functors()
     339        3337 :   { _preparation.has_reinit_ghosting_functors = false; }
     340             : 
     341             :   /**
     342             :    * Tells this we have done some operation which may have invalidated
     343             :    * our cached boundary id sets.
     344             :    *
     345             :    * User code which removes elements, or which adds or removes
     346             :    * boundary entries, should call this method.
     347             :    */
     348           2 :   void unset_has_boundary_id_sets()
     349        3245 :   { _preparation.has_boundary_id_sets = false; }
     350             : 
     351             :   /**
     352             :    * Tells this we have done some operation which may have left the
     353             :    * subdomain id to name map inconsistent across processors.
     354             :    *
     355             :    * User code which adds or changes subdomain names should call this
     356             :    * method.
     357             :    */
     358       59094 :   void unset_has_synched_subdomain_name_map()
     359     1123116 :   { _preparation.has_synched_subdomain_name_map = false; }
     360             : 
     361             :   /**
     362             :    * \returns \p true if all elements and nodes of the mesh
     363             :    * exist on the current processor, \p false otherwise
     364             :    */
     365      818496 :   virtual bool is_serial () const
     366      818496 :   { return true; }
     367             : 
     368             :   /**
     369             :    * \returns \p true if all elements and nodes of the mesh
     370             :    * exist on the processor 0, \p false otherwise
     371             :    */
     372        1325 :   virtual bool is_serial_on_zero () const
     373        1325 :   { return true; }
     374             : 
     375             :   /**
     376             :    * Asserts that not all elements and nodes of the mesh necessarily
     377             :    * exist on the current processor.  Only valid to call on classes
     378             :    * which can be created in a distributed form.
     379             :    */
     380           0 :   virtual void set_distributed ()
     381           0 :   { libmesh_error(); }
     382             : 
     383             :   /**
     384             :    * \returns \p true if new elements and nodes can and should be
     385             :    * created in synchronization on all processors, \p false otherwise
     386             :    */
     387     2468099 :   virtual bool is_replicated () const
     388     2468099 :   { return true; }
     389             : 
     390             :   /**
     391             :    * Gathers all elements and nodes of the mesh onto
     392             :    * every processor
     393             :    */
     394           2 :   virtual void allgather () {}
     395             : 
     396             :   /**
     397             :    * Gathers all elements and nodes of the mesh onto
     398             :    * processor zero
     399             :    */
     400           0 :   virtual void gather_to_zero() {}
     401             : 
     402             :   /**
     403             :    * When supported, deletes all nonlocal elements of the mesh
     404             :    * except for "ghosts" which touch a local element, and deletes
     405             :    * all nodes which are not part of a local or ghost element
     406             :    */
     407       66241 :   virtual void delete_remote_elements () {
     408       66241 :     _preparation.has_removed_remote_elements = true;
     409       66241 :   }
     410             : 
     411             :   /**
     412             :    * Loops over ghosting functors and calls mesh_reinit()
     413             :    */
     414             :   void reinit_ghosting_functors();
     415             : 
     416             :   /**
     417             :    * \returns The logical dimension of the mesh; i.e. the manifold
     418             :    * dimension of the elements in the mesh.  When we have
     419             :    * multi-dimensional meshes (e.g. hexes and quads in the same mesh)
     420             :    * then this will return the largest such dimension.
     421             :    */
     422             :   unsigned int mesh_dimension () const;
     423             : 
     424             :   /**
     425             :    * Resets the logical dimension of the mesh. If the mesh has
     426             :    * elements of multiple dimensions, this should be set to the largest
     427             :    * dimension. E.g. if the mesh has 1D and 2D elements, this should
     428             :    * be set to 2. If the mesh has 2D and 3D elements, this should be
     429             :    * set to 3.
     430             :    */
     431       10046 :   void set_mesh_dimension (unsigned char d)
     432      295105 :   { _elem_dims.clear(); _elem_dims.insert(d); }
     433             : 
     434             :   /**
     435             :    * \returns A const reference to a std::set of element dimensions
     436             :    * present in the mesh.
     437             :    */
     438             :   const std::set<unsigned char> & elem_dimensions() const;
     439             : 
     440             :   /**
     441             :    * \returns A const reference to a std::set of element default
     442             :    * orders present in the mesh.
     443             :    */
     444             :   const std::set<Order> & elem_default_orders() const;
     445             : 
     446             :   /**
     447             :    * \returns The smallest supported_nodal_order() of any element
     448             :    * present in the mesh, which is thus the maximum supported nodal
     449             :    * order on the mesh as a whole.
     450             :    */
     451             :   Order supported_nodal_order() const;
     452             : 
     453             :   /**
     454             :    * Most of the time you should not need to call this, as the element
     455             :    * dimensions will be set automatically by a call to cache_elem_data(),
     456             :    * therefore only call this if you know what you're doing.
     457             :    *
     458             :    * In some specialized situations, for example when adding a single
     459             :    * Elem on all procs, it can be faster to skip calling cache_elem_data()
     460             :    * and simply specify the element dimensions manually, which is why this
     461             :    * setter exists.
     462             :    */
     463             :   void set_elem_dimensions(std::set<unsigned char> elem_dims);
     464             : 
     465             :   /**
     466             :    * Typedef for the "set" container used to store elemset ids. The
     467             :    * main requirements are that the entries be sorted and unique, so
     468             :    * std::set works for this, but there may be more efficient
     469             :    * alternatives.
     470             :    */
     471             :   typedef std::set<elemset_id_type> elemset_type;
     472             : 
     473             :   /**
     474             :    * Tabulate a user-defined "code" for elements which belong to the element sets
     475             :    * specified in \p id_set. For example, suppose that we have two elemsets A and
     476             :    * B with the following Elem ids:
     477             :    * Elemset A = {1, 3}
     478             :    * Elemset B = {2, 3}
     479             :    *
     480             :    * This implies the following mapping from elem id to elemset id:
     481             :    * Elem 1 -> {A}
     482             :    * Elem 2 -> {B}
     483             :    * Elem 3 -> {A,B}
     484             :    *
     485             :    * In this case, we would need to tabulate three different elemset codes, e.g.:
     486             :    * 0 -> {A}
     487             :    * 1 -> {B}
     488             :    * 2 -> {A,B}
     489             :    *
     490             :    * Also sets up the inverse mapping, so that if one knows all the
     491             :    * element sets an Elem belongs to, one can look up the
     492             :    * corresponding elemset code.
     493             :    */
     494             :   void add_elemset_code(dof_id_type code, MeshBase::elemset_type id_set);
     495             : 
     496             :   /**
     497             :    * Returns the number of unique elemset ids which have been added
     498             :    * via add_elemset_code(), which is the size of the _all_elemset_ids
     499             :    * set.
     500             :    */
     501             :   unsigned int n_elemsets() const;
     502             : 
     503             :   /**
     504             :    * Look up the element sets for a given elemset code and
     505             :    * vice-versa. The elemset must have been previously stored by
     506             :    * calling add_elemset_code(). If no such code/set is found, returns
     507             :    * the empty set or DofObject::invalid_id, respectively.
     508             :    */
     509             :   void get_elemsets(dof_id_type elemset_code, MeshBase::elemset_type & id_set_to_fill) const;
     510             :   dof_id_type get_elemset_code(const MeshBase::elemset_type & id_set) const;
     511             : 
     512             :   /**
     513             :    * Return a vector of all elemset codes defined on the mesh. We get
     514             :    * this by looping over the _elemset_codes map.
     515             :    */
     516             :   std::vector<dof_id_type> get_elemset_codes() const;
     517             : 
     518             :   /**
     519             :    * Replace elemset code "old_code" with "new_code". This function loops over
     520             :    * all elements and changes the extra integer corresponding to the "elemset_code"
     521             :    * label, and updates the _elemset_codes and _elemset_codes_inverse_map members.
     522             :    * Does not change the elemset ids of any of the sets.
     523             :    */
     524             :   void change_elemset_code(dof_id_type old_code, dof_id_type new_code);
     525             : 
     526             :   /**
     527             :    * Replace elemset id "old_id" with "new_id". Does not change any of the
     528             :    * elemset codes, so does not need to loop over the elements themselves.
     529             :    */
     530             :   void change_elemset_id(elemset_id_type old_id, elemset_id_type new_id);
     531             : 
     532             :   /**
     533             :    * \returns The "spatial dimension" of the mesh.
     534             :    *
     535             :    * The spatial dimension is defined as:
     536             :    *
     537             :    *   1 - for an exactly x-aligned mesh of 1D elements
     538             :    *   2 - for an exactly x-y planar mesh of 2D elements
     539             :    *   3 - otherwise
     540             :    *
     541             :    * No tolerance checks are performed to determine whether the Mesh
     542             :    * is x-aligned or x-y planar, only strict equality with zero in the
     543             :    * higher dimensions is checked.  Also, x-z and y-z planar meshes are
     544             :    * considered to have spatial dimension == 3.
     545             :    *
     546             :    * The spatial dimension is updated during mesh preparation based
     547             :    * on the dimensions of the various elements present in the Mesh,
     548             :    * but is *never automatically decreased*.
     549             :    *
     550             :    * For example, if the user calls set_spatial_dimension(2) and then
     551             :    * later inserts 3D elements into the mesh,
     552             :    * Mesh::spatial_dimension() will return 3 after the next call to
     553             :    * prepare_for_use() or complete_preparation().  On the other hand,
     554             :    * if the user calls set_spatial_dimension(3) and then inserts only
     555             :    * x-aligned 1D elements into the Mesh, mesh.spatial_dimension()
     556             :    * will remain 3.
     557             :    */
     558             :   unsigned int spatial_dimension () const;
     559             : 
     560             :   /**
     561             :    * Sets the "spatial dimension" of the Mesh.  See the documentation
     562             :    * for Mesh::spatial_dimension() for more information.
     563             :    */
     564             :   void set_spatial_dimension(unsigned char d);
     565             : 
     566             :   /**
     567             :    * \returns The number of nodes in the mesh.
     568             :    *
     569             :    * This function and others must be defined in derived classes since
     570             :    * the MeshBase class has no specific storage for nodes or elements.
     571             :    * The standard \p n_nodes() function may return a cached value on
     572             :    * distributed meshes, and so can be called by any processor at any
     573             :    * time.
     574             :    */
     575             :   virtual dof_id_type n_nodes () const = 0;
     576             : 
     577             :   /**
     578             :    * \returns The number of nodes in the mesh.
     579             :    *
     580             :    * This function and others must be overridden in derived classes since
     581             :    * the MeshBase class has no specific storage for nodes or elements.
     582             :    * The \p parallel_n_nodes() function computes a parallel-synchronized
     583             :    * value on distributed meshes, and so must be called in parallel
     584             :    * only.
     585             :    */
     586             :   virtual dof_id_type parallel_n_nodes () const = 0;
     587             : 
     588             :   /**
     589             :    * \returns The number of nodes on processor \p proc.
     590             :    */
     591             :   dof_id_type n_nodes_on_proc (const processor_id_type proc) const;
     592             : 
     593             :   /**
     594             :    * \returns The number of nodes on the local processor.
     595             :    */
     596         504 :   dof_id_type n_local_nodes () const
     597     1910770 :   { return this->n_nodes_on_proc (this->processor_id()); }
     598             : 
     599             :   /**
     600             :    * \returns The number of nodes owned by no processor.
     601             :    */
     602       33658 :   dof_id_type n_unpartitioned_nodes () const
     603     2123599 :   { return this->n_nodes_on_proc (DofObject::invalid_processor_id); }
     604             : 
     605             :   /**
     606             :    * \returns A number one greater than the maximum node id in the
     607             :    * mesh. A more apt name for this method would be end_node_id
     608             :    */
     609             :   virtual dof_id_type max_node_id () const = 0;
     610             : 
     611             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     612             :   /**
     613             :    * \returns The next unique id to be used.
     614             :    */
     615        7176 :   unique_id_type next_unique_id() const { return _next_unique_id; }
     616             : 
     617             :   /**
     618             :    * Sets the next available unique id to be used.  On a
     619             :    * ReplicatedMesh, or when adding unpartitioned objects to a
     620             :    * DistributedMesh, this must be kept in sync on all processors.
     621             :    *
     622             :    * On a DistributedMesh, other unique_id values (larger than this
     623             :    * one) may be chosen next, to allow unique_id assignment without
     624             :    * communication.
     625             :    */
     626             :   virtual void set_next_unique_id(unique_id_type id) = 0;
     627             : #endif
     628             : 
     629             :   /**
     630             :    * Reserves space for a known number of nodes.
     631             :    *
     632             :    * \note This method may or may not do anything, depending on the
     633             :    * actual \p Mesh implementation.  If you know the number of nodes
     634             :    * you will add and call this method before repeatedly calling \p
     635             :    * add_point() the implementation will be more efficient.
     636             :    */
     637             :   virtual void reserve_nodes (const dof_id_type nn) = 0;
     638             : 
     639             :   /**
     640             :    * \returns The number of elements in the mesh.
     641             :    *
     642             :    * The standard n_elem() function may return a cached value on
     643             :    * distributed meshes, and so can be called by any processor at any
     644             :    * time.
     645             :    */
     646             :   virtual dof_id_type n_elem () const = 0;
     647             : 
     648             :   /**
     649             :    * \returns The number of elements in the mesh.
     650             :    *
     651             :    * The parallel_n_elem() function computes a parallel-synchronized
     652             :    * value on distributed meshes, and so must be called in parallel
     653             :    * only.
     654             :    */
     655             :   virtual dof_id_type parallel_n_elem () const = 0;
     656             : 
     657             :   /**
     658             :    * \returns A number one greater than the maximum element id in the
     659             :    * mesh. A more apt name for this method would be end_elem_id
     660             :    */
     661             :   virtual dof_id_type max_elem_id () const = 0;
     662             : 
     663             :   /**
     664             :    * \returns A number greater than or equal to the maximum unique_id in the
     665             :    * mesh.
     666             :    */
     667             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     668             :   virtual unique_id_type parallel_max_unique_id () const = 0;
     669             : #endif
     670             : 
     671             :   /**
     672             :    * Reserves space for a known number of elements.
     673             :    *
     674             :    * \note This method may or may not do anything, depending on the
     675             :    * actual \p Mesh implementation.  If you know the number of
     676             :    * elements you will add and call this method before repeatedly
     677             :    * calling \p add_point() the implementation will be more efficient.
     678             :    */
     679             :   virtual void reserve_elem (const dof_id_type ne) = 0;
     680             : 
     681             :   /**
     682             :    * Updates parallel caches so that methods like n_elem()
     683             :    * accurately reflect changes on other processors
     684             :    */
     685             :   virtual void update_parallel_id_counts () = 0;
     686             : 
     687             :   /**
     688             :    * \returns The number of active elements in the mesh.
     689             :    *
     690             :    * Implemented in terms of active_element_iterators.
     691             :    */
     692             :   virtual dof_id_type n_active_elem () const = 0;
     693             : 
     694             :   /**
     695             :    * \returns The number of elements on processor \p proc.
     696             :    */
     697             :   dof_id_type n_elem_on_proc (const processor_id_type proc) const;
     698             : 
     699             :   /**
     700             :    * \returns The number of elements on the local processor.
     701             :    */
     702         488 :   dof_id_type n_local_elem () const
     703     1909751 :   { return this->n_elem_on_proc (this->processor_id()); }
     704             : 
     705             :   /**
     706             :    * \returns The number of elements owned by no processor.
     707             :    */
     708       46776 :   dof_id_type n_unpartitioned_elem () const
     709     2556689 :   { return this->n_elem_on_proc (DofObject::invalid_processor_id); }
     710             : 
     711             :   /**
     712             :    * \returns The number of active elements on processor \p proc.
     713             :    */
     714             :   dof_id_type n_active_elem_on_proc (const processor_id_type proc) const;
     715             : 
     716             :   /**
     717             :    * \returns The number of active elements on the local processor.
     718             :    */
     719         216 :   dof_id_type n_active_local_elem () const
     720     1297926 :   { return this->n_active_elem_on_proc (this->processor_id()); }
     721             : 
     722             :   /**
     723             :    * \returns The number of elements that will be written
     724             :    * out in certain I/O formats.
     725             :    *
     726             :    * For example, a 9-noded quadrilateral will be broken into 4 linear
     727             :    * sub-elements for plotting purposes.  Thus, for a mesh of 2 \p
     728             :    * QUAD9 elements \p n_tecplot_elem() will return 8.  Implemented in
     729             :    * terms of element_iterators.
     730             :    */
     731             :   dof_id_type n_sub_elem () const;
     732             : 
     733             :   /**
     734             :    * Same as \p n_sub_elem(), but only counts active elements.
     735             :    */
     736             :   dof_id_type n_active_sub_elem () const;
     737             : 
     738             :   /**
     739             :    * \returns A constant reference (for reading only) to the
     740             :    * \f$ i^{th} \f$ point, which should be present in this processor's
     741             :    * subset of the mesh data structure.
     742             :    */
     743             :   virtual const Point & point (const dof_id_type i) const = 0;
     744             : 
     745             :   /**
     746             :    * \returns A constant reference (for reading only) to the
     747             :    * \f$ i^{th} \f$ node, which should be present in this processor's
     748             :    * subset of the mesh data structure.
     749             :    */
     750    59534081 :   virtual const Node & node_ref (const dof_id_type i) const
     751             :   {
     752    59534081 :     return *this->node_ptr(i);
     753             :   }
     754             : 
     755             :   /**
     756             :    * \returns A reference to the \f$ i^{th} \f$ node, which should be
     757             :    * present in this processor's subset of the mesh data structure.
     758             :    */
     759   504077080 :   virtual Node & node_ref (const dof_id_type i)
     760             :   {
     761   504077080 :     return *this->node_ptr(i);
     762             :   }
     763             : 
     764             :   /**
     765             :    * \returns A pointer to the \f$ i^{th} \f$ node, which should be
     766             :    * present in this processor's subset of the mesh data structure.
     767             :    */
     768             :   virtual const Node * node_ptr (const dof_id_type i) const = 0;
     769             : 
     770             :   /**
     771             :    * \returns A writable pointer to the \f$ i^{th} \f$ node, which
     772             :    * should be present in this processor's subset of the mesh data
     773             :    * structure.
     774             :    */
     775             :   virtual Node * node_ptr (const dof_id_type i) = 0;
     776             : 
     777             :   /**
     778             :    * \returns A pointer to the \f$ i^{th} \f$ node, or \p nullptr if no such
     779             :    * node exists in this processor's mesh data structure.
     780             :    */
     781             :   virtual const Node * query_node_ptr (const dof_id_type i) const = 0;
     782             : 
     783             :   /**
     784             :    * \returns A writable pointer to the \f$ i^{th} \f$ node, or \p nullptr if
     785             :    * no such node exists in this processor's mesh data structure.
     786             :    */
     787             :   virtual Node * query_node_ptr (const dof_id_type i) = 0;
     788             : 
     789             :   /**
     790             :    * \returns A reference to the \f$ i^{th} \f$ element, which should be
     791             :    * present in this processor's subset of the mesh data structure.
     792             :    */
     793     5295762 :   virtual const Elem & elem_ref (const dof_id_type i) const
     794             :   {
     795     5295762 :     return *this->elem_ptr(i);
     796             :   }
     797             : 
     798             :   /**
     799             :    * \returns A writable reference to the \f$ i^{th} \f$ element, which
     800             :    * should be present in this processor's subset of the mesh data
     801             :    * structure.
     802             :    */
     803   304560150 :   virtual Elem & elem_ref (const dof_id_type i)
     804             :   {
     805   304560150 :     return *this->elem_ptr(i);
     806             :   }
     807             : 
     808             :   /**
     809             :    * \returns A pointer to the \f$ i^{th} \f$ element, which should be
     810             :    * present in this processor's subset of the mesh data structure.
     811             :    */
     812             :   virtual const Elem * elem_ptr (const dof_id_type i) const = 0;
     813             : 
     814             :   /**
     815             :    * \returns A writable pointer to the \f$ i^{th} \f$ element, which
     816             :    * should be present in this processor's subset of the mesh data
     817             :    * structure.
     818             :    */
     819             :   virtual Elem * elem_ptr (const dof_id_type i) = 0;
     820             : 
     821             :   /**
     822             :    * \returns A pointer to the \f$ i^{th} \f$ element, or nullptr if no
     823             :    * such element exists in this processor's mesh data structure.
     824             :    */
     825             :   virtual const Elem * query_elem_ptr (const dof_id_type i) const = 0;
     826             : 
     827             :   /**
     828             :    * \returns A writable pointer to the \f$ i^{th} \f$ element, or nullptr
     829             :    * if no such element exists in this processor's mesh data structure.
     830             :    */
     831             :   virtual Elem * query_elem_ptr (const dof_id_type i) = 0;
     832             : 
     833             :   /**
     834             :    * Add a new \p Node at \p Point \p p to the end of the vertex array,
     835             :    * with processor_id \p procid.
     836             :    * Use DofObject::invalid_processor_id (default) to add a node to all
     837             :    * processors, or this->processor_id() to add a node to the local
     838             :    * processor only.
     839             :    * If adding a node locally, passing an \p id other than
     840             :    * DofObject::invalid_id will set that specific node id.  Only
     841             :    * do this in parallel if you are manually keeping ids consistent.
     842             :    */
     843             :   virtual Node * add_point (const Point & p,
     844             :                             const dof_id_type id = DofObject::invalid_id,
     845             :                             const processor_id_type proc_id =
     846             :                             DofObject::invalid_processor_id) = 0;
     847             : 
     848             :   /**
     849             :    * Add \p Node \p n to the end of the vertex array.
     850             :    */
     851             :   virtual Node * add_node (Node * n) = 0;
     852             : 
     853             :   /**
     854             :    * Version of add_node() taking a std::unique_ptr by value. The version
     855             :    * taking a dumb pointer will eventually be deprecated in favor of this
     856             :    * version. This API is intended to indicate that ownership of the Node
     857             :    * is transferred to the Mesh when this function is called, and it should
     858             :    * play more nicely with the Node::build() API which has always returned
     859             :    * a std::unique_ptr.
     860             :    */
     861             :   virtual Node * add_node (std::unique_ptr<Node> n) = 0;
     862             : 
     863             :   /**
     864             :    * Removes the Node n from the mesh.
     865             :    */
     866             :   virtual void delete_node (Node * n) = 0;
     867             : 
     868             :   /**
     869             :    * Takes ownership of node \p n on this partition of a distributed
     870             :    * mesh, by setting n.processor_id() to this->processor_id(), as
     871             :    * well as changing n.id() and moving it in the mesh's internal
     872             :    * container to give it a new authoritative id.
     873             :    */
     874           0 :   virtual void own_node (Node &) {}
     875             : 
     876             :   /**
     877             :    * Changes the id of node \p old_id, both by changing node(old_id)->id() and
     878             :    * by moving node(old_id) in the mesh's internal container.  No element with
     879             :    * the id \p new_id should already exist.
     880             :    */
     881             :   virtual void renumber_node (dof_id_type old_id, dof_id_type new_id) = 0;
     882             : 
     883             :   /**
     884             :    * Add elem \p e to the end of the element array.
     885             :    * To add an element locally, set e->processor_id() before adding it.
     886             :    * To ensure a specific element id, call e->set_id() before adding it;
     887             :    * only do this in parallel if you are manually keeping ids consistent.
     888             :    *
     889             :    * Users should call MeshBase::complete_preparation() after elements are
     890             :    * added to and/or deleted from the mesh.
     891             :    */
     892             :   virtual Elem * add_elem (Elem * e) = 0;
     893             : 
     894             :   /**
     895             :    * Version of add_elem() taking a std::unique_ptr by value. The version
     896             :    * taking a dumb pointer will eventually be deprecated in favor of this
     897             :    * version. This API is intended to indicate that ownership of the Elem
     898             :    * is transferred to the Mesh when this function is called, and it should
     899             :    * play more nicely with the Elem::build() API which has always returned
     900             :    * a std::unique_ptr.
     901             :    */
     902             :   virtual Elem * add_elem (std::unique_ptr<Elem> e) = 0;
     903             : 
     904             :   /**
     905             :    * Insert elem \p e to the element array, preserving its id
     906             :    * and replacing/deleting any existing element with the same id.
     907             :    *
     908             :    * Users should call MeshBase::complete_preparation() after elements are
     909             :    * added to and/or deleted from the mesh.
     910             :    */
     911             :   virtual Elem * insert_elem (Elem * e) = 0;
     912             : 
     913             :   /**
     914             :    * Version of insert_elem() taking a std::unique_ptr by value. The version
     915             :    * taking a dumb pointer will eventually be deprecated in favor of this
     916             :    * version. This API is intended to indicate that ownership of the Elem
     917             :    * is transferred to the Mesh when this function is called, and it should
     918             :    * play more nicely with the Elem::build() API which has always returned
     919             :    * a std::unique_ptr.
     920             :    */
     921             :   virtual Elem * insert_elem (std::unique_ptr<Elem> e) = 0;
     922             : 
     923             :   /**
     924             :    * Removes element \p e from the mesh. This method must be
     925             :    * implemented in derived classes in such a way that it does not
     926             :    * invalidate element iterators.  Users should call
     927             :    * MeshBase::complete_preparation() after elements are added to
     928             :    * and/or deleted from the mesh.
     929             :    *
     930             :    * \note Calling this method may produce isolated nodes, i.e. nodes
     931             :    * not connected to any element.
     932             :    */
     933             :   virtual void delete_elem (Elem * e) = 0;
     934             : 
     935             :   /**
     936             :    * Changes the id of element \p old_id, both by changing elem(old_id)->id()
     937             :    * and by moving elem(old_id) in the mesh's internal container.  No element
     938             :    * with the id \p new_id should already exist.
     939             :    */
     940             :   virtual void renumber_elem (dof_id_type old_id, dof_id_type new_id) = 0;
     941             : 
     942             :   /**
     943             :    * Returns the default master space to physical space mapping basis
     944             :    * functions to be used on newly added elements.
     945             :    */
     946     1840127 :   ElemMappingType default_mapping_type () const
     947             :   {
     948    59456385 :     return _default_mapping_type;
     949             :   }
     950             : 
     951             :   /**
     952             :    * Set the default master space to physical space mapping basis
     953             :    * functions to be used on newly added elements.
     954             :    */
     955          44 :   void set_default_mapping_type (const ElemMappingType type)
     956             :   {
     957       16029 :     _default_mapping_type = type;
     958          44 :   }
     959             : 
     960             :   /**
     961             :    * Returns any default data value used by the master space to
     962             :    * physical space mapping.
     963             :    */
     964     1840127 :   unsigned char default_mapping_data () const
     965             :   {
     966    59456385 :     return _default_mapping_data;
     967             :   }
     968             : 
     969             :   /**
     970             :    * Set the default master space to physical space mapping basis
     971             :    * functions to be used on newly added elements.
     972             :    */
     973          44 :   void set_default_mapping_data (const unsigned char data)
     974             :   {
     975       16029 :     _default_mapping_data = data;
     976          44 :   }
     977             : 
     978             :   /**
     979             :    * Locate element face (edge in 2D) neighbors.  This is done with the help
     980             :    * of a \p std::map that functions like a hash table.
     981             :    * After this routine is called all the elements with a \p nullptr neighbor
     982             :    * pointer are guaranteed to be on the boundary.  Thus this routine is
     983             :    * useful for automatically determining the boundaries of the domain.
     984             :    *
     985             :    * If \p reset_remote_elements is left to false, remote neighbor
     986             :    * links are not reset and searched for in the local mesh.
     987             :    *
     988             :    * If \p reset_current_list is left as true, then any existing links
     989             :    * will be reset before initiating the algorithm, while honoring the
     990             :    * value of the \p reset_remote_elements flag.
     991             :    *
     992             :    * If \p assert_valid is left as true, then in dbg mode extensive
     993             :    * consistency checking is performed before returning.
     994             :    *
     995             :    * If \p check_non_remote is set to false, then only sides which
     996             :    * currently have remote neighbors are checked for possible local
     997             :    * neighbors.  This is intended to handle a corner case where
     998             :    * ancestor neighbors are redistributed to a processor only by other
     999             :    * processors who do not see that neighbor link.
    1000             :    */
    1001             :   virtual void find_neighbors (const bool reset_remote_elements = false,
    1002             :                                const bool reset_current_list    = true,
    1003             :                                const bool assert_valid          = true,
    1004             :                                const bool check_non_remote      = true) = 0;
    1005             : 
    1006             :   /**
    1007             :    * Removes any orphaned nodes, nodes not connected to any elements.
    1008             :    * Typically done automatically in a preparation step
    1009             :    */
    1010             :   void remove_orphaned_nodes ();
    1011             : 
    1012             :   /**
    1013             :    * After partitioning a mesh it is useful to renumber the nodes and elements
    1014             :    * so that they lie in contiguous blocks on the processors.  This method
    1015             :    * does just that.
    1016             :    */
    1017             :   virtual void renumber_nodes_and_elements () = 0;
    1018             : 
    1019             :   /**
    1020             :    * There is no reason for a user to ever call this function.
    1021             :    *
    1022             :    * This function restores a previously broken element/node numbering such that
    1023             :    * \p mesh.node_ref(n).id() == n.
    1024             :    */
    1025             :   virtual void fix_broken_node_and_element_numbering () = 0;
    1026             : 
    1027             : 
    1028             : #ifdef LIBMESH_ENABLE_AMR
    1029             :   /**
    1030             :    * Delete subactive (i.e. children of coarsened) elements.
    1031             :    * This removes all elements descended from currently active
    1032             :    * elements in the mesh.
    1033             :    */
    1034             :   virtual bool contract () = 0;
    1035             : #endif
    1036             : 
    1037             :   /**
    1038             :    * Register an integer datum (of type dof_id_type) to be added to
    1039             :    * each element in the mesh.
    1040             :    *
    1041             :    * If the mesh already has elements, data by default is allocated in
    1042             :    * each of them.  This may be expensive to do repeatedly; use
    1043             :    * add_elem_integers instead.  Alternatively, the \p allocate_data
    1044             :    * option can be manually set to false, but if this is done then a
    1045             :    * manual call to \p size_elem_extra_integers() will need to be done
    1046             :    * before the new space is usable.
    1047             :    *
    1048             :    * Newly allocated values for the new datum will be initialized to
    1049             :    * \p default_value
    1050             :    *
    1051             :    * \returns The index number for the new datum, or for the existing
    1052             :    * datum if one by the same name has already been added.
    1053             :    */
    1054             :   unsigned int add_elem_integer(std::string name,
    1055             :                                 bool allocate_data = true,
    1056             :                                 dof_id_type default_value = DofObject::invalid_id);
    1057             : 
    1058             :   /**
    1059             :    * Register integer data (of type dof_id_type) to be added to
    1060             :    * each element in the mesh, one string name for each new integer.
    1061             :    *
    1062             :    * If the mesh already has elements, data by default is allocated in
    1063             :    * each of them.
    1064             :    *
    1065             :    * Newly allocated values for the new datum with name \p names[i]
    1066             :    * will be initialized to \p default_values[i], or to
    1067             :    * DofObject::invalid_id if \p default_values is null.
    1068             :    *
    1069             :    * \returns The index numbers for the new data, and/or for existing
    1070             :    * data if data by some of the same names has already been added.
    1071             :    */
    1072             :   std::vector<unsigned int> add_elem_integers(const std::vector<std::string> & names,
    1073             :                                               bool allocate_data = true,
    1074             :                                               const std::vector<dof_id_type> * default_values = nullptr);
    1075             : 
    1076             :   /*
    1077             :    * \returns The index number for the named extra element integer
    1078             :    * datum, which must have already been added.
    1079             :    */
    1080             :   unsigned int get_elem_integer_index(std::string_view name) const;
    1081             : 
    1082             :   /*
    1083             :    * \returns Whether or not the mesh has an element integer with its name.
    1084             :    */
    1085             :   bool has_elem_integer(std::string_view name) const;
    1086             : 
    1087             :   /*
    1088             :    * \returns The name for the indexed extra element integer
    1089             :    * datum, which must have already been added.
    1090             :    */
    1091          19 :   const std::string & get_elem_integer_name(unsigned int i) const
    1092          38 :   { return _elem_integer_names[i]; }
    1093             : 
    1094             :   /*
    1095             :    * \returns The number of extra element integers for which space is
    1096             :    * being reserved on this mesh.
    1097             :    *
    1098             :    * If non-integer data has been associated, each datum of type T
    1099             :    * counts for sizeof(T)/sizeof(dof_id_type) times in the return
    1100             :    * value.
    1101             :    */
    1102         816 :   unsigned int n_elem_integers() const { return _elem_integer_names.size(); }
    1103             : 
    1104             :   /**
    1105             :    * Register a datum (of type T) to be added to each element in the
    1106             :    * mesh.
    1107             :    *
    1108             :    * If the mesh already has elements, data by default is allocated in
    1109             :    * each of them.  This may be expensive to do repeatedly; use
    1110             :    * add_elem_data instead.  Alternatively, the \p allocate_data
    1111             :    * option can be manually set to false, but if this is done then a
    1112             :    * manual call to \p size_elem_extra_integers() will need to be done
    1113             :    * before the new space is usable.
    1114             :    *
    1115             :    * Newly allocated values for the new datum will be initialized to
    1116             :    * \p *default_value if \p default_value is not null, or to
    1117             :    * meaningless memcpy output otherwise.
    1118             :    *
    1119             :    * \returns The index numbers for the new data, and/or for existing
    1120             :    * data if data by some of the same names has already been added.
    1121             :    *
    1122             :    * If type T is larger than dof_id_type, its data will end up
    1123             :    * spanning multiple index values, but will be queried with the
    1124             :    * starting index number.
    1125             :    *
    1126             :    * No type checking is done with this function!  If you add data of
    1127             :    * type T, don't try to access it with a call specifying type U.
    1128             :    */
    1129             :   template <typename T>
    1130             :   unsigned int add_elem_datum(const std::string & name,
    1131             :                               bool allocate_data = true,
    1132             :                               const T * default_value = nullptr);
    1133             : 
    1134             :   /**
    1135             :    * Register data (of type T) to be added to each element in the
    1136             :    * mesh.
    1137             :    *
    1138             :    * If the mesh already has elements, data is allocated in each.
    1139             :    *
    1140             :    * Newly allocated values for the new datum with name \p names[i]
    1141             :    * will be initialized to \p default_values[i], or to
    1142             :    * meaningless memcpy output if \p default_values is null.
    1143             :    *
    1144             :    * \returns The starting index number for the new data, or for the
    1145             :    * existing data if one by the same name has already been added.
    1146             :    *
    1147             :    * If type T is larger than dof_id_type, each datum will end up
    1148             :    * spanning multiple index values, but will be queried with the
    1149             :    * starting index number.
    1150             :    *
    1151             :    * No type checking is done with this function!  If you add data of
    1152             :    * type T, don't try to access it with a call specifying type U.
    1153             :    */
    1154             :   template <typename T>
    1155             :   std::vector<unsigned int> add_elem_data(const std::vector<std::string> & names,
    1156             :                                           bool allocate_data = true,
    1157             :                                           const std::vector<T> * default_values = nullptr);
    1158             : 
    1159             :   /**
    1160             :    * Register an integer datum (of type dof_id_type) to be added to
    1161             :    * each node in the mesh.
    1162             :    *
    1163             :    * If the mesh already has nodes, data by default is allocated in
    1164             :    * each of them.  This may be expensive to do repeatedly; use
    1165             :    * add_node_integers instead.  Alternatively, the \p allocate_data
    1166             :    * option can be manually set to false, but if this is done then a
    1167             :    * manual call to \p size_node_extra_integers() will need to be done
    1168             :    * before the new space is usable.
    1169             :    *
    1170             :    * Newly allocated values for the new datum will be initialized to
    1171             :    * \p default_value
    1172             :    *
    1173             :    * \returns The index number for the new datum, or for the existing
    1174             :    * datum if one by the same name has already been added.
    1175             :    */
    1176             :   unsigned int add_node_integer(std::string name,
    1177             :                                 bool allocate_data = true,
    1178             :                                 dof_id_type default_value = DofObject::invalid_id);
    1179             : 
    1180             :   /**
    1181             :    * Register integer data (of type dof_id_type) to be added to
    1182             :    * each node in the mesh.
    1183             :    *
    1184             :    * If the mesh already has nodes, data by default is allocated in
    1185             :    * each.
    1186             :    *
    1187             :    * Newly allocated values for the new datum with name \p names[i]
    1188             :    * will be initialized to \p default_values[i], or to
    1189             :    * DofObject::invalid_id if \p default_values is null.
    1190             :    *
    1191             :    * \returns The index numbers for the new data, and/or for existing
    1192             :    * data if data by some of the same names has already been added.
    1193             :    */
    1194             :   std::vector<unsigned int> add_node_integers(const std::vector<std::string> & names,
    1195             :                                               bool allocate_data = true,
    1196             :                                               const std::vector<dof_id_type> * default_values = nullptr);
    1197             : 
    1198             :   /*
    1199             :    * \returns The index number for the named extra node integer
    1200             :    * datum, which must have already been added.
    1201             :    */
    1202             :   unsigned int get_node_integer_index(std::string_view name) const;
    1203             : 
    1204             :   /*
    1205             :    * \returns Whether or not the mesh has a node integer with its name.
    1206             :    */
    1207             :   bool has_node_integer(std::string_view name) const;
    1208             : 
    1209             :   /*
    1210             :    * \returns The name for the indexed extra node integer
    1211             :    * datum, which must have already been added.
    1212             :    */
    1213          36 :   const std::string & get_node_integer_name(unsigned int i) const
    1214          72 :   { return _node_integer_names[i]; }
    1215             : 
    1216             :   /*
    1217             :    * \returns The number of extra node integers for which space is
    1218             :    * being reserved on this mesh.
    1219             :    *
    1220             :    * If non-integer data has been associated, each datum of type T
    1221             :    * counts for sizeof(T)/sizeof(dof_id_type) times in the return
    1222             :    * value.
    1223             :    */
    1224         816 :   unsigned int n_node_integers() const { return _node_integer_names.size(); }
    1225             : 
    1226             :   /**
    1227             :    * Register a datum (of type T) to be added to each node in the
    1228             :    * mesh.
    1229             :    *
    1230             :    * If the mesh already has nodes, data by default is allocated in
    1231             :    * each of them.  This may be expensive to do repeatedly; use
    1232             :    * add_node_data instead.  Alternatively, the \p allocate_data
    1233             :    * option can be manually set to false, but if this is done then a
    1234             :    * manual call to \p size_node_extra_integers() will need to be done
    1235             :    * before the new space is usable.
    1236             :    *
    1237             :    * Newly allocated values for the new datum will be initialized to
    1238             :    * \p *default_value if \p default_value is not null, or to
    1239             :    * meaningless memcpy output otherwise.
    1240             :    *
    1241             :    * \returns The starting index number for the new datum, or for the
    1242             :    * existing datum if one by the same name has already been added.
    1243             :    *
    1244             :    * If type T is larger than dof_id_type, its data will end up
    1245             :    * spanning multiple index values, but will be queried with the
    1246             :    * starting index number.
    1247             :    *
    1248             :    * No type checking is done with this function!  If you add data of
    1249             :    * type T, don't try to access it with a call specifying type U.
    1250             :    */
    1251             :   template <typename T>
    1252             :   unsigned int add_node_datum(const std::string & name,
    1253             :                               bool allocate_data = true,
    1254             :                               const T * default_value = nullptr);
    1255             : 
    1256             :   /**
    1257             :    * Register data (of type T) to be added to each node in the
    1258             :    * mesh.
    1259             :    *
    1260             :    * If the mesh already has nodes, data by default is allocated in each.
    1261             :    *
    1262             :    * Newly allocated values for the new datum with name \p names[i]
    1263             :    * will be initialized to \p default_values[i], or to
    1264             :    * meaningless memcpy output if \p default_values is null.
    1265             :    *
    1266             :    * \returns The starting index number for the new data, or for the
    1267             :    * existing data if one by the same name has already been added.
    1268             :    *
    1269             :    * If type T is larger than dof_id_type, its data will end up
    1270             :    * spanning multiple index values, but will be queried with the
    1271             :    * starting index number.
    1272             :    *
    1273             :    * No type checking is done with this function!  If you add data of
    1274             :    * type T, don't try to access it with a call specifying type U.
    1275             :    */
    1276             :   template <typename T>
    1277             :   std::vector<unsigned int> add_node_data(const std::vector<std::string> & name,
    1278             :                                           bool allocate_data = true,
    1279             :                                           const std::vector<T> * default_values = nullptr);
    1280             : 
    1281             :   /**
    1282             :    * Prepare a newly created (or read) mesh for use.
    1283             :    * This involves several steps:
    1284             :    *  1.) renumbering (if enabled)
    1285             :    *  2.) removing any orphaned nodes
    1286             :    *  3.) updating parallel id counts
    1287             :    *  4.) finding neighbor links
    1288             :    *  5.) caching summarized element data
    1289             :    *  6.) finding interior parent links
    1290             :    *  7.) clearing any old point locator
    1291             :    *  8.) calling reinit() on ghosting functors
    1292             :    *  9.) repartitioning (if enabled)
    1293             :    *  10.) removing any remote elements (if enabled)
    1294             :    *  11.) regenerating summarized boundary id sets
    1295             :    *
    1296             :    * For backwards compatibility, prepare_for_use() performs *all* those
    1297             :    * steps, regardless of the official preparation() state of the
    1298             :    * mesh.  In codes which have maintained a valid preparation() state
    1299             :    * via methods such as unset_has_synched_id_counts(), calling
    1300             :    * complete_preparation() will result in a fully-prepared mesh at
    1301             :    * less cost.
    1302             :    *
    1303             :    * The argument to skip renumbering is now deprecated - to prevent a
    1304             :    * mesh from being renumbered, set allow_renumbering(false). The argument to skip
    1305             :    * finding neighbors is also deprecated. To prevent find_neighbors, set
    1306             :    * allow_find_neighbors(false)
    1307             :    *
    1308             :    * If this is a distributed mesh, local copies of remote elements
    1309             :    * will be deleted here - to keep those elements replicated during
    1310             :    * preparation, set allow_remote_element_removal(false).
    1311             :    */
    1312             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1313             :   void prepare_for_use (const bool skip_renumber_nodes_and_elements, const bool skip_find_neighbors);
    1314             :   void prepare_for_use (const bool skip_renumber_nodes_and_elements);
    1315             : #endif // LIBMESH_ENABLE_DEPRECATED
    1316             :   void prepare_for_use ();
    1317             : 
    1318             :   /*
    1319             :    * Prepare a newly created or modified mesh for use.
    1320             :    *
    1321             :    * Unlike \p prepare_for_use(), \p complete_preparation() performs
    1322             :    * *only* those preparatory steps that have been marked as
    1323             :    * necessary in the MeshBase::Preparation state.
    1324             :    */
    1325             :   void complete_preparation();
    1326             : 
    1327             :   /**
    1328             :    * Call the default partitioner (currently \p metis_partition()).
    1329             :    */
    1330             :   virtual void partition (const unsigned int n_parts);
    1331             : 
    1332        2018 :   void partition ()
    1333      434536 :   { this->partition(this->n_processors()); }
    1334             : 
    1335             :   /**
    1336             :    * Redistribute elements between processors.  This gets called
    1337             :    * automatically by the Partitioner, and merely notifies any
    1338             :    * GhostingFunctors of redistribution in the case of a
    1339             :    * ReplicatedMesh or serialized DistributedMesh
    1340             :    */
    1341             :   virtual void redistribute ();
    1342             : 
    1343             :   /**
    1344             :    * Recalculate any cached data (or invalidate any caches that are
    1345             :    * computed on the fly) after elements and nodes have been
    1346             :    * repartitioned.
    1347             :    */
    1348             :   virtual void update_post_partitioning ();
    1349             : 
    1350             :   /**
    1351             :    * If false is passed in then this mesh will no longer be renumbered
    1352             :    * when being prepared for use.  This may slightly adversely affect
    1353             :    * performance during subsequent element access, particularly when
    1354             :    * using a distributed mesh.
    1355             :    *
    1356             :    * Important! When allow_renumbering(false) is set,
    1357             :    * ReplicatedMesh::n_elem() and ReplicatedMesh::n_nodes() will
    1358             :    * return *wrong* values whenever adaptive refinement is followed by
    1359             :    * adaptive coarsening. (Uniform refinement followed by uniform
    1360             :    * coarsening is OK.) This is due to the fact that n_elem() and
    1361             :    * n_nodes() are currently O(1) functions that just return the size
    1362             :    * of the respective underlying vectors, and this size is wrong when
    1363             :    * the numbering includes "gaps" from nodes and elements that have
    1364             :    * been deleted. We plan to implement a caching mechanism in the
    1365             :    * near future that will fix this incorrect behavior.
    1366             :    */
    1367       79450 :   void allow_renumbering(bool allow) { _skip_renumber_nodes_and_elements = !allow; }
    1368       72851 :   bool allow_renumbering() const { return !_skip_renumber_nodes_and_elements; }
    1369             : 
    1370             :   /**
    1371             :    * If \p false is passed then this mesh will no longer work to find element
    1372             :    * neighbors when being prepared for use
    1373             :    */
    1374       84109 :   void allow_find_neighbors(bool allow) { _skip_find_neighbors = !allow; }
    1375      183711 :   bool allow_find_neighbors() const { return !_skip_find_neighbors; }
    1376             : 
    1377             :   /**
    1378             :    * If \p false is passed then this mesh will no longer work to detect
    1379             :    * interior parents when being prepared for use
    1380             :    */
    1381       42700 :   void allow_detect_interior_parents(bool allow) { _skip_detect_interior_parents = !allow; }
    1382       41928 :   bool allow_detect_interior_parents() const { return !_skip_detect_interior_parents; }
    1383             : 
    1384             :   /**
    1385             :    * If false is passed in then this mesh will no longer have remote
    1386             :    * elements deleted when being prepared for use; i.e. even a
    1387             :    * DistributedMesh will remain (if it is already) serialized.
    1388             :    * This may adversely affect performance and memory use.
    1389             :    */
    1390      731113 :   void allow_remote_element_removal(bool allow) { _allow_remote_element_removal = allow; }
    1391      434285 :   bool allow_remote_element_removal() const { return _allow_remote_element_removal; }
    1392             : 
    1393             :   /**
    1394             :    * If \p true is passed, then this mesh will no longer require
    1395             :    * unique_ids to be unique across the set of all DofObjects. That
    1396             :    * is, although no two Elems (resp. Nodes) will share the same
    1397             :    * unique_id, a given Elem and Node might share the same unique_id.
    1398             :    */
    1399         142 :   void allow_node_and_elem_unique_id_overlap(bool allow) { _allow_node_and_elem_unique_id_overlap = allow; }
    1400       62618 :   bool allow_node_and_elem_unique_id_overlap() const { return _allow_node_and_elem_unique_id_overlap; }
    1401             : 
    1402             :   /**
    1403             :    * If true is passed in then the elements on this mesh will no
    1404             :    * longer be (re)partitioned, and the nodes on this mesh will only
    1405             :    * be repartitioned if they are found "orphaned" via coarsening or
    1406             :    * other removal of the last element responsible for their
    1407             :    * node/element processor id consistency.
    1408             :    *
    1409             :    * \note It would probably be a bad idea to call this on a
    1410             :    * DistributedMesh _before_ the first partitioning has happened...
    1411             :    * because no elements would get assigned to your processor pool.
    1412             :    *
    1413             :    * \note Skipping partitioning can have adverse effects on your
    1414             :    * performance when using AMR... i.e. you could get large load
    1415             :    * imbalances.  However you might still want to use this if the
    1416             :    * communication and computation of the rebalance and repartition is
    1417             :    * too high for your application.
    1418             :    *
    1419             :    * It is also possible, for backwards-compatibility purposes, to
    1420             :    * skip noncritical partitioning by resetting the partitioner()
    1421             :    * pointer for this mesh.
    1422             :    */
    1423             :   void skip_noncritical_partitioning(bool skip)
    1424             :   { _skip_noncritical_partitioning = skip; }
    1425             : 
    1426        3760 :   bool skip_noncritical_partitioning() const
    1427      155500 :   { return _skip_noncritical_partitioning || _skip_all_partitioning || !_partitioner.get(); }
    1428             : 
    1429             : 
    1430             :   /**
    1431             :    * If true is passed in then nothing on this mesh will be
    1432             :    * (re)partitioned.
    1433             :    *
    1434             :    * \note The caveats for skip_noncritical_partitioning() still
    1435             :    * apply, and removing elements from a mesh with this setting
    1436             :    * enabled can leave node processor ids in an inconsistent state
    1437             :    * (not matching any attached element), causing failures in other
    1438             :    * library code.  Do not use this setting along with element
    1439             :    * deletion or coarsening.
    1440             :    */
    1441       34921 :   void skip_partitioning(bool skip) { _skip_all_partitioning = skip; }
    1442             : 
    1443      711334 :   bool skip_partitioning() const { return _skip_all_partitioning; }
    1444             : 
    1445             :   /**
    1446             :    * Adds a functor which can specify ghosting requirements for use on
    1447             :    * distributed meshes.  Multiple ghosting functors can be added; any
    1448             :    * element which is required by any functor will be ghosted.
    1449             :    *
    1450             :    * GhostingFunctor memory must be managed by the code which calls
    1451             :    * this function; the GhostingFunctor lifetime is expected to extend
    1452             :    * until either the functor is removed or the Mesh is destructed.
    1453             :    */
    1454             :   void add_ghosting_functor(GhostingFunctor & ghosting_functor);
    1455             : 
    1456             :   /**
    1457             :    * Adds a functor which can specify ghosting requirements for use on
    1458             :    * distributed meshes.  Multiple ghosting functors can be added; any
    1459             :    * element which is required by any functor will be ghosted.
    1460             :    *
    1461             :    * GhostingFunctor memory when using this method is managed by the
    1462             :    * shared_ptr mechanism.
    1463             :    */
    1464       33366 :   void add_ghosting_functor(std::shared_ptr<GhostingFunctor> ghosting_functor)
    1465       63034 :   { _shared_functors[ghosting_functor.get()] = ghosting_functor;
    1466       33366 :     this->add_ghosting_functor(*ghosting_functor); }
    1467             : 
    1468             :   /**
    1469             :    * Removes a functor which was previously added to the set of
    1470             :    * ghosting functors.
    1471             :    */
    1472             :   void remove_ghosting_functor(GhostingFunctor & ghosting_functor);
    1473             : 
    1474             :   /**
    1475             :    * Iterator type for ghosting functor ranges.  This has changed in
    1476             :    * the past and may change again; code should use auto or the type
    1477             :    * here.
    1478             :    */
    1479             :   typedef std::vector<GhostingFunctor *>::const_iterator GhostingFunctorIterator;
    1480             : 
    1481             :   /**
    1482             :    * Beginning of range of ghosting functors
    1483             :    */
    1484        2662 :   GhostingFunctorIterator ghosting_functors_begin() const
    1485       17657 :   { return _ghosting_functors.begin(); }
    1486             : 
    1487             :   /**
    1488             :    * End of range of ghosting functors
    1489             :    */
    1490        2662 :   GhostingFunctorIterator ghosting_functors_end() const
    1491       17657 :   { return _ghosting_functors.end(); }
    1492             : 
    1493             :   /**
    1494             :    * Default ghosting functor
    1495             :    */
    1496           6 :   GhostingFunctor & default_ghosting() { return *_default_ghosting; }
    1497             : 
    1498             :   /**
    1499             :    * Constructs a list of all subdomain identifiers in the local mesh if
    1500             :    * \p global == false, and in the global mesh if \p global == true (default).
    1501             :    * Subdomains correspond to separate subsets of the mesh which could correspond
    1502             :    * e.g. to different materials in a solid mechanics application,
    1503             :    * or regions where different physical processes are important.  The subdomain
    1504             :    * mapping is independent from the parallel decomposition.
    1505             :    *
    1506             :    * Unpartitioned elements are included in the set in the case that \p
    1507             :    * global == true. If \p global == false, the unpartitioned elements are not
    1508             :    * included because unpartitioned elements do not have a sense of locality.
    1509             :    */
    1510             :   void subdomain_ids (std::set<subdomain_id_type> & ids, const bool global = true) const;
    1511             : 
    1512             :   /**
    1513             :    * \returns The number of subdomains in the global mesh. Subdomains correspond
    1514             :    * to separate subsets of the mesh which could correspond e.g. to different
    1515             :    * materials in a solid mechanics application, or regions where different
    1516             :    * physical processes are important.  The subdomain mapping is independent
    1517             :    * from the parallel decomposition.
    1518             :    */
    1519             :   subdomain_id_type n_subdomains () const;
    1520             : 
    1521             :   /**
    1522             :    * \returns The number of subdomains in the local mesh. Subdomains correspond
    1523             :    * to separate subsets of the mesh which could correspond e.g. to different
    1524             :    * materials in a solid mechanics application, or regions where different
    1525             :    * physical processes are important.  The subdomain mapping is independent
    1526             :    * from the parallel decomposition.
    1527             :    */
    1528             :   subdomain_id_type n_local_subdomains () const;
    1529             : 
    1530             :   /**
    1531             :    * \returns The number of partitions which have been defined via
    1532             :    * a call to either mesh.partition() or by building a Partitioner
    1533             :    * object and calling partition.
    1534             :    *
    1535             :    * \note The partitioner object is responsible for setting this
    1536             :    * value.
    1537             :    */
    1538        8612 :   unsigned int n_partitions () const
    1539       58236 :   { return _n_parts; }
    1540             : 
    1541             :   /**
    1542             :    * \returns A string containing relevant information
    1543             :    * about the mesh.
    1544             :    *
    1545             :    * \p verbosity sets the verbosity, with 0 being the least and 2 being the greatest.
    1546             :    * 0 - Dimensions, number of nodes, number of elems, number of subdomains, number of
    1547             :    *     partitions, prepared status.
    1548             :    * 1 - Adds the mesh bounding box, mesh element types, specific nodesets/edgesets/sidesets
    1549             :    *     with element types, number of nodes/edges/sides.
    1550             :    * 2 - Adds volume information and bounding boxes to boundary information.
    1551             :    *
    1552             :    * The \p global parameter pertains primarily to verbosity levels 1 and above.
    1553             :    * When \p global == true, information is only output on rank 0 and the information
    1554             :    * is reduced. When \p global == false, information is output on all ranks that pertains
    1555             :    * only to that local partition.
    1556             :    */
    1557             :   std::string get_info (const unsigned int verbosity = 0, const bool global = true) const;
    1558             : 
    1559             :   /**
    1560             :    * Prints relevant information about the mesh.
    1561             :    *
    1562             :    * Take note of the docstring for get_info() for more information pretaining to
    1563             :    * the \p verbosity and \p global parameters.
    1564             :    */
    1565             :   void print_info (std::ostream & os=libMesh::out, const unsigned int verbosity = 0, const bool global = true) const;
    1566             : 
    1567             :   /**
    1568             :    * Equivalent to calling print_info() above, but now you can write:
    1569             :    * Mesh mesh;
    1570             :    * libMesh::out << mesh << std::endl;
    1571             :    */
    1572             :   friend std::ostream & operator << (std::ostream & os, const MeshBase & m);
    1573             : 
    1574             :   /**
    1575             :    * Interfaces for reading/writing a mesh to/from a file.  Must be
    1576             :    * implemented in derived classes.
    1577             :    */
    1578             :   virtual void read  (const std::string & name,
    1579             :                       void * mesh_data=nullptr,
    1580             :                       bool skip_renumber_nodes_and_elements=false,
    1581             :                       bool skip_find_neighbors=false,
    1582             :                       bool skip_detect_interior_parents=false) = 0;
    1583             :   virtual void write (const std::string & name) const = 0;
    1584             : 
    1585             :   /**
    1586             :    * Converts a mesh with higher-order
    1587             :    * elements into a mesh with linear elements.  For
    1588             :    * example, a mesh consisting of \p Tet10 will be converted
    1589             :    * to a mesh with \p Tet4 etc.
    1590             :    */
    1591             :   virtual void all_first_order () = 0;
    1592             : 
    1593             :   /**
    1594             :    * We need an empty, generic class to act as a predicate for this
    1595             :    * and derived mesh classes.
    1596             :    */
    1597             :   typedef Predicates::multi_predicate Predicate;
    1598             : 
    1599             :   /**
    1600             :    * structs for the element_iterator's.
    1601             :    *
    1602             :    * \note These iterators were designed so that derived mesh classes
    1603             :    * could use the _same_ base class iterators interchangeably.  Their
    1604             :    * definition comes later in the header file.
    1605             :    */
    1606             :   struct element_iterator;
    1607             :   struct const_element_iterator;
    1608             : 
    1609             :   /**
    1610             :    * structs for the node_iterator's.
    1611             :    *
    1612             :    * \note These iterators were designed so that derived mesh classes
    1613             :    * could use the _same_ base class iterators interchangeably.  Their
    1614             :    * definition comes later in the header file.
    1615             :    */
    1616             :   struct node_iterator;
    1617             :   struct const_node_iterator;
    1618             : 
    1619             :   /**
    1620             :    * Converts a set of this Mesh's elements defined by \p range from
    1621             :    * FIRST order to SECOND order. Must be called on conforming,
    1622             :    * non-refined meshes. For example, a mesh consisting of \p Tet4
    1623             :    * will be converted to a mesh with \p Tet10 etc.
    1624             :    *
    1625             :    * \note For some elements like \p Hex8 there exist two higher order
    1626             :    * equivalents, \p Hex20 and \p Hex27.  When \p full_ordered is \p
    1627             :    * true (default), then \p Hex27 is built.  Otherwise, \p Hex20 is
    1628             :    * built.  The same holds obviously for \p Quad4, \p Prism6, etc.
    1629             :    */
    1630             :   virtual void all_second_order_range(const SimpleRange<element_iterator> & range,
    1631             :                                       const bool full_ordered = true) = 0;
    1632             : 
    1633             :   /**
    1634             :    * Calls the range-based version of this function with a range
    1635             :    * consisting of all elements in the mesh.
    1636             :    */
    1637             :   void all_second_order (const bool full_ordered = true);
    1638             : 
    1639             :   /**
    1640             :    * Converts a set of elements in this (conforming, non-refined) mesh
    1641             :    * into "complete" order elements, i.e. elements which
    1642             :    * can store degrees of freedom on any vertex, edge, or face.  For
    1643             :    * example, a mesh consisting of \p Tet4 or \p Tet10 will be
    1644             :    * converted to a mesh with \p Tet14 etc.
    1645             :    */
    1646             :   virtual void all_complete_order_range(const SimpleRange<element_iterator> & range) = 0;
    1647             : 
    1648             :   /**
    1649             :    * Calls the range-based version of this function with a range
    1650             :    * consisting of all elements in the mesh.
    1651             :    */
    1652             :   virtual void all_complete_order ();
    1653             : 
    1654             :   /**
    1655             :    * In a few (very rare) cases, the user may have manually tagged the
    1656             :    * elements with specific processor IDs by hand, without using a
    1657             :    * partitioner.  In this case, the Mesh will not know that the total
    1658             :    * number of partitions, _n_parts, has changed, unless you call this
    1659             :    * function.  This is an O(N active elements) calculation.  The return
    1660             :    * value is the number of partitions, and _n_parts is also set by
    1661             :    * this function.
    1662             :    */
    1663             :   unsigned int recalculate_n_partitions();
    1664             : 
    1665             :   /**
    1666             :    * \returns A pointer to a subordinate \p PointLocatorBase object
    1667             :    * for this mesh, constructing a master PointLocator first if
    1668             :    * necessary.  This should not be used in threaded or
    1669             :    * non-parallel_only code unless the master has already been
    1670             :    * constructed.
    1671             :    */
    1672             :   std::unique_ptr<PointLocatorBase> sub_point_locator () const;
    1673             : 
    1674             :   /**
    1675             :    * Set value used by PointLocatorBase::close_to_point_tol().
    1676             :    *
    1677             :    * Defaults to 0.0. If nonzero, calls close_to_point_tol() whenever
    1678             :    * a new PointLocator is built for use by this Mesh.  Since the Mesh
    1679             :    * controls the creation and destruction of the PointLocator, if
    1680             :    * there are any parameters we need to customize on it, the Mesh
    1681             :    * will need to know about them.
    1682             :    */
    1683             :   void set_point_locator_close_to_point_tol(Real val);
    1684             :   Real get_point_locator_close_to_point_tol() const;
    1685             : 
    1686             :   /**
    1687             :    * Releases the current \p PointLocator object.
    1688             :    */
    1689             :   void clear_point_locator ();
    1690             : 
    1691             :   /**
    1692             :    * In the point locator, do we count lower dimensional elements
    1693             :    * when we refine point locator regions? This is relevant in
    1694             :    * tree-based point locators, for example.
    1695             :    */
    1696             :   void set_count_lower_dim_elems_in_point_locator(bool count_lower_dim_elems);
    1697             : 
    1698             :   /**
    1699             :    * Get the current value of _count_lower_dim_elems_in_point_locator.
    1700             :    */
    1701             :   bool get_count_lower_dim_elems_in_point_locator() const;
    1702             : 
    1703             :   /**
    1704             :    * Verify id and processor_id consistency of our elements and
    1705             :    * nodes containers.
    1706             :    * Calls libmesh_assert() on each possible failure.
    1707             :    * Currently only implemented on DistributedMesh; a serial data
    1708             :    * structure is much harder to get out of sync.
    1709             :    */
    1710         292 :   virtual void libmesh_assert_valid_parallel_ids() const {}
    1711             : 
    1712             :   /**
    1713             :    * \returns A writable reference for getting/setting an optional
    1714             :    * name for a subdomain.
    1715             :    */
    1716             :   std::string & subdomain_name(subdomain_id_type id);
    1717             :   const std::string & subdomain_name(subdomain_id_type id) const;
    1718             : 
    1719             :   /**
    1720             :    * Sets the \p name for the provided \p id
    1721             :    * @param id The subdomain id to set the name for
    1722             :    * @param name The subdomain name
    1723             :    * @param synchronous Whether this method is being called across all mesh ranks. If this is true,
    1724             :    * then we don't have to register this collective container as being out of sync
    1725             :    */
    1726             :   void set_subdomain_name(subdomain_id_type id,
    1727             :                           const std::string & name,
    1728             :                           bool synchronous = false);
    1729             : 
    1730             :   /**
    1731             :    * \returns The id of the named subdomain if it exists,
    1732             :    * \p Elem::invalid_subdomain_id otherwise.
    1733             :    */
    1734             :   subdomain_id_type get_id_by_name(std::string_view name) const;
    1735             : 
    1736             :   /*
    1737             :    * We have many combinations of iterators that filter on various
    1738             :    * characteristics; we use macros to make their abstract base class
    1739             :    * and their subclass declarations more terse.
    1740             :    */
    1741             : #define ABSTRACT_ELEM_ITERATORS(TYPE, ARGDECL) \
    1742             :   virtual element_iterator TYPE##elements_begin(ARGDECL) = 0; \
    1743             :   virtual element_iterator TYPE##elements_end(ARGDECL) = 0; \
    1744             :   virtual const_element_iterator TYPE##elements_begin(ARGDECL) const = 0; \
    1745             :   virtual const_element_iterator TYPE##elements_end(ARGDECL) const = 0; \
    1746             :   virtual SimpleRange<element_iterator> TYPE##element_ptr_range(ARGDECL) = 0; \
    1747             :   virtual SimpleRange<const_element_iterator> TYPE##element_ptr_range(ARGDECL) const = 0;
    1748             : 
    1749             : #define DECLARE_ELEM_ITERATORS(TYPE, ARGDECL, ARGS) \
    1750             :   virtual element_iterator TYPE##elements_begin(ARGDECL) override final; \
    1751             :   virtual element_iterator TYPE##elements_end(ARGDECL) override final; \
    1752             :   virtual const_element_iterator TYPE##elements_begin(ARGDECL) const override final; \
    1753             :   virtual const_element_iterator TYPE##elements_end(ARGDECL) const override final; \
    1754             :   virtual SimpleRange<element_iterator> TYPE##element_ptr_range(ARGDECL) override final { return {TYPE##elements_begin(ARGS), TYPE##elements_end(ARGS)}; } \
    1755             :   virtual SimpleRange<const_element_iterator> TYPE##element_ptr_range(ARGDECL) const override final  { return {TYPE##elements_begin(ARGS), TYPE##elements_end(ARGS)}; }
    1756             : 
    1757             : #define ABSTRACT_NODE_ITERATORS(TYPE, ARGDECL) \
    1758             :   virtual node_iterator TYPE##nodes_begin(ARGDECL) = 0; \
    1759             :   virtual node_iterator TYPE##nodes_end(ARGDECL) = 0; \
    1760             :   virtual const_node_iterator TYPE##nodes_begin(ARGDECL) const = 0; \
    1761             :   virtual const_node_iterator TYPE##nodes_end(ARGDECL) const = 0; \
    1762             :   virtual SimpleRange<node_iterator> TYPE##node_ptr_range(ARGDECL) = 0; \
    1763             :   virtual SimpleRange<const_node_iterator> TYPE##node_ptr_range(ARGDECL) const = 0;
    1764             : 
    1765             : #define DECLARE_NODE_ITERATORS(TYPE, ARGDECL, ARGS) \
    1766             :   virtual node_iterator TYPE##nodes_begin(ARGDECL) override final; \
    1767             :   virtual node_iterator TYPE##nodes_end(ARGDECL) override final; \
    1768             :   virtual const_node_iterator TYPE##nodes_begin(ARGDECL) const override final; \
    1769             :   virtual const_node_iterator TYPE##nodes_end(ARGDECL) const override final; \
    1770             :   virtual SimpleRange<node_iterator> TYPE##node_ptr_range(ARGDECL) override final { return {TYPE##nodes_begin(ARGS), TYPE##nodes_end(ARGS)}; } \
    1771             :   virtual SimpleRange<const_node_iterator> TYPE##node_ptr_range(ARGDECL) const override final  { return {TYPE##nodes_begin(ARGS), TYPE##nodes_end(ARGS)}; }
    1772             : 
    1773             : #define LIBMESH_COMMA ,
    1774             : 
    1775             :   /*
    1776             :    * element_iterator accessors
    1777             :    *
    1778             :    * The basic elements_begin() and elements_end() iterators iterate
    1779             :    * over all elements in a mesh, returning element pointers or const
    1780             :    * element pointers when dereferenced (depending on whether the mesh
    1781             :    * reference was const). range-for loops can be written using
    1782             :    * element_ptr_range()
    1783             :    *
    1784             :    * Filtered versions of these iterators, which skip over all
    1785             :    * elements not matching some predicate, are also available, by
    1786             :    * adding a prefix to the methods above.  E.g. local_ (in a form
    1787             :    * like local_elements_begin() or local_element_ptr_range()) will
    1788             :    * iterate only over elements whose processor_id() is the current
    1789             :    * processor, or active_ will iterate only over active elements even
    1790             :    * if the mesh is refined, or active_local_ will iterate over
    1791             :    * elements that are both active and local.  Negation forms such as
    1792             :    * not_local_ also exist.
    1793             :    *
    1794             :    * For some iterator prefixes, such as type_, an argument is needed
    1795             :    * for the filter; e.g. the ElemType to select for in that case.
    1796             :    *
    1797             :    * All valid prefixes and their corresponding arguments can be found
    1798             :    * in the macro invocations below.
    1799             :    */
    1800             :   ABSTRACT_ELEM_ITERATORS(,)                // elements_begin(), element_ptr_range(): all elements
    1801             :   ABSTRACT_ELEM_ITERATORS(active_,)         // Elem::active() == true
    1802             :   ABSTRACT_ELEM_ITERATORS(ancestor_,)       // Elem::ancestor() == true
    1803             :   ABSTRACT_ELEM_ITERATORS(subactive_,)      // Elem::subactive() == true
    1804             :   ABSTRACT_ELEM_ITERATORS(local_,)          // Elem::processor_id() == this processor
    1805             :   ABSTRACT_ELEM_ITERATORS(unpartitioned_,)  // Elem::processor_id() == invalid_processor_id
    1806             :   ABSTRACT_ELEM_ITERATORS(facelocal_,)      // is on or has a neighbor on this processor
    1807             :   ABSTRACT_ELEM_ITERATORS(level_,unsigned int level)   // Elem::level() == level
    1808             :   ABSTRACT_ELEM_ITERATORS(pid_,processor_id_type pid)  // Elem::processor_id() == pid
    1809             :   ABSTRACT_ELEM_ITERATORS(type_,ElemType type)         // Elem::type() == type
    1810             : 
    1811             :   ABSTRACT_ELEM_ITERATORS(active_subdomain_,subdomain_id_type sid) // active && Elem::subdomain_id() == sid
    1812             :   ABSTRACT_ELEM_ITERATORS(active_subdomain_set_,std::set<subdomain_id_type> ss) // active && ss.contains(Elem::subdomain_id())
    1813             : 
    1814             :   // Iterators which use negations of filters described above
    1815             :   ABSTRACT_ELEM_ITERATORS(not_active_,)
    1816             :   ABSTRACT_ELEM_ITERATORS(not_ancestor_,)
    1817             :   ABSTRACT_ELEM_ITERATORS(not_subactive_,)
    1818             :   ABSTRACT_ELEM_ITERATORS(not_local_,)
    1819             :   ABSTRACT_ELEM_ITERATORS(not_level_,unsigned int level)
    1820             : 
    1821             :   // Iterators which combine multiple of the filters described above
    1822             :   ABSTRACT_ELEM_ITERATORS(active_local_,)
    1823             :   ABSTRACT_ELEM_ITERATORS(active_not_local_,)
    1824             :   ABSTRACT_ELEM_ITERATORS(active_unpartitioned_,)
    1825             :   ABSTRACT_ELEM_ITERATORS(active_type_,ElemType type)
    1826             :   ABSTRACT_ELEM_ITERATORS(active_pid_,processor_id_type pid)
    1827             :   ABSTRACT_ELEM_ITERATORS(local_level_,unsigned int level)
    1828             :   ABSTRACT_ELEM_ITERATORS(local_not_level_,unsigned int level)
    1829             :   ABSTRACT_ELEM_ITERATORS(active_local_subdomain_,subdomain_id_type sid)
    1830             :   ABSTRACT_ELEM_ITERATORS(active_local_subdomain_set_,std::set<subdomain_id_type> ss)
    1831             : 
    1832             :   // Backwards compatibility
    1833             :   virtual SimpleRange<element_iterator> active_subdomain_elements_ptr_range(subdomain_id_type sid) = 0;
    1834             :   virtual SimpleRange<const_element_iterator> active_subdomain_elements_ptr_range(subdomain_id_type sid) const = 0;
    1835             :   virtual SimpleRange<element_iterator> active_local_subdomain_elements_ptr_range(subdomain_id_type sid) = 0;
    1836             :   virtual SimpleRange<const_element_iterator> active_local_subdomain_elements_ptr_range(subdomain_id_type sid) const = 0;
    1837             :   virtual SimpleRange<element_iterator> active_subdomain_set_elements_ptr_range(std::set<subdomain_id_type> ss) = 0;
    1838             :   virtual SimpleRange<const_element_iterator> active_subdomain_set_elements_ptr_range(std::set<subdomain_id_type> ss) const = 0;
    1839             : 
    1840             :   // Discouraged from use - these iterators use outdated
    1841             :   // pre-GhostingFunctor definitions and should be renamed if not
    1842             :   // deprecated
    1843             :   ABSTRACT_ELEM_ITERATORS(semilocal_,)         // active && Elem::is_semilocal()
    1844             :   ABSTRACT_ELEM_ITERATORS(ghost_,)             // active && Elem::is_semilocal() && not local discouraged
    1845             :   ABSTRACT_ELEM_ITERATORS(active_semilocal_,)
    1846             : 
    1847             :   // solution can be evaluated, with the given DoF map, for the given
    1848             :   // variable number, or for all variables by default
    1849             :   ABSTRACT_ELEM_ITERATORS(evaluable_,const DofMap & dof_map LIBMESH_COMMA unsigned int var_num = libMesh::invalid_uint)
    1850             : 
    1851             :   // solution can be evaluated for all variables of all given DoF maps
    1852             :   ABSTRACT_ELEM_ITERATORS(multi_evaluable_,std::vector<const DofMap *> dof_maps)
    1853             : 
    1854             : #ifdef LIBMESH_ENABLE_AMR
    1855             :   ABSTRACT_ELEM_ITERATORS(flagged_,unsigned char rflag)  // Elem::refinement_flag() == rflag
    1856             : 
    1857             :   // Elem::refinement_flag() == rflag && Elem::processor_id() == pid
    1858             :   ABSTRACT_ELEM_ITERATORS(flagged_pid_,unsigned char rflag LIBMESH_COMMA processor_id_type pid)
    1859             : #endif
    1860             : 
    1861             :   /*
    1862             :    * node_iterator accessors
    1863             :    *
    1864             :    * The basic nodes_begin() and nodes_end() iterators iterate
    1865             :    * over all nodes in a mesh, returning node pointers or const
    1866             :    * node pointers when dereferenced (depending on whether the mesh
    1867             :    * reference was const). range-for loops can be written using
    1868             :    * node_ptr_range()
    1869             :    *
    1870             :    * Filtered versions of these iterators, which skip over all
    1871             :    * nodes not matching some predicate, are also available, by
    1872             :    * adding a prefix to the methods above.  E.g. local_ (in a form
    1873             :    * like local_nodes_begin() or local_node_ptr_range()) will
    1874             :    * iterate only over nodes whose processor_id() is the current
    1875             :    * processor.
    1876             :    *
    1877             :    * All valid prefixes and their corresponding arguments can be found
    1878             :    * in the macro invocations below.
    1879             :    */
    1880             :   ABSTRACT_NODE_ITERATORS(,)          // nodes_begin(), node_ptr_range(): all nodes
    1881             :   ABSTRACT_NODE_ITERATORS(active_,)   // Node::active() == true; i.e. Node::id() != invalid_id
    1882             :   ABSTRACT_NODE_ITERATORS(local_,)    // Node::processor_id() == this processor
    1883             :   ABSTRACT_NODE_ITERATORS(bnd_,)      // BoundaryInfo::n_boundary_ids(node) > 0
    1884             :   ABSTRACT_NODE_ITERATORS(pid_,processor_id_type pid)  // Node::processor_id() == pid
    1885             :   ABSTRACT_NODE_ITERATORS(bid_,boundary_id_type bid)   // BoundaryInfo::has_boundary_id(node, bid)
    1886             : 
    1887             :   // solution can be evaluated, with the given DoF map, for the given
    1888             :   // variable number, or for all variables by default
    1889             :   ABSTRACT_NODE_ITERATORS(evaluable_,const DofMap & dof_map LIBMESH_COMMA unsigned int var_num = libMesh::invalid_uint)
    1890             : 
    1891             :   // solution can be evaluated for all variables of all given DoF maps
    1892             :   ABSTRACT_NODE_ITERATORS(multi_evaluable_,std::vector<const DofMap *> dof_maps)
    1893             : 
    1894             :   // Technically these define libMesh::MeshBase::*ElemRange, but since
    1895             :   // those don't conflict with libMesh::*ElemRange they're as good as
    1896             :   // a real forward declaration, which we can't do here.
    1897             :   typedef StoredRange<MeshBase::element_iterator,             Elem *>      ElemRange;
    1898             :   typedef StoredRange<MeshBase::const_element_iterator, const Elem *> ConstElemRange;
    1899             : 
    1900             :   /**
    1901             :    * \returns A reference to a cached vector copy of a range of
    1902             :    * pointers to all semilocal elements, suitable for threading.
    1903             :    *
    1904             :    * Iterating over all semilocal elements is most useful for
    1905             :    * modifying the mesh, so we only have a non-const version for now.
    1906             :    */
    1907             :   const ElemRange & element_stored_range();
    1908             : 
    1909             :   /**
    1910             :    * \returns A reference to a cached vector copy of a range of
    1911             :    * pointers to all active local elements, suitable for threading.
    1912             :    *
    1913             :    * Iterating over only local elements is most useful for computing
    1914             :    * on the mesh, so we only have a non-const version for now.
    1915             :    */
    1916             :   const ConstElemRange & active_local_element_stored_range() const;
    1917             : 
    1918             :   /**
    1919             :    * Clears stored ranges, to indicate that the mesh has changed and
    1920             :    * they should be regenerated when next needed.
    1921             :    */
    1922             :   void clear_stored_ranges();
    1923             : 
    1924             :   /**
    1925             :    * \returns A writable reference to the whole subdomain name map
    1926             :    */
    1927       13828 :   std::map<subdomain_id_type, std::string> & set_subdomain_name_map ()
    1928       36029 :   { this->unset_has_synched_subdomain_name_map(); return _block_id_to_name; }
    1929        2123 :   const std::map<subdomain_id_type, std::string> & get_subdomain_name_map () const
    1930        2399 :   { return _block_id_to_name; }
    1931             : 
    1932             :   typedef std::vector<std::pair<std::pair<const Elem *, unsigned int>, Real>> constraint_rows_mapped_type;
    1933             :   typedef std::map<const Node *, constraint_rows_mapped_type> constraint_rows_type;
    1934             : 
    1935             :   /**
    1936             :    * Constraint rows accessors
    1937             :    */
    1938        8528 :   constraint_rows_type & get_constraint_rows()
    1939      200149 :   { return _constraint_rows; }
    1940             : 
    1941       79899 :   const constraint_rows_type & get_constraint_rows() const
    1942       79899 :   { return _constraint_rows; }
    1943             : 
    1944             :   dof_id_type n_constraint_rows() const;
    1945             : 
    1946             :   /**
    1947             :    * Copy the constraints from the other mesh to this mesh
    1948             :    */
    1949             :   void copy_constraint_rows(const MeshBase & other_mesh);
    1950             : 
    1951             :   /**
    1952             :    * Copy the constraints from the given matrix to this mesh.  The
    1953             :    * \p constraint_operator should be an mxn matrix, where
    1954             :    * m == this->n_nodes() and the operator indexing matches the
    1955             :    * current node indexing.  This may require users to disable mesh
    1956             :    * renumbering in between loading a mesh file and loading a
    1957             :    * constraint matrix which matches it.
    1958             :    *
    1959             :    * If any "constraint" rows in the matrix are unit vectors, the node
    1960             :    * corresponding to that row index will be left unconstrained, and
    1961             :    * will be used to constrain any other nodes which have a non-zero
    1962             :    * in the column index of that unit vector.
    1963             :    *
    1964             :    * For each matrix column index which does not correspond to an
    1965             :    * existing node, a new NodeElem will be added to the mesh on which
    1966             :    * to store the new unconstrained degree(s) of freedom.
    1967             :    *
    1968             :    * If \p precondition_constraint_operator is true, then the values
    1969             :    * of those new unconstrained degrees of freedom may be scaled to
    1970             :    * improve the conditioning of typical PDE matrices integrated on
    1971             :    * constrained mesh elements.
    1972             :    *
    1973             :    * \p T for the constraint_operator in this function should be \p
    1974             :    * Real or \p Number ... and the data should be \p Real - we just
    1975             :    * allow complex \p T for the sake of subclasses which have to be
    1976             :    * configured and compiled with only one runtime option.
    1977             :    */
    1978             :   template <typename T>
    1979             :   void copy_constraint_rows(const SparseMatrix<T> & constraint_operator,
    1980             :                             bool precondition_constraint_operator = false);
    1981             : 
    1982             :   /**
    1983             :    * Prints (from processor 0) all mesh constraint rows.  If \p
    1984             :    * print_nonlocal is true, then each constraint is printed once for
    1985             :    * each processor that knows about it, which may be useful for \p
    1986             :    * DistributedMesh debugging.
    1987             :    */
    1988             :   void print_constraint_rows(std::ostream & os=libMesh::out,
    1989             :                              bool print_nonlocal=false) const;
    1990             : 
    1991             :   /**
    1992             :    * Gets a string reporting all mesh constraint rows local to
    1993             :    * this processor.  If \p print_nonlocal is true, then nonlocal
    1994             :    * constraints which are locally known are included.
    1995             :    */
    1996             :   std::string get_local_constraints(bool print_nonlocal=false) const;
    1997             : 
    1998             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1999             :   /**
    2000             :    * \deprecated This method has ben replaced by \p cache_elem_data which
    2001             :    * caches data in addition to elem dimensions (e.g. elem subdomain ids)
    2002             :    * Search the mesh and cache the different dimensions of the elements
    2003             :    * present in the mesh.  This is done in prepare_for_use(), but can
    2004             :    * be done manually by other classes after major mesh modifications.
    2005             :    */
    2006             :   void cache_elem_dims();
    2007             : #endif // LIBMESH_ENABLE_DEPRECATED
    2008             : 
    2009             :   /*
    2010             :    * Search the mesh and cache data for the elements
    2011             :    * present in the mesh.  This is done in prepare_for_use(), but can
    2012             :    * be done manually by other classes after major mesh modifications.
    2013             :    * Data cached includes:
    2014             :    *   - elem dimensions
    2015             :    *   - elem subdomains
    2016             :    */
    2017             :   void cache_elem_data();
    2018             : 
    2019             :   /**
    2020             :    * libMesh often expects all processors to know about names of all
    2021             :    * subdomain ids, but distributed mesh generators may only know
    2022             :    * about part of a mesh when creating names.  This method can
    2023             :    * synchronize the subdomain id to name map across processors,
    2024             :    * assuming no conflicts exist.  It is called automatically during
    2025             :    * complete_preparation() unless the map is already known to be
    2026             :    * synchronized.
    2027             :    */
    2028             :   void sync_subdomain_name_map();
    2029             : 
    2030             :   /**
    2031             :    * Search the mesh for elements that have a neighboring element
    2032             :    * of dim+1 and set that element as the interior parent
    2033             :    */
    2034             :   void detect_interior_parents();
    2035             : 
    2036             :   /**
    2037             :    * \return A mesh that may own interior parents of elements in this
    2038             :    * mesh.  In most cases this mesh includes its own interior parents,
    2039             :    * but in cases where a separate "interior" mesh was used to create
    2040             :    * this mesh as a distinct lower-dimensional boundary (or boundary
    2041             :    * subset) mesh, the original mesh will be returned here.
    2042             :    */
    2043         298 :   const MeshBase & interior_mesh() const { return *_interior_mesh; }
    2044             : 
    2045             :   /**
    2046             :    * \return A writeable reference to the interior mesh.
    2047             :    */
    2048       34326 :   MeshBase & interior_mesh() { return *_interior_mesh; }
    2049             : 
    2050             :   /**
    2051             :    * Sets the interior mesh.  For advanced use only.
    2052             :    */
    2053        3635 :   void set_interior_mesh(MeshBase & int_mesh) { _interior_mesh = &int_mesh; }
    2054             : 
    2055             :   /**
    2056             :    * \return The cached mesh subdomains. As long as the mesh is prepared, this
    2057             :    * should contain all the subdomain ids across processors. Relies on the mesh
    2058             :    * being prepared
    2059             :    */
    2060             :   const std::set<subdomain_id_type> & get_mesh_subdomains() const;
    2061             : 
    2062             : #ifdef LIBMESH_ENABLE_PERIODIC
    2063             :   /**
    2064             :    * Register a pair of boundaries as disjoint neighbor boundary pairs.
    2065             :    */
    2066             :   void add_disjoint_neighbor_boundary_pairs(const boundary_id_type b1,
    2067             :                                    const boundary_id_type b2,
    2068             :                                    const RealVectorValue & translation);
    2069             : 
    2070             :   PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs();
    2071             : 
    2072             :   const PeriodicBoundaries * get_disjoint_neighbor_boundary_pairs() const;
    2073             : 
    2074             :   void remove_disjoint_boundary_pair(const boundary_id_type b1,
    2075             :                                      const boundary_id_type b2);
    2076             : #endif
    2077             : 
    2078             :   /**
    2079             :    * Flags indicating in what ways a mesh has been prepared for use.
    2080             :    */
    2081             :   struct Preparation
    2082             :   {
    2083             :     /**
    2084             :      * Constructor. Initializes all flags to false.
    2085             :      */
    2086             :     Preparation();
    2087             : 
    2088             :     /**
    2089             :      * Returns true iff all the flags are true.
    2090             :      */
    2091             :     explicit operator bool() const;
    2092             : 
    2093             :     /**
    2094             :      * Set all flags to the "set_all" value.
    2095             :      */
    2096             :     Preparation & operator= (bool set_all);
    2097             : 
    2098             :     /**
    2099             :      * Two Preparation objects are equivalent iff all the flags match,
    2100             :      * regardless of the true/false status of any given flag.
    2101             :      */
    2102             :     bool operator== (const Preparation & other) const;
    2103             :     bool operator!= (const Preparation & other) const;
    2104             : 
    2105             :     // Assert that a Preparation object is identical across processors
    2106             :     void libmesh_assert_consistent (const Parallel::Communicator & libmesh_dbg_var(comm));
    2107             : 
    2108             :     bool is_partitioned;
    2109             :     bool has_synched_id_counts;
    2110             :     bool has_neighbor_ptrs;
    2111             :     bool has_cached_elem_data;
    2112             :     bool has_interior_parent_ptrs;
    2113             :     bool has_removed_remote_elements;
    2114             :     bool has_removed_orphaned_nodes;
    2115             :     bool has_boundary_id_sets;
    2116             :     bool has_reinit_ghosting_functors;
    2117             :     bool has_synched_subdomain_name_map;
    2118             :   };
    2119             : 
    2120             : protected:
    2121             : 
    2122             : #ifdef LIBMESH_ENABLE_PERIODIC
    2123             :   /// @brief The disjoint neighbor boundary id pairs.
    2124             :   std::unique_ptr<PeriodicBoundaries> _disjoint_neighbor_boundary_pairs;
    2125             : #endif
    2126             : 
    2127             :   /**
    2128             :    * This class holds the boundary information.  It can store nodes, edges,
    2129             :    * and faces with a corresponding id that facilitates setting boundary
    2130             :    * conditions.
    2131             :    *
    2132             :    * Direct access to this class is now officially deprecated and will
    2133             :    * be removed in future libMesh versions.  Use the \p get_boundary_info()
    2134             :    * accessor instead.
    2135             :    */
    2136             :   std::unique_ptr<BoundaryInfo> boundary_info;
    2137             : 
    2138             :   /**
    2139             :    * Moves any superclass data (e.g. GhostingFunctors that might rely
    2140             :    * on element and nodal data (which is managed by subclasses!)
    2141             :    * being already moved first.
    2142             :    *
    2143             :    * Must be manually called in dofobject-managing subclass move
    2144             :    * operators.
    2145             :    */
    2146             :   void post_dofobject_moves(MeshBase && other_mesh);
    2147             : 
    2148             :   /**
    2149             :    * Helper class to copy cached data, to synchronize with a possibly
    2150             :    * unprepared \p other_mesh
    2151             :    */
    2152             :   void copy_cached_data (const MeshBase & other_mesh);
    2153             : 
    2154             :   /**
    2155             :    * Shim to allow operator == (&) to behave like a virtual function
    2156             :    * without having to be one.
    2157             :    */
    2158             :   virtual std::string_view subclass_first_difference_from (const MeshBase & other_mesh) const = 0;
    2159             : 
    2160             :   /**
    2161             :    * Tests for equality of all elements and nodes in the mesh.  Helper
    2162             :    * function for subclass_equals() in unstructured mesh subclasses.
    2163             :    */
    2164             :   bool nodes_and_elements_equal(const MeshBase & other_mesh) const;
    2165             : 
    2166             :   /**
    2167             :    *
    2168             :    */
    2169             :   std::string_view first_difference_from(const MeshBase & other_mesh) const;
    2170             : 
    2171             : 
    2172             :   /**
    2173             :    * \returns A writable reference to the number of partitions.
    2174             :    */
    2175       13588 :   unsigned int & set_n_partitions ()
    2176       13588 :   { return _n_parts; }
    2177             : 
    2178             :   /**
    2179             :    * The number of partitions the mesh has.  This is set by
    2180             :    * the partitioners, and may not be changed directly by
    2181             :    * the user.
    2182             :    *
    2183             :    * \note The number of partitions \e need \e not equal
    2184             :    * this->n_processors(), consider for example the case where you
    2185             :    * simply want to partition a mesh on one processor and view the
    2186             :    * result in GMV.
    2187             :    */
    2188             :   unsigned int _n_parts;
    2189             : 
    2190             :   /**
    2191             :    * The default mapping type (typically Lagrange) between master and
    2192             :    * physical space to assign to newly added elements.
    2193             :    */
    2194             :   ElemMappingType _default_mapping_type;
    2195             : 
    2196             :   /**
    2197             :    * The default mapping data (unused with Lagrange, used for nodal
    2198             :    * weight lookup index with rational bases) to assign to newly added
    2199             :    * elements.
    2200             :    */
    2201             :   unsigned char _default_mapping_data;
    2202             : 
    2203             :   /**
    2204             :    * Flags indicating in what ways \p this mesh has been prepared.
    2205             :    */
    2206             :   Preparation _preparation;
    2207             : 
    2208             :   /**
    2209             :    * A cached \p ElemRange for threaded mutation of all semilocal
    2210             :    * elements of this mesh.
    2211             :    *
    2212             :    * This will not actually be built unless needed. Further, since we
    2213             :    * want our \p elem_stored_range() method to be \p const (yet do the
    2214             :    * dynamic allocating) this needs to be mutable.
    2215             :    */
    2216             :   mutable std::unique_ptr<ElemRange> _element_stored_range;
    2217             : 
    2218             :   /**
    2219             :    * A cached \p ConstElemRange for threaded calculation on all
    2220             :    * local elements of this mesh.
    2221             :    *
    2222             :    * This will not actually be built unless needed. Further, since we
    2223             :    * want our \p elem_stored_range() method to be \p const (yet do the
    2224             :    * dynamic allocating) this needs to be mutable.
    2225             :    */
    2226             :   mutable std::unique_ptr<ConstElemRange>
    2227             :     _const_active_local_element_stored_range;
    2228             : 
    2229             :   /**
    2230             :    * A \p PointLocator class for this mesh.
    2231             :    * This will not actually be built unless needed. Further, since we want
    2232             :    * our \p point_locator() method to be \p const (yet do the dynamic allocating)
    2233             :    * this needs to be mutable.  Since the PointLocatorBase::build() member is used,
    2234             :    * and it operates on a constant reference to the mesh, this is OK.
    2235             :    */
    2236             :   mutable std::unique_ptr<PointLocatorBase> _point_locator;
    2237             : 
    2238             :   /**
    2239             :    * Do we count lower dimensional elements in point locator refinement?
    2240             :    * This is relevant in tree-based point locators, for example.
    2241             :    */
    2242             :   bool _count_lower_dim_elems_in_point_locator;
    2243             : 
    2244             :   /**
    2245             :    * A partitioner to use at each prepare_for_use().
    2246             :    *
    2247             :    * This will be built in the constructor of each derived class, but
    2248             :    * can be replaced by the user through the partitioner() accessor.
    2249             :    */
    2250             :   std::unique_ptr<Partitioner> _partitioner;
    2251             : 
    2252             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
    2253             :   /**
    2254             :    * The next available unique id for assigning ids to DOF objects
    2255             :    */
    2256             :   unique_id_type _next_unique_id;
    2257             : #endif
    2258             : 
    2259             :   /**
    2260             :    * Defaulting to \p this, a pointer to the mesh used to generate
    2261             :    * boundary elements on \p this.
    2262             :    */
    2263             :   MeshBase *_interior_mesh;
    2264             : 
    2265             :   /**
    2266             :    * If this is true then no partitioning should be done with the
    2267             :    * possible exception of orphaned nodes.
    2268             :    */
    2269             :   bool _skip_noncritical_partitioning;
    2270             : 
    2271             :   /**
    2272             :    * If this is true then no partitioning should be done.
    2273             :    */
    2274             :   bool _skip_all_partitioning;
    2275             : 
    2276             :   /**
    2277             :    * If this is true then renumbering will be kept to a minimum.
    2278             :    *
    2279             :    * This is set when prepare_for_use() is called.
    2280             :    */
    2281             :   bool _skip_renumber_nodes_and_elements;
    2282             : 
    2283             :   /**
    2284             :    * If this is \p true then we will skip \p find_neighbors in \p prepare_for_use
    2285             :    */
    2286             :   bool _skip_find_neighbors;
    2287             : 
    2288             :   /**
    2289             :    * If this is \p true then we will skip \p detect_interior_parents in \p prepare_for_use
    2290             :    */
    2291             :   bool _skip_detect_interior_parents;
    2292             : 
    2293             :   /**
    2294             :    * If this is false then even on DistributedMesh remote elements
    2295             :    * will not be deleted during mesh preparation.
    2296             :    *
    2297             :    * This is true by default.
    2298             :    */
    2299             :   bool _allow_remote_element_removal;
    2300             : 
    2301             :   /**
    2302             :    * The Exodus reader (and potentially other readers in the future?)
    2303             :    * now supports setting Node and Elem unique_ids based on values
    2304             :    * from within the Exodus file itself, rather than generating them
    2305             :    * automatically in LibMesh. In this case, the unique_ids will not
    2306             :    * necessarily be unique across the set of all _DofObjects_,
    2307             :    * although they should still be unique within the individual sets
    2308             :    * of Elems and Nodes. The reader can therefore set this Mesh flag
    2309             :    * (which defaults to false) to indicate we should be less strict
    2310             :    * when checking the "uniqueness" of unique_ids.
    2311             :    */
    2312             :   bool _allow_node_and_elem_unique_id_overlap;
    2313             : 
    2314             :   /**
    2315             :    * This structure maintains the mapping of named blocks
    2316             :    * for file formats that support named blocks.  Currently
    2317             :    * this is only implemented for ExodusII
    2318             :    */
    2319             :   std::map<subdomain_id_type, std::string> _block_id_to_name;
    2320             : 
    2321             :   /**
    2322             :    * We cache the dimension of the elements present in the mesh.
    2323             :    * So, if we have a mesh with 1D and 2D elements, this structure
    2324             :    * will contain 1 and 2.
    2325             :    */
    2326             :   std::set<unsigned char> _elem_dims;
    2327             : 
    2328             :   /**
    2329             :    * We cache the (default) order of the geometric elements present in
    2330             :    * the mesh.  E.g. if we have a mesh with TRI3 and TRI6 elements,
    2331             :    * this structure will contain FIRST and SECOND.
    2332             :    */
    2333             :   std::set<Order> _elem_default_orders;
    2334             : 
    2335             :   /**
    2336             :    * We cache the maximum nodal order supported by all the mesh's
    2337             :    * elements (the minimum supported_nodal_order() of any element)
    2338             :    */
    2339             :   Order _supported_nodal_order;
    2340             : 
    2341             :   /**
    2342             :    * We cache the subdomain ids of the elements present in the mesh.
    2343             :    */
    2344             :   std::set<subdomain_id_type> _mesh_subdomains;
    2345             : 
    2346             :   /**
    2347             :    * Map from "element set code" to list of set ids to which that element
    2348             :    * belongs (and vice-versa). Remarks:
    2349             :    * 1.) The elemset code is a dof_id_type because (if used) it is
    2350             :    * stored as an extra_integer (named "elemset_code") on all elements,
    2351             :    * and extra_integers are of type dof_id_type. Elements which do not
    2352             :    * belong to any set should be assigned an elemset code of DofObject::invalid_id.
    2353             :    * 2.) Element sets can be thought of as a generalization of the concept
    2354             :    * of a subdomain. Subdomains have the following restrictions:
    2355             :    *   a.) A given element can only belong to a single subdomain
    2356             :    *   b.) When using Exodus file input/output, subdomains are (unfortunately)
    2357             :    *   tied to the concept of exodus element blocks, which consist of a single
    2358             :    *   geometric element type, somewhat limiting their generality.
    2359             :    * 3.) The user is responsible for filling in the values of this map
    2360             :    * in a consistent manner, unless the elemsets are read in from an
    2361             :    * Exodus file, in which case the elemset codes will be set up
    2362             :    * automatically. The codes can basically be chosen arbitrarily,
    2363             :    * with the one requirement that elements which belong to no sets
    2364             :    * should have a set code of DofObject::invalid_id.
    2365             :    * 4.) We also keep a list of all the elemset ids which have been added in
    2366             :    * order to support O(1) performance behavior in n_elemsets() calls.
    2367             :    */
    2368             :   std::map<dof_id_type, const MeshBase::elemset_type *> _elemset_codes;
    2369             :   std::map<MeshBase::elemset_type, dof_id_type> _elemset_codes_inverse_map;
    2370             :   MeshBase::elemset_type _all_elemset_ids;
    2371             : 
    2372             :   /**
    2373             :    * The "spatial dimension" of the Mesh.  See the documentation for
    2374             :    * Mesh::spatial_dimension() for more information.
    2375             :    */
    2376             :   unsigned char _spatial_dimension;
    2377             : 
    2378             :   /**
    2379             :    * The array of names for integer data associated with each element
    2380             :    * in the mesh
    2381             :    */
    2382             :   std::vector<std::string> _elem_integer_names;
    2383             : 
    2384             :   /**
    2385             :    * The array of default initialization values for integer data
    2386             :    * associated with each element in the mesh
    2387             :    */
    2388             :   std::vector<dof_id_type> _elem_integer_default_values;
    2389             : 
    2390             :   /**
    2391             :    * The array of names for integer data associated with each node
    2392             :    * in the mesh
    2393             :    */
    2394             :   std::vector<std::string> _node_integer_names;
    2395             : 
    2396             :   /**
    2397             :    * The array of default initialization values for integer data
    2398             :    * associated with each node in the mesh
    2399             :    */
    2400             :   std::vector<dof_id_type> _node_integer_default_values;
    2401             : 
    2402             :   /**
    2403             :    * Size extra-integer arrays of all elements in the mesh
    2404             :    */
    2405             :   void size_elem_extra_integers();
    2406             : 
    2407             :   /**
    2408             :    * Size extra-integer arrays of all nodes in the mesh
    2409             :    */
    2410             :   void size_node_extra_integers();
    2411             : 
    2412             :   /**
    2413             :    * Merge extra-integer arrays from an \p other mesh.  Returns two
    2414             :    * mappings from index values in \p other to (possibly newly created)
    2415             :    * index values with the same string name in \p this mesh, the first
    2416             :    * for element integers and the second for node integers.
    2417             :    */
    2418             :   std::pair<std::vector<unsigned int>, std::vector<unsigned int>>
    2419             :     merge_extra_integer_names(const MeshBase & other);
    2420             : 
    2421             :   /**
    2422             :    * The default geometric GhostingFunctor, used to implement standard
    2423             :    * libMesh element ghosting behavior.  We use a base class pointer
    2424             :    * here to avoid dragging in more header dependencies.
    2425             :    */
    2426             :   std::unique_ptr<GhostingFunctor> _default_ghosting;
    2427             : 
    2428             :   /**
    2429             :    * The list of all GhostingFunctor objects to be used when
    2430             :    * distributing a DistributedMesh.
    2431             :    *
    2432             :    * Basically unused by ReplicatedMesh for now, but belongs to
    2433             :    * MeshBase because the cost is trivial.
    2434             :    */
    2435             :   std::vector<GhostingFunctor *> _ghosting_functors;
    2436             : 
    2437             :   /**
    2438             :    * Hang on to references to any GhostingFunctor objects we were
    2439             :    * passed in shared_ptr form
    2440             :    */
    2441             :   std::map<GhostingFunctor *, std::shared_ptr<GhostingFunctor> > _shared_functors;
    2442             : 
    2443             :   // Keep track of any constraint equations that are inherent to the
    2444             :   // mesh, such as FE nodes whose Rational Bernstein values need to be
    2445             :   // constrained in terms of values on spline control nodes.
    2446             :   //
    2447             :   // _constraint_rows[constrained_node][i].first.first is an
    2448             :   // element (e.g. a NodeElem for a spline control node),
    2449             :   // _constraint_rows[constrained_node][i].first.second is the
    2450             :   // local node id of that element which is a constraining node,
    2451             :   // _constraint_rows[constrained_node][i].second is that node's
    2452             :   // constraint coefficient.
    2453             :   constraint_rows_type _constraint_rows;
    2454             : 
    2455             :   /**
    2456             :    * If nonzero, we will call PointLocatorBase::set_close_to_point_tol()
    2457             :    * on any PointLocators that we create.
    2458             :    */
    2459             :   Real _point_locator_close_to_point_tol;
    2460             : 
    2461             :   /**
    2462             :    * The partitioner class is a friend so that it can set
    2463             :    * the number of partitions.
    2464             :    */
    2465             :   friend class Partitioner;
    2466             : 
    2467             :   /**
    2468             :    * The MeshInput classes are friends so that they can set the number
    2469             :    * of partitions.
    2470             :    */
    2471             :   friend class MeshInput<MeshBase>;
    2472             : 
    2473             :   /**
    2474             :    * Make the \p BoundaryInfo class a friend so that
    2475             :    * it can create and interact with \p BoundaryMesh.
    2476             :    */
    2477             :   friend class BoundaryInfo;
    2478             : 
    2479             :   /**
    2480             :    * Make the \p MeshCommunication class a friend so that
    2481             :    * it can directly broadcast *_integer_names
    2482             :    */
    2483             :   friend class MeshCommunication;
    2484             : 
    2485             : 
    2486             :   /**
    2487             :    * The original iterator classes weren't properly const-safe;
    2488             :    * relying on their const-incorrectness is now deprecated.
    2489             :    */
    2490             : #ifdef LIBMESH_ENABLE_DEPRECATED
    2491             : typedef variant_filter_iterator<MeshBase::Predicate, Elem *> elem_filter_iter;
    2492             : 
    2493             : typedef variant_filter_iterator<MeshBase::Predicate,
    2494             :                                 Elem * const,
    2495             :                                 Elem * const &,
    2496             :                                 Elem * const *> const_elem_filter_iter;
    2497             : 
    2498             : typedef variant_filter_iterator<MeshBase::Predicate, Node *> node_filter_iter;
    2499             : 
    2500             : typedef variant_filter_iterator<MeshBase::Predicate,
    2501             :                                 Node * const,
    2502             :                                 Node * const &,
    2503             :                                 Node * const *> const_node_filter_iter;
    2504             : #else
    2505             : typedef variant_filter_iterator<MeshBase::Predicate,
    2506             :                                 Elem * const,
    2507             :                                 Elem * const &,
    2508             :                                 Elem * const *,
    2509             :                                 const Elem * const,
    2510             :                                 const Elem * const &,
    2511             :                                 const Elem * const *> elem_filter_iter;
    2512             : 
    2513             : typedef variant_filter_iterator<MeshBase::Predicate,
    2514             :                                 const Elem * const,
    2515             :                                 const Elem * const &,
    2516             :                                 const Elem * const *> const_elem_filter_iter;
    2517             : 
    2518             : typedef variant_filter_iterator<MeshBase::Predicate,
    2519             :                                 Node * const,
    2520             :                                 Node * const &,
    2521             :                                 Node * const *,
    2522             :                                 const Node * const,
    2523             :                                 const Node * const &,
    2524             :                                 const Node * const *> node_filter_iter;
    2525             : 
    2526             : typedef variant_filter_iterator<MeshBase::Predicate,
    2527             :                                 const Node * const,
    2528             :                                 const Node * const &,
    2529             :                                 const Node * const *> const_node_filter_iter;
    2530             : #endif // LIBMESH_ENABLE_DEPRECATED
    2531             : 
    2532             : };
    2533             : 
    2534             : 
    2535             : 
    2536             : 
    2537             : 
    2538             : 
    2539             : 
    2540             : 
    2541             : 
    2542             : 
    2543             : 
    2544             : /**
    2545             :  * The definition of the element_iterator struct.
    2546             :  */
    2547             : struct
    2548    38234144 : MeshBase::element_iterator : MeshBase::elem_filter_iter
    2549             : {
    2550             :   // Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor
    2551             :   template <typename PredType, typename IterType>
    2552      750764 :   element_iterator (const IterType & d,
    2553             :                     const IterType & e,
    2554             :                     const PredType & p ) :
    2555    29485840 :     elem_filter_iter(d,e,p) {}
    2556             : };
    2557             : 
    2558             : 
    2559             : 
    2560             : 
    2561             : /**
    2562             :  * The definition of the const_element_iterator struct.  It is similar to the regular
    2563             :  * iterator above, but also provides an additional conversion-to-const ctor.
    2564             :  */
    2565             : struct
    2566    74489834 : MeshBase::const_element_iterator : MeshBase::const_elem_filter_iter
    2567             : {
    2568             :   /**
    2569             :    * Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor.
    2570             :    */
    2571             :   template <typename PredType, typename IterType>
    2572     9044078 :   const_element_iterator (const IterType & d,
    2573             :                           const IterType & e,
    2574             :                           const PredType & p ) :
    2575    44102088 :     const_elem_filter_iter(d,e,p)  {}
    2576             : 
    2577             :   /**
    2578             :    * The conversion-to-const ctor.  Takes a regular iterator and calls the appropriate
    2579             :    * variant_filter_iterator copy constructor.
    2580             :    *
    2581             :    * \note This one is \e not templated!
    2582             :    */
    2583     6298692 :   const_element_iterator (const MeshBase::element_iterator & rhs) :
    2584     3496812 :     const_elem_filter_iter(rhs) {}
    2585             : };
    2586             : 
    2587             : 
    2588             : 
    2589             : 
    2590             : 
    2591             : 
    2592             : 
    2593             : /**
    2594             :  * The definition of the node_iterator struct.
    2595             :  */
    2596             : struct
    2597    12728526 : MeshBase::node_iterator : MeshBase::node_filter_iter
    2598             : {
    2599             :   /**
    2600             :    * Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor.
    2601             :    */
    2602             :   template <typename PredType, typename IterType>
    2603      359142 :   node_iterator (const IterType & d,
    2604             :                  const IterType & e,
    2605             :                  const PredType & p ) :
    2606    11367230 :     node_filter_iter(d,e,p)  {}
    2607             : };
    2608             : 
    2609             : 
    2610             : 
    2611             : 
    2612             : /**
    2613             :  * The definition of the const_node_iterator struct.  It is similar to the regular
    2614             :  * iterator above, but also provides an additional conversion-to-const ctor.
    2615             :  */
    2616             : struct
    2617     8681503 : MeshBase::const_node_iterator : MeshBase::const_node_filter_iter
    2618             : {
    2619             :   /**
    2620             :    * Templated forwarding ctor -- forwards to appropriate variant_filter_iterator ctor.
    2621             :    */
    2622             :   template <typename PredType, typename IterType>
    2623      534028 :   const_node_iterator (const IterType & d,
    2624             :                        const IterType & e,
    2625             :                        const PredType & p ) :
    2626     8959909 :     const_node_filter_iter(d,e,p)  {}
    2627             : 
    2628             :   /**
    2629             :    * The conversion-to-const ctor.  Takes a regular iterator and calls the appropriate
    2630             :    * variant_filter_iterator copy constructor.
    2631             :    *
    2632             :    * \note This one is *not* templated!
    2633             :    */
    2634       39260 :   const_node_iterator (const MeshBase::node_iterator & rhs) :
    2635       20196 :     const_node_filter_iter(rhs) {}
    2636             : };
    2637             : 
    2638             : 
    2639             : // ------------------------------------------------------------
    2640             : // Elem class member functions
    2641             : inline
    2642       99885 : const std::set<unsigned char> & MeshBase::elem_dimensions() const
    2643             : {
    2644       99885 :   libmesh_assert(_preparation.has_cached_elem_data);
    2645       99885 :   return _elem_dims;
    2646             : }
    2647             : 
    2648             : 
    2649             : inline
    2650           0 : const std::set<Order> & MeshBase::elem_default_orders() const
    2651             : {
    2652           0 :   libmesh_assert(_preparation.has_cached_elem_data);
    2653           0 :   return _elem_default_orders;
    2654             : }
    2655             : 
    2656             : 
    2657             : inline
    2658          12 : Order MeshBase::supported_nodal_order() const
    2659             : {
    2660          12 :   libmesh_assert(_preparation.has_cached_elem_data);
    2661         414 :   return _supported_nodal_order;
    2662             : }
    2663             : 
    2664             : 
    2665             : inline
    2666             : const std::set<subdomain_id_type> & MeshBase::get_mesh_subdomains() const
    2667             : {
    2668             :   libmesh_assert(_preparation.has_cached_elem_data);
    2669             :   return _mesh_subdomains;
    2670             : }
    2671             : 
    2672             : 
    2673             : inline
    2674        7824 : unsigned int MeshBase::spatial_dimension () const
    2675             : {
    2676        7824 :   libmesh_assert(_preparation.has_cached_elem_data);
    2677             : 
    2678      238663 :   return cast_int<unsigned int>(_spatial_dimension);
    2679             : }
    2680             : 
    2681             : template <typename T>
    2682             : inline
    2683             : unsigned int MeshBase::add_elem_datum(const std::string & name,
    2684             :                                       bool allocate_data,
    2685             :                                       const T * default_value)
    2686             : {
    2687             :   const std::size_t old_size = _elem_integer_names.size();
    2688             : 
    2689             :   unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
    2690             :   std::vector<dof_id_type> int_data(n_more_integers+1, DofObject::invalid_id);
    2691             :   if (default_value)
    2692             :     std::memcpy(int_data.data(), default_value, sizeof(T));
    2693             : 
    2694             :   unsigned int start_idx = this->add_elem_integer(name, false, int_data[0]);
    2695             :   for (unsigned int i=0; i != n_more_integers; ++i)
    2696             :     this->add_elem_integer(name+"__"+std::to_string(i), false, int_data[i+1]);
    2697             : 
    2698             :   if (allocate_data && old_size != _elem_integer_names.size())
    2699             :     this->size_elem_extra_integers();
    2700             : 
    2701             :   return start_idx;
    2702             : }
    2703             : 
    2704             : 
    2705             : template <typename T>
    2706             : inline
    2707             : std::vector<unsigned int> MeshBase::add_elem_data(const std::vector<std::string> & names,
    2708             :                                                   bool allocate_data,
    2709             :                                                   const std::vector<T> * default_values)
    2710             : {
    2711             :   libmesh_assert(!default_values || default_values->size() == names.size());
    2712             : 
    2713             :   std::vector<unsigned int> returnval(names.size());
    2714             : 
    2715             :   const std::size_t old_size = _elem_integer_names.size();
    2716             : 
    2717             :   for (auto i : index_range(names))
    2718             :     returnval[i] =
    2719             :       this->add_elem_datum<T>(names[i], false,
    2720             :                               default_values ?
    2721             :                               (*default_values)[i] : nullptr);
    2722             : 
    2723             :   if (allocate_data && old_size != _elem_integer_names.size())
    2724             :     this->size_elem_extra_integers();
    2725             : 
    2726             :   return returnval;
    2727             : }
    2728             : 
    2729             : 
    2730             : template <typename T>
    2731             : inline
    2732          72 : unsigned int MeshBase::add_node_datum(const std::string & name,
    2733             :                                       bool allocate_data,
    2734             :                                       const T * default_value)
    2735             : {
    2736          12 :   const std::size_t old_size = _node_integer_names.size();
    2737             : 
    2738           6 :   unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
    2739          72 :   std::vector<dof_id_type> int_data(n_more_integers+1, DofObject::invalid_id);
    2740          72 :   if (default_value)
    2741          72 :     std::memcpy(int_data.data(), default_value, sizeof(T));
    2742             : 
    2743          78 :   unsigned int start_idx = this->add_node_integer(name, false, int_data[0]);
    2744          36 :   for (unsigned int i=0; i != n_more_integers; ++i)
    2745          36 :     this->add_node_integer(name+"__"+std::to_string(i), false, int_data[i+1]);
    2746             : 
    2747          72 :   if (allocate_data && old_size != _node_integer_names.size())
    2748          72 :     this->size_node_extra_integers();
    2749             : 
    2750          78 :   return start_idx;
    2751             : }
    2752             : 
    2753             : 
    2754             : template <typename T>
    2755             : inline
    2756             : std::vector<unsigned int> MeshBase::add_node_data(const std::vector<std::string> & names,
    2757             :                                                   bool allocate_data,
    2758             :                                                   const std::vector<T> * default_values)
    2759             : {
    2760             :   libmesh_assert(!default_values || default_values->size() == names.size());
    2761             : 
    2762             :   std::vector<unsigned int> returnval(names.size());
    2763             : 
    2764             :   const std::size_t old_size = _node_integer_names.size();
    2765             : 
    2766             :   for (auto i : index_range(names))
    2767             :     returnval[i] =
    2768             :       this->add_node_datum<T>(names[i], false,
    2769             :                               default_values ?
    2770             :                               (*default_values)[i] : nullptr);
    2771             : 
    2772             :   if (allocate_data && old_size != _node_integer_names.size())
    2773             :     this->size_node_extra_integers();
    2774             : 
    2775             :   return returnval;
    2776             : }
    2777             : 
    2778             : 
    2779             : 
    2780             : } // namespace libMesh
    2781             : 
    2782             : #endif // LIBMESH_MESH_BASE_H

Generated by: LCOV version 1.14