LCOV - code coverage report
Current view: top level - include/base - dof_object.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 220 239 92.1 %
Date: 2025-08-19 19:27:09 Functions: 47 49 95.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : #ifndef LIBMESH_DOF_OBJECT_H
      21             : #define LIBMESH_DOF_OBJECT_H
      22             : 
      23             : // Local includes
      24             : #include "libmesh/id_types.h"
      25             : #include "libmesh/int_range.h"
      26             : #include "libmesh/libmesh_config.h"
      27             : #include "libmesh/libmesh_common.h"
      28             : #include "libmesh/libmesh.h" // libMesh::invalid_uint
      29             : #include "libmesh/reference_counted_object.h"
      30             : 
      31             : // C++ includes
      32             : #include <cstddef>
      33             : #include <cstring>
      34             : #include <vector>
      35             : #include <memory>
      36             : 
      37             : namespace libMesh
      38             : {
      39             : 
      40             : // Forward declarations
      41             : class DofObject;
      42             : 
      43             : 
      44             : /**
      45             :  * The \p DofObject defines an abstract base class for objects that
      46             :  * have degrees of freedom associated with them.  Examples of such
      47             :  * objects are the \p Node and \p Elem classes.  This class can
      48             :  * not be instantiated, only derived from.
      49             :  *
      50             :  * \author Benjamin S. Kirk
      51             :  * \date 2003, 2011
      52             :  */
      53             : 
      54             : class DofObject : public ReferenceCountedObject<DofObject>
      55             : {
      56             : #ifdef LIBMESH_IS_UNIT_TESTING
      57             : public:
      58             : #else
      59             : protected:
      60             : #endif
      61             : 
      62             :   /**
      63             :    * Constructor. Protected so that you can't instantiate one of these
      64             :    * except as a part of a Node or Elem.
      65             :    */
      66             :   DofObject ();
      67             : 
      68             : public:
      69             : 
      70             :   /**
      71             :    * Destructor.
      72             :    */
      73   530887926 :   ~DofObject () = default;
      74             : 
      75             : #ifdef LIBMESH_ENABLE_AMR
      76             : 
      77             :   /**
      78             :    * This object on the last mesh.  Useful for projecting
      79             :    * solutions from one mesh to another.
      80             :    *
      81             :    * Public access to old_dof_object is now officially deprecated and will
      82             :    * be removed in future libMesh versions.  Use the \p get_old_dof_object()
      83             :    * accessor instead.
      84             :    */
      85             : #ifndef LIBMESH_ENABLE_DEPRECATED
      86             : protected:
      87             : #endif
      88             :   std::unique_ptr<DofObject> old_dof_object;
      89             : 
      90             : public:
      91             :   /**
      92             :    * Pointer accessor for previously public old_dof_object. If you
      93             :    * want to assert that the old_dof_object pointer is valid as well,
      94             :    * consider using the get_old_dof_object_ref() accessor instead.
      95             :    */
      96     8988934 :   DofObject * get_old_dof_object() { return old_dof_object.get(); }
      97     2837911 :   const DofObject * get_old_dof_object() const  { return old_dof_object.get(); }
      98             : 
      99             :   /**
     100             :    * As above, but do not use in situations where the old_dof_object
     101             :    * may be nullptr, since this function asserts that the
     102             :    * old_dof_object is valid before returning a reference to it.
     103             :    */
     104             :   DofObject & get_old_dof_object_ref()
     105             :   {
     106             :     libmesh_assert(old_dof_object);
     107             :     return *old_dof_object;
     108             :   }
     109             : 
     110     7305032 :   const DofObject & get_old_dof_object_ref() const
     111             :   {
     112     7305032 :     libmesh_assert(old_dof_object);
     113     7305032 :     return *old_dof_object;
     114             :   }
     115             : 
     116             :   /**
     117             :    * Sets the \p old_dof_object to nullptr
     118             :    */
     119             :   void clear_old_dof_object ();
     120             : 
     121             :   /**
     122             :    * Sets the \p old_dof_object to a copy of \p this
     123             :    */
     124             :   void set_old_dof_object ();
     125             : 
     126             : #endif
     127             : 
     128             :   /**
     129             :    * Clear the \p DofMap data structures holding degree of freedom
     130             :    * data.
     131             :    *
     132             :    * If any extra integers are associated with this \p DofObject,
     133             :    * their count and values are unchanged.
     134             :    */
     135             :   void clear_dofs ();
     136             : 
     137             :   /**
     138             :    * Sets all degree of freedom numbers to \p invalid_id
     139             :    */
     140             :   void invalidate_dofs (const unsigned int sys_num = libMesh::invalid_uint);
     141             : 
     142             :   /**
     143             :    * Sets the id to \p invalid_id
     144             :    */
     145             :   void invalidate_id ();
     146             : 
     147             :   /**
     148             :    * Sets the processor id to \p invalid_processor_id
     149             :    */
     150             :   void invalidate_processor_id ();
     151             : 
     152             :   /**
     153             :    * Invalidates all the indices for this \p DofObject
     154             :    */
     155             :   void invalidate ();
     156             : 
     157             :   /**
     158             :    * \returns The number of degrees of freedom associated with
     159             :    * system \p s directly stored on this object. Optionally only
     160             :    * degrees of freedom for variable number \p var are counted.  Does
     161             :    * not count degrees of freedom only indirectly associated with this
     162             :    * object, such as those stored on an element's nodes when \p
     163             :    * n_dofs() is called on the element itself.
     164             :    */
     165             :   unsigned int n_dofs (const unsigned int s,
     166             :                        const unsigned int var =
     167             :                        libMesh::invalid_uint) const;
     168             : 
     169             :   /**
     170             :    * \returns The \p id for this \p DofObject
     171             :    */
     172             :   dof_id_type id () const;
     173             : 
     174             :   /**
     175             :    * \returns The \p id for this \p DofObject as a writable reference.
     176             :    */
     177             :   dof_id_type & set_id ();
     178             : 
     179             :   /**
     180             :    * \returns The globally \p unique_id for this \p DofObject
     181             :    */
     182             :   unique_id_type unique_id () const;
     183             : 
     184             : #ifdef LIBMESH_ENABLE_DEPRECATED
     185             :   /**
     186             :    * \returns The globally \p unique_id for this \p DofObject as a
     187             :    * writable reference.  Deprecated; use the API taking an input
     188             :    * instead.
     189             :    */
     190             :   unique_id_type & set_unique_id ();
     191             : #endif // LIBMESH_ENABLE_DEPRECATED
     192             : 
     193             :   /**
     194             :    * Sets the \p unique_id for this \p DofObject
     195             :    */
     196             :   void set_unique_id (unique_id_type new_id);
     197             : 
     198             :   /**
     199             :    * Sets the \p id for this \p DofObject
     200             :    */
     201    62853849 :   void set_id (const dof_id_type dofid)
     202  1363566741 :   { this->set_id() = dofid; }
     203             : 
     204             :   /**
     205             :    * \returns \p true if this \p DofObject has a valid \p id set,
     206             :    * \p false otherwise.
     207             :    */
     208             :   bool valid_id () const;
     209             : 
     210             :   /**
     211             :    * \returns \p true if this \p DofObject has a valid \p unique_id set,
     212             :    * \p false otherwise.
     213             :    */
     214             :   bool valid_unique_id () const;
     215             : 
     216             :   /**
     217             :    * \returns The processor that this DofObject belongs to.
     218             :    *
     219             :    * When partitioning and DoF numbering have been performed by
     220             :    * libMesh, every current DoF on this DofObject will belong to its
     221             :    * processor.
     222             :    */
     223             :   processor_id_type processor_id () const;
     224             : 
     225             :   /**
     226             :    * \returns The processor that this DofObject belongs to as a
     227             :    * writable reference.
     228             :    */
     229             :   processor_id_type & processor_id ();
     230             : 
     231             :   /**
     232             :    * Sets the \p processor_id for this \p DofObject.
     233             :    */
     234             :   void processor_id (const processor_id_type pid);
     235             : 
     236             :   /**
     237             :    * \returns \p true if this \p DofObject has a valid \p id set,
     238             :    * \p false otherwise.
     239             :    */
     240             :   bool valid_processor_id () const;
     241             : 
     242             :   /**
     243             :    * \returns The number of systems associated with this
     244             :    * \p DofObject
     245             :    */
     246             :   unsigned int n_systems() const;
     247             : 
     248             :   /**
     249             :    * \returns The total number of pseudo-systems associated with this
     250             :    * \p DofObject :
     251             :    * n_systems(), plus one iff \p this->has_extra_integers()
     252             :    */
     253             :   unsigned int n_pseudo_systems() const;
     254             : 
     255             :   /**
     256             :    * Sets the number of systems for this \p DofObject.  If this number
     257             :    * is a change, also clears all variable count and DoF indexing
     258             :    * associated with this \p DofObject.
     259             :    *
     260             :    * If any extra integers are associated with this \p DofObject,
     261             :    * their count and values are unchanged.
     262             :    */
     263             :   void set_n_systems (const unsigned int s);
     264             : 
     265             :   /**
     266             :    * Sets the value on this object of the extra integer associated
     267             :    * with \p index, which should have been obtained via a call to \p
     268             :    * MeshBase::add_elem_integer or \p MeshBase::add_node_integer
     269             :    */
     270             :   void set_extra_integer (const unsigned int index, const dof_id_type value);
     271             : 
     272             :   /**
     273             :    * Gets the value on this object of the extra integer associated
     274             :    * with \p index, which should have been obtained via a call to \p
     275             :    * MeshBase::add_elem_integer or \p MeshBase::add_node_integer
     276             :    */
     277             :   dof_id_type get_extra_integer (const unsigned int index) const;
     278             : 
     279             :   /**
     280             :    * Sets the value on this object of the extra datum associated
     281             :    * with \p index, which should have been obtained via a call to \p
     282             :    * MeshBase::add_elem_datum or \p MeshBase::add_node_datum using
     283             :    * the same type T.
     284             :    */
     285             :   template <typename T>
     286             :   void set_extra_datum (const unsigned int index, const T value);
     287             : 
     288             :   /**
     289             :    * Gets the value on this object of the extra datum associated
     290             :    * with \p index, which should have been obtained via a call to \p
     291             :    * MeshBase::add_elem_datum or \p MeshBase::add_node_datum using
     292             :    * the same type T.
     293             :    */
     294             :   template <typename T>
     295             :   T get_extra_datum (const unsigned int index) const;
     296             : 
     297             : 
     298             :   /**
     299             :    * Adds an additional system to the \p DofObject
     300             :    */
     301             :   void add_system ();
     302             : 
     303             :   /**
     304             :    * \returns The number of \p VariableGroup variable groups
     305             :    * associated with system \p s for this \p DofObject
     306             :    */
     307             :   unsigned int n_var_groups(const unsigned int s) const;
     308             : 
     309             :   /**
     310             :    * \returns The number of \p Variable variables associated
     311             :    * with \p VariableGroup \p vg in system \p s for this \p DofObject
     312             :    */
     313             :   unsigned int n_vars(const unsigned int s,
     314             :                       const unsigned int vg) const;
     315             : 
     316             :   /**
     317             :    * \returns The number of \p Variable variables associated
     318             :    * with system \p s for this \p DofObject
     319             :    */
     320             :   unsigned int n_vars(const unsigned int s) const;
     321             : 
     322             :   /**
     323             :    * Sets number of variables in each group associated with system \p s for this
     324             :    * \p DofObject. Implicit in this is also setting the number of \p VariableGroup
     325             :    * variable groups for the system.
     326             :    * Has the effect of setting the number of components
     327             :    * to 0 even when called even with (nvg == this->n_var_groups(s)).
     328             :    */
     329             :   void set_n_vars_per_group(const unsigned int s,
     330             :                             const std::vector<unsigned int> & nvpg);
     331             : 
     332             :   /**
     333             :    * \returns The number of components for variable \p var
     334             :    * of system \p s associated with this \p DofObject.
     335             :    * For example, the \p HIERARCHIC shape functions may
     336             :    * have multiple DoFs associated with one node.  Another
     337             :    * example is the \p MONOMIALs, where only the elements
     338             :    * hold the DoFs.  For the different spatial directions,
     339             :    * and orders, see \p FE.
     340             :    */
     341             :   unsigned int n_comp(const unsigned int s,
     342             :                       const unsigned int var) const;
     343             : 
     344             :   /**
     345             :    * \returns The number of components for \p VariableGroup \p vg
     346             :    * of system \p s associated with this \p DofObject.
     347             :    * For example, the \p HIERARCHIC shape functions may
     348             :    * have multiple DoFs associated with one node.  Another
     349             :    * example is the \p MONOMIALs, where only the elements
     350             :    * hold the DoFs.  For the different spatial directions,
     351             :    * and orders, see \p FE.
     352             :    */
     353             :   unsigned int n_comp_group(const unsigned int s,
     354             :                             const unsigned int vg) const;
     355             : 
     356             :   /**
     357             :    * Sets the number of components for \p Variable \p var
     358             :    * of system \p s associated with this \p DofObject
     359             :    */
     360             :   void set_n_comp(const unsigned int s,
     361             :                   const unsigned int var,
     362             :                   const unsigned int ncomp);
     363             : 
     364             :   /**
     365             :    * Sets the number of components for \p VariableGroup \p vg
     366             :    * of system \p s associated with this \p DofObject
     367             :    */
     368             :   void set_n_comp_group(const unsigned int s,
     369             :                         const unsigned int vg,
     370             :                         const unsigned int ncomp);
     371             : 
     372             :   /**
     373             :    * \returns The global degree of freedom number for variable \p var,
     374             :    * component \p comp for system \p s associated with this \p DofObject
     375             :    *
     376             :    * When partitioning and DoF numbering have been performed by
     377             :    * libMesh, every current DoF on this DofObject will belong to its
     378             :    * processor.
     379             :    */
     380             :   dof_id_type dof_number(const unsigned int s,
     381             :                          const unsigned int var,
     382             :                          const unsigned int comp) const;
     383             : 
     384             :   /**
     385             :    * \returns The global degree of freedom number for variable group
     386             :    * \p vg, variable index \p vig within the group, component \p comp
     387             :    * out of \p n_comp, for system \p s on this \p DofObject
     388             :    *
     389             :    * Even users who need to call dof_number from user code probably
     390             :    * don't want to call this overload.
     391             :    */
     392             :   dof_id_type dof_number(const unsigned int s,
     393             :                          const unsigned int vg,
     394             :                          const unsigned int vig,
     395             :                          const unsigned int comp,
     396             :                          const unsigned int n_comp) const;
     397             : 
     398             :   /**
     399             :    * \returns A pair consisting of the variable group number and the
     400             :    * offset index from the start of that group for variable \p var on
     401             :    * system \p s associated with this \p DofObject
     402             :    */
     403             :   std::pair<unsigned int, unsigned int>
     404             :   var_to_vg_and_offset(const unsigned int s,
     405             :                        const unsigned int var) const;
     406             : 
     407             :   /**
     408             :    * Sets the global degree of freedom number for variable \p var,
     409             :    * component \p comp for system \p s associated with this \p DofObject
     410             :    */
     411             :   void set_dof_number(const unsigned int s,
     412             :                       const unsigned int var,
     413             :                       const unsigned int comp,
     414             :                       const dof_id_type dn);
     415             : 
     416             :   /**
     417             :    * \returns \p true if any system has variables which have been assigned,
     418             :    * \p false otherwise.
     419             :    */
     420             :   bool has_dofs(const unsigned int s=libMesh::invalid_uint) const;
     421             : 
     422             :   /**
     423             :    * \p VariableGroup DoF indices are indexed as
     424             :    * id = base + var_in_vg*ncomp + comp
     425             :    * This method allows for direct access to the base.
     426             :    */
     427             :   void set_vg_dof_base(const unsigned int s,
     428             :                        const unsigned int vg,
     429             :                        const dof_id_type db);
     430             : 
     431             :   /**
     432             :    * \p VariableGroup DoF indices are indexed as
     433             :    * id = base + var_in_vg*ncomp + comp
     434             :    * This method allows for direct access to the base.
     435             :    */
     436             :   dof_id_type vg_dof_base(const unsigned int s,
     437             :                           const unsigned int vg) const;
     438             : 
     439             :   /**
     440             :    * Assigns a set of extra integers to this \p DofObject.  There will
     441             :    * now be \p n_integers associated; this *replaces*, not augments,
     442             :    * any previous count.
     443             :    *
     444             :    * Any newly-added values will initially be DofObject::invalid_id
     445             :    *
     446             :    * If non-integer data is in the set, each datum of type T should be
     447             :    * counted sizeof(T)/sizeof(dof_id_type) times in \p n_integers.
     448             :    */
     449             :   void add_extra_integers (const unsigned int n_integers);
     450             : 
     451             :   /**
     452             :    * Assigns a set of extra integers to this \p DofObject.  There will
     453             :    * now be \p n_integers associated; this *replaces*, not augments,
     454             :    * any previous count.
     455             :    *
     456             :    * Any newly-added values will be copied from \p default_values.
     457             :    *
     458             :    * If non-integer data is in the set, each datum of type T should be
     459             :    * counted sizeof(T)/sizeof(dof_id_type) times in \p n_integers, and
     460             :    * its data should be expressed in \p default_values as per memcpy.
     461             :    */
     462             :   void add_extra_integers (const unsigned int n_integers,
     463             :                            const std::vector<dof_id_type> & default_values);
     464             : 
     465             :   /**
     466             :    * Returns how many extra integers are associated to the \p DofObject
     467             :    *
     468             :    * If non-integer data has been associated, each datum of type T
     469             :    * counts for sizeof(T)/sizeof(dof_id_type) times in the return
     470             :    * value.
     471             :    */
     472             :   unsigned int n_extra_integers () const;
     473             : 
     474             :   /**
     475             :    * Returns whether extra integers are associated to the \p DofObject
     476             :    */
     477             :   bool has_extra_integers () const;
     478             : 
     479             :   /**
     480             :    * An invalid \p id to distinguish an uninitialized \p DofObject
     481             :    */
     482             :   static const dof_id_type invalid_id = static_cast<dof_id_type>(-1);
     483             : 
     484             :   /**
     485             :    * An invalid \p unique_id to distinguish an uninitialized \p DofObject
     486             :    */
     487             :   static const unique_id_type invalid_unique_id = static_cast<unique_id_type>(-1);
     488             : 
     489             :   /**
     490             :    * An invalid \p processor_id to distinguish DoFs that have
     491             :    * not been assigned to a processor.
     492             :    */
     493             :   static const processor_id_type invalid_processor_id = static_cast<processor_id_type>(-1);
     494             : 
     495             :   /**
     496             :    * If we pack our indices into an buffer for communications, how
     497             :    * many ints do we need?
     498             :    */
     499             :   unsigned int packed_indexing_size() const;
     500             : 
     501             :   /**
     502             :    * If we have indices packed into an buffer for communications, how
     503             :    * much of that buffer applies to this dof object?
     504             :    */
     505             :   static unsigned int unpackable_indexing_size
     506             :   (std::vector<largest_id_type>::const_iterator begin);
     507             : 
     508             :   /**
     509             :    * A method for creating our index buffer from packed data -
     510             :    * basically with our current implementation we investigate the size
     511             :    * term and then copy.
     512             :    */
     513             :   void unpack_indexing(std::vector<largest_id_type>::const_iterator begin);
     514             : 
     515             :   /**
     516             :    * A method for creating packed data from our index buffer -
     517             :    * basically a copy with prepended size with our current
     518             :    * implementation.
     519             :    */
     520             :   void pack_indexing(std::back_insert_iterator<std::vector<largest_id_type>> target) const;
     521             : 
     522             :   /**
     523             :    * Print our buffer for debugging.
     524             :    */
     525             :   void debug_buffer () const;
     526             : 
     527             :   /**
     528             :    * Print out info for debugging.
     529             :    */
     530             :   void print_dof_info() const;
     531             : 
     532             :   // Deep copy (or almost-copy) of DofObjects is solely for a couple
     533             :   // tricky internal uses.
     534             : private:
     535             : 
     536             :   /**
     537             :    * "Copy"-constructor.  Does not copy old_dof_object, but leaves it
     538             :    * null in the new object.
     539             :    */
     540             :   DofObject (const DofObject &);
     541             : 
     542             :   /**
     543             :    * Convenient factory function that calls either the (deep) copy
     544             :    * constructor or the default constructor depending on the input
     545             :    * arg. Like the copy constructor, this function is also private. We
     546             :    * can't use std::make_unique to construct a DofObject since the
     547             :    * copy constructor is private, but we can at least encapsulate the
     548             :    * code which calls "new" directly.
     549             :    */
     550             :   std::unique_ptr<DofObject>
     551             :   construct(const DofObject * other = nullptr);
     552             : 
     553             :   /**
     554             :    * Deep-copying assignment operator
     555             :    */
     556             :   DofObject & operator= (const DofObject & dof_obj);
     557             : 
     558             :   /**
     559             :    * Utility function - for variable \p var in system \p s, figure out what
     560             :    * variable group it lives in.
     561             :    */
     562             :   unsigned int var_to_vg (const unsigned int s,
     563             :                           const unsigned int var) const;
     564             : 
     565             :   /**
     566             :    * Utility function - for variable \p var in system \p s, figure out what
     567             :    * variable group it lives in.
     568             :    */
     569             :   unsigned int system_var_to_vg_var (const unsigned int s,
     570             :                                      const unsigned int vg,
     571             :                                      const unsigned int var) const;
     572             : 
     573             :   /**
     574             :    * A globally unique id, guaranteed not to change as the mesh is repartitioned or adapted
     575             :    */
     576             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     577             :   unique_id_type _unique_id;
     578             : #endif
     579             : 
     580             :   /**
     581             :    * The \p id of the \p DofObject
     582             :    */
     583             :   dof_id_type _id;
     584             : 
     585             :   /**
     586             :    * The \p processor_id of the \p DofObject.
     587             :    * Degrees of freedom are wholly owned by processors,
     588             :    * however they may be duplicated on other processors.
     589             :    *
     590             :    * This is stored as an unsigned short int since we cannot
     591             :    * expect to be solving on 65000+ processors any time soon,
     592             :    * can we??
     593             :    */
     594             :   processor_id_type _processor_id;
     595             : 
     596             :   /**
     597             :    * DoF index information.  This is packed into a contiguous buffer of the following format:
     598             :    *
     599             :    * \verbatim
     600             :    * [hdr end_0 end_1 ... end_{nps-2} (ncv_0 idx_0 ncv_1 idx_1 ... ncv_nv idx_nv)_0
     601             :    *                                  (ncv_0 idx_0 ncv_1 idx_1 ... ncv_nv idx_nv)_1
     602             :    *                                   ...
     603             :    *                                  (ncv_0 idx_0 ncv_1 idx_1 ... ncv_nv idx_nv)_{nps-2} ]
     604             :    * \endverbatim
     605             :    *
     606             :    * 'hdr' determines whether this \p DofObject \p has_extra_integers()
     607             :    * associated with it; iff so then it is negative.
     608             :    *
     609             :    * The total number of "pseudo systems" is nps := abs(hdr).
     610             :    *
     611             :    * The total number of true systems is
     612             :    * \verbatim
     613             :    * ns = hdr,            hdr >= 0
     614             :    *    = abs(hdr) - 1,   otherwise.
     615             :    * \endverbatim
     616             :    *
     617             :    * 'end_s' is the index past the end of the variable group (or
     618             :    * integer) storage for (pseudo) system \p s.
     619             :    *
     620             :    * \note We specifically do not store the end for the last (pseudo)
     621             :    * system - this always _idx_buf.size().
     622             :    *
     623             :    * As a first example, consider the case of 4 systems, with 3, 0, 1,
     624             :    * 2 variable groups, respectively.  The _idx_buf then looks like:
     625             :    *
     626             :    * \verbatim
     627             :    * [4 10 10 12 () (ncv_0 idx_0 ncv_1 idx_1 ncv_2 idx_2) () (ncv_0 idx_0) (ncv_0 idx_0 ncv_1 idx_1)]
     628             :    * [0  1  2  3         4     5     6     7     8     9         10    11      12    13    14    15]
     629             :    * \endverbatim
     630             :    *
     631             :    * The ending index for each (pseudo) system is then given by:
     632             :    *
     633             :    * \verbatim
     634             :    * end_s = _idx_buf.size(),                        s == (nps-1),
     635             :    *       = _idx_buf[s+1] + has_extra_integers(),   otherwise.
     636             :    * \endverbatim
     637             :    *
     638             :    * The starting indices are not specifically stored, but rather inferred as follows:
     639             :    *
     640             :    * start_s = abs(_idx_buf[s])
     641             :    *
     642             :    * Now, the defining characteristic of the \p VariableGroup is that it supports
     643             :    * an arbitrary number of variables of the same type.  At the \p DofObject level, what
     644             :    * that means is that each \p Variable in the \p VariableGroup will have the same number
     645             :    * of nonzero components, and they can all be indexed from the same base number.  We use this
     646             :    * information in the ncv_# and idx_# entries as follows:
     647             :    *
     648             :    * ncv_# = n_vars*ncv_magic + n_comp      for variable group #
     649             :    * idx_# = base_offset                    for variable group #
     650             :    *
     651             :    * the DoF index for a particular component c of variable v within that group is then given by
     652             :    *
     653             :    * idx_var = idx_# + n_comp*v + c
     654             :    *
     655             :    * \note There is a subtlety here - "variable v within that group" usually means nothing to the
     656             :    * user. This class is either indexed with variable group numbers, or variable numbers counted
     657             :    * *within the system*. So for a system with 2 variable groups, 4 and 8 variables each,
     658             :    * the 5th variable in the system is the 1st variable in 2nd variable group.
     659             :    * (Now of course 0-base everything...  but you get the idea.)
     660             :    *
     661             :    * When hdr is *negative* when cast to a signed type, then we
     662             :    * interpret that to mean there exists one pseudo-system following
     663             :    * the true systems, one for which the _idx_buf data stores the
     664             :    * values associated with add_extra_integer entries, not ncv and idx
     665             :    * data associated with system variables.  We still return only the
     666             :    * number of true systems for n_systems(), but we report
     667             :    * has_extra_integers() as true iff hdr is negative, and abs(hdr)
     668             :    * will reflect the total number of pseudo-systems, n_systems()+1.
     669             :    *
     670             :    * E.g. if we had added two extra integers to the example case
     671             :    * above, the _idx_buf then looks like:
     672             :    *
     673             :    * \verbatim
     674             :    * [-5 11 11 13 17 () (ncv_0 idx_0 ncv_1 idx_1 ncv_2 idx_2) () (ncv_0 idx_0) (ncv_0 idx_0 ncv_1 idx_1) (xtra1 xtra2)]
     675             :    * [0   1  2  3  4         5     6     7     8     9    10         11    12      13    14    15    16      17    18]
     676             :    * \endverbatim
     677             :    */
     678             :   typedef dof_id_type index_t;
     679             :   typedef std::vector<index_t> index_buffer_t;
     680             :   index_buffer_t _idx_buf;
     681             : 
     682             :   /**
     683             :    * Above we introduced the chimera ncv, which is a hybrid of the form
     684             :    * ncv = ncv_magic*nv + nc
     685             :    * where nv are the number of identical variables of a given type,
     686             :    * and nc is the number of components for this set of variables.
     687             :    *
     688             :    * It is hoped that by setting this to a power of two, an optimizing compiler
     689             :    * will recognize later that  #/ncv_magic is simply a bitshift
     690             :    */
     691             :   static const index_t ncv_magic = 256; // = 2^8, in case we want to manually bitshift
     692             :   static const index_t ncv_magic_exp = 8; // Let's manually bitshift
     693             : 
     694             :   /**
     695             :    * The starting index for system \p s.
     696             :    */
     697             :   unsigned int start_idx(const unsigned int s) const;
     698             : 
     699             :   /**
     700             :    * The ending index for system \p s.
     701             :    */
     702             :   unsigned int end_idx(const unsigned int s) const;
     703             : 
     704             :   /**
     705             :    * The starting index for an extra_integers pseudosystem
     706             :    */
     707             :   unsigned int start_idx_ints() const;
     708             : 
     709             :   /**
     710             :    * The ending index for an extra_integers pseudosystem
     711             :    */
     712             :   unsigned int end_idx_ints() const;
     713             : 
     714             :   // methods only available for unit testing
     715             : #ifdef LIBMESH_IS_UNIT_TESTING
     716             : public:
     717             :   void set_buffer (const std::vector<dof_id_type> & buf)
     718             :   { _idx_buf = buf; }
     719             : #endif
     720             : };
     721             : 
     722             : 
     723             : 
     724             : //------------------------------------------------------
     725             : // Inline functions
     726             : inline
     727  1222815042 : DofObject::DofObject () :
     728             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     729   747045937 :   _unique_id (invalid_unique_id),
     730             : #endif
     731   747045937 :   _id (invalid_id),
     732  1222815042 :   _processor_id (invalid_processor_id)
     733             : {
     734    58178816 :   this->invalidate();
     735  1222815042 : }
     736             : 
     737             : 
     738             : 
     739             : inline
     740             : std::unique_ptr<DofObject>
     741    26303964 : DofObject::construct(const DofObject * other)
     742             : {
     743             :   return other
     744    26303655 :     ? std::unique_ptr<DofObject>(new DofObject(*other))
     745    39651940 :     : std::unique_ptr<DofObject>(new DofObject());
     746             : }
     747             : 
     748             : 
     749             : 
     750             : inline
     751   956458849 : void DofObject::invalidate_dofs (const unsigned int sys_num)
     752             : {
     753    62631376 :   const unsigned int n_sys = this->n_systems();
     754             :   // If the user does not specify the system number...
     755   956458849 :   if (sys_num >= n_sys)
     756             :     {
     757   892687239 :       for (auto s : make_range(n_sys))
     758           0 :         for (auto vg : make_range(this->n_var_groups(s)))
     759           0 :           if (this->n_comp_group(s,vg))
     760           0 :             this->set_vg_dof_base(s,vg,invalid_id);
     761             :     }
     762             :   // ...otherwise invalidate the dofs for all systems
     763             :   else
     764   145100548 :     for (auto vg : make_range(this->n_var_groups(sys_num)))
     765    81328938 :       if (this->n_comp_group(sys_num,vg))
     766     2329408 :         this->set_vg_dof_base(sys_num,vg,invalid_id);
     767   956458849 : }
     768             : 
     769             : 
     770             : 
     771             : inline
     772    58178816 : void DofObject::invalidate_id ()
     773             : {
     774    58178816 :   this->set_id (invalid_id);
     775    58178816 : }
     776             : 
     777             : 
     778             : 
     779             : inline
     780    59859476 : void DofObject::invalidate_processor_id ()
     781             : {
     782    59859476 :   this->processor_id (invalid_processor_id);
     783    59859476 : }
     784             : 
     785             : 
     786             : 
     787             : inline
     788    58178816 : void DofObject::invalidate ()
     789             : {
     790  1222815042 :   this->invalidate_dofs ();
     791    58178816 :   this->invalidate_id ();
     792    58178816 :   this->invalidate_processor_id ();
     793    58178816 : }
     794             : 
     795             : 
     796             : 
     797             : inline
     798             : void DofObject::clear_dofs ()
     799             : {
     800             :   this->set_n_systems(0);
     801             : }
     802             : 
     803             : 
     804             : 
     805             : inline
     806      357872 : unsigned int DofObject::n_dofs (const unsigned int s,
     807             :                                 const unsigned int var) const
     808             : {
     809       38345 :   libmesh_assert_less (s, this->n_systems());
     810             : 
     811       38345 :   unsigned int num = 0;
     812             : 
     813             :   // Count all variables
     814      357872 :   if (var == libMesh::invalid_uint)
     815      103184 :     for (auto v : make_range(this->n_vars(s)))
     816       77388 :       num += this->n_comp(s,v);
     817             : 
     818             :   // Only count specified variable
     819             :   else
     820      332076 :     num = this->n_comp(s,var);
     821             : 
     822      357872 :   return num;
     823             : }
     824             : 
     825             : 
     826             : 
     827             : inline
     828  3669768884 : dof_id_type DofObject::id () const
     829             : {
     830  9707526774 :   return _id;
     831             : }
     832             : 
     833             : 
     834             : 
     835             : inline
     836    68448956 : dof_id_type & DofObject::set_id ()
     837             : {
     838    68448956 :   return _id;
     839             : }
     840             : 
     841             : 
     842             : 
     843             : inline
     844    37115562 : unique_id_type DofObject::unique_id () const
     845             : {
     846             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     847    37115562 :   libmesh_assert (this->valid_unique_id());
     848   141150947 :   return _unique_id;
     849             : #else
     850             :   return invalid_unique_id;
     851             : #endif
     852             : }
     853             : 
     854             : 
     855             : 
     856             : #ifdef LIBMESH_ENABLE_DEPRECATED
     857             : inline
     858             : unique_id_type & DofObject::set_unique_id ()
     859             : {
     860             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     861             :   libmesh_deprecated();
     862             :   return _unique_id;
     863             : #else
     864             :   libmesh_not_implemented();
     865             : #endif
     866             : }
     867             : #endif // LIBMESH_ENABLE_DEPRECATED
     868             : 
     869             : 
     870             : 
     871             : inline
     872     2626199 : void DofObject::set_unique_id (unique_id_type new_id)
     873             : {
     874             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     875   138081809 :   _unique_id = new_id;
     876             : #else
     877             :   libmesh_ignore(new_id);
     878             :   libmesh_not_implemented();
     879             : #endif
     880    22925410 : }
     881             : 
     882             : 
     883             : 
     884             : inline
     885      904488 : bool DofObject::valid_id () const
     886             : {
     887   216322573 :   return (DofObject::invalid_id != _id);
     888             : }
     889             : 
     890             : 
     891             : 
     892             : inline
     893    39496758 : bool DofObject::valid_unique_id () const
     894             : {
     895             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     896   342617030 :   return (DofObject::invalid_unique_id != _unique_id);
     897             : #else
     898             :   return false;
     899             : #endif
     900             : }
     901             : 
     902             : 
     903             : 
     904             : inline
     905    77927465 : processor_id_type DofObject::processor_id () const
     906             : {
     907  1226611922 :   return _processor_id;
     908             : }
     909             : 
     910             : 
     911             : 
     912             : inline
     913   330003664 : processor_id_type & DofObject::processor_id ()
     914             : {
     915   586600635 :   return _processor_id;
     916             : }
     917             : 
     918             : 
     919             : 
     920             : inline
     921    91255066 : void DofObject::processor_id (const processor_id_type pid)
     922             : {
     923  1449962078 :   this->processor_id() = pid;
     924    91255066 : }
     925             : 
     926             : 
     927             : 
     928             : inline
     929       41506 : bool DofObject::valid_processor_id () const
     930             : {
     931       41506 :   return (DofObject::invalid_processor_id != _processor_id);
     932             : }
     933             : 
     934             : 
     935             : 
     936             : inline
     937  4858189426 : unsigned int DofObject::n_systems () const
     938             : {
     939  7376480607 :   const int hdr = _idx_buf.empty() ?
     940  6282209581 :     0 : cast_int<int>(dof_id_signed_type(_idx_buf[0]));
     941  7252437234 :   return hdr >= 0 ? hdr : (-hdr-1);
     942             : }
     943             : 
     944             : 
     945             : 
     946             : inline
     947  1019544278 : unsigned int DofObject::n_pseudo_systems () const
     948             : {
     949  1445280377 :   const int hdr = _idx_buf.empty() ?
     950  1445280619 :     0 : cast_int<int>(dof_id_signed_type(_idx_buf[0]));
     951  1445280619 :   return std::abs(hdr);
     952             : }
     953             : 
     954             : 
     955             : 
     956             : inline
     957  1418750609 : unsigned int DofObject::n_var_groups(const unsigned int s) const
     958             : {
     959  1018085856 :   libmesh_assert_less (s, this->n_systems());
     960             : 
     961  1418750609 :   return (this->end_idx(s) - this->start_idx(s)) / 2;
     962             : }
     963             : 
     964             : 
     965             : 
     966             : inline
     967   392479799 : unsigned int DofObject::n_vars(const unsigned int s,
     968             :                                const unsigned int vg) const
     969             : {
     970   392479799 :   libmesh_assert_less (s,  this->n_systems());
     971   392479799 :   libmesh_assert_less (vg, this->n_var_groups(s));
     972             : 
     973   392479799 :   const unsigned int start_idx_sys = this->start_idx(s);
     974             : 
     975   392479799 :   libmesh_assert_less ((start_idx_sys + 2*vg), _idx_buf.size());
     976             : 
     977             :   return (cast_int<unsigned int>
     978   738106234 :           (_idx_buf[start_idx_sys + 2*vg]) >> ncv_magic_exp);
     979             : }
     980             : 
     981             : 
     982             : 
     983             : inline
     984   211396415 : unsigned int DofObject::n_vars(const unsigned int s) const
     985             : {
     986    72117068 :   libmesh_assert_less (s, this->n_systems());
     987             : 
     988   211396415 :   const unsigned int nvg = this->n_var_groups(s);
     989             : 
     990    72117068 :   unsigned int val=0;
     991             : 
     992   382244438 :   for (unsigned int vg=0; vg<nvg; vg++)
     993   170848023 :     val += this->n_vars(s,vg);
     994             : 
     995   211396415 :   return val;
     996             : }
     997             : 
     998             : 
     999             : 
    1000             : 
    1001             : inline
    1002   203903076 : unsigned int DofObject::n_comp(const unsigned int s,
    1003             :                                const unsigned int var) const
    1004             : {
    1005    40790691 :   libmesh_assert_less (s,   this->n_systems());
    1006    40790691 :   libmesh_assert_less (var, this->n_vars(s));
    1007             : 
    1008   203903076 :   return this->n_comp_group(s,this->var_to_vg(s,var));
    1009             : }
    1010             : 
    1011             : 
    1012             : 
    1013             : 
    1014             : inline
    1015   205777336 : unsigned int DofObject::n_comp_group(const unsigned int s,
    1016             :                                      const unsigned int vg) const
    1017             : {
    1018   205777336 :   libmesh_assert_less (s,  this->n_systems());
    1019   205777336 :   libmesh_assert_less (vg, this->n_var_groups(s));
    1020             : 
    1021             :   const unsigned int
    1022   205777336 :     start_idx_sys = this->start_idx(s);
    1023             : 
    1024   205777336 :   libmesh_assert_less ((start_idx_sys + 2*vg), _idx_buf.size());
    1025             : 
    1026  2244091695 :   return (_idx_buf[start_idx_sys + 2*vg] % ncv_magic);
    1027             : }
    1028             : 
    1029             : 
    1030             : 
    1031             : inline
    1032    82011356 : dof_id_type DofObject::dof_number(const unsigned int s,
    1033             :                                   const unsigned int var,
    1034             :                                   const unsigned int comp) const
    1035             : {
    1036    12876529 :   libmesh_assert_less (s,    this->n_systems());
    1037    12876529 :   libmesh_assert_less (var,  this->n_vars(s));
    1038    12876529 :   libmesh_assert_less (comp, this->n_comp(s,var));
    1039             : 
    1040             :   const std::pair<unsigned int, unsigned int>
    1041    76747834 :     vg_vig = this->var_to_vg_and_offset(s,var);
    1042             : 
    1043             :   const unsigned int
    1044    76747834 :     n_comp = this->n_comp_group(s,vg_vig.first);
    1045             : 
    1046    76747834 :   return this->dof_number(s, vg_vig.first, vg_vig.second,
    1047    94887885 :                           comp, n_comp);
    1048             : }
    1049             : 
    1050             : 
    1051             : 
    1052             : inline
    1053  1445542520 : dof_id_type DofObject::dof_number(const unsigned int s,
    1054             :                                   const unsigned int vg,
    1055             :                                   const unsigned int vig,
    1056             :                                   const unsigned int comp,
    1057             :                                   const unsigned int n_comp) const
    1058             : {
    1059   122815657 :   libmesh_assert_less (s,   this->n_systems());
    1060   122815657 :   libmesh_assert_less (vg,  this->n_var_groups(s));
    1061   122815657 :   libmesh_assert_less (vig, this->n_vars(s,vg));
    1062             : 
    1063             :   const unsigned int
    1064   122815657 :     start_idx_sys = this->start_idx(s);
    1065             : 
    1066   122815657 :   libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
    1067             : 
    1068             :   const dof_id_type
    1069  1463768765 :     base_idx = _idx_buf[start_idx_sys + 2*vg + 1];
    1070             : 
    1071             :   // if the first component is invalid, they
    1072             :   // are all invalid
    1073  1459105105 :   if (base_idx == invalid_id)
    1074           0 :     return invalid_id;
    1075             : 
    1076             :   // otherwise the index is the first component
    1077             :   // index augmented by the component number
    1078             :   else
    1079  1459105105 :     return cast_int<dof_id_type>(base_idx + vig*n_comp + comp);
    1080             : }
    1081             : 
    1082             : 
    1083             : 
    1084             : inline
    1085             : void
    1086      332414 : DofObject::set_extra_integer(const unsigned int index,
    1087             :                              const dof_id_type value)
    1088             : {
    1089           0 :   libmesh_assert_less(index, this->n_extra_integers());
    1090           0 :   libmesh_assert_less(this->n_pseudo_systems(), _idx_buf.size());
    1091             : 
    1092      350483 :   const unsigned int start_idx_i = this->start_idx_ints();
    1093             : 
    1094           0 :   libmesh_assert_less(start_idx_i+index, _idx_buf.size());
    1095      366776 :   _idx_buf[start_idx_i+index] = value;
    1096      332414 : }
    1097             : 
    1098             : 
    1099             : 
    1100             : inline
    1101             : dof_id_type
    1102      389569 : DofObject::get_extra_integer (const unsigned int index) const
    1103             : {
    1104      119736 :   libmesh_assert_less(index, this->n_extra_integers());
    1105      119736 :   libmesh_assert_less(this->n_systems(), _idx_buf.size());
    1106             : 
    1107      405650 :   const unsigned int start_idx_i = this->start_idx_ints();
    1108             : 
    1109      119736 :   libmesh_assert_less(start_idx_i+index, _idx_buf.size());
    1110      421731 :   return _idx_buf[start_idx_i+index];
    1111             : }
    1112             : 
    1113             : 
    1114             : 
    1115             : // If we're using a type T that's a class with no trivial
    1116             : // copy-assignment, -Wclass-memaccess will scream about doing it with
    1117             : // memcpy, even if (as with boost::multiprecision::float128) this is a
    1118             : // false positive.
    1119             : #include "libmesh/ignore_warnings.h"
    1120             : 
    1121             : 
    1122             : 
    1123             : template <typename T>
    1124             : inline
    1125             : void
    1126       63510 : DofObject::set_extra_datum(const unsigned int index,
    1127             :                            const T value)
    1128             : {
    1129             : #ifndef NDEBUG
    1130        4356 :   const unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
    1131             : #endif
    1132        4356 :   libmesh_assert_less(index+n_more_integers, this->n_extra_integers());
    1133        4356 :   libmesh_assert_less(this->n_pseudo_systems(), _idx_buf.size());
    1134             : 
    1135       69369 :   const unsigned int start_idx_i = this->start_idx_ints();
    1136             : 
    1137        4356 :   libmesh_assert_less(start_idx_i+index+n_more_integers, _idx_buf.size());
    1138       75228 :   std::memcpy(&_idx_buf[start_idx_i+index], &value, sizeof(T));
    1139       63510 : }
    1140             : 
    1141             : 
    1142             : 
    1143             : template <typename T>
    1144             : inline
    1145             : T
    1146  1107115539 : DofObject::get_extra_datum (const unsigned int index) const
    1147             : {
    1148             : #ifndef NDEBUG
    1149    14188212 :   const unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
    1150             : #endif
    1151    14188212 :   libmesh_assert_less(index+n_more_integers, this->n_extra_integers());
    1152    14188212 :   libmesh_assert_less(this->n_systems(), _idx_buf.size());
    1153             : 
    1154  1213316725 :   const unsigned int start_idx_i = this->start_idx_ints();
    1155             : 
    1156    14188212 :   libmesh_assert_less(start_idx_i+index+n_more_integers, _idx_buf.size());
    1157             :   T returnval;
    1158  1319517911 :   std::memcpy(&returnval, &_idx_buf[start_idx_i+index], sizeof(T));
    1159  1107115539 :   return returnval;
    1160             : }
    1161             : 
    1162             : 
    1163             : 
    1164             : #include "libmesh/restore_warnings.h"
    1165             : 
    1166             : 
    1167             : 
    1168             : inline
    1169             : unsigned int
    1170   201517502 : DofObject::n_extra_integers () const
    1171             : {
    1172   201517502 :   if (_idx_buf.empty())
    1173     3801629 :     return 0;
    1174             : 
    1175    83754794 :   const int hdr = dof_id_signed_type(_idx_buf[0]);
    1176    83754794 :   if (hdr >= 0)
    1177     6790028 :     return 0;
    1178             : 
    1179    15905271 :   const unsigned int start_idx_i = this->start_idx_ints();
    1180             : 
    1181    15905271 :   return _idx_buf.size() - start_idx_i;
    1182             : }
    1183             : 
    1184             : 
    1185             : 
    1186             : inline
    1187             : bool
    1188    30500762 : DofObject::has_extra_integers () const
    1189             : {
    1190    58241466 :   if (_idx_buf.empty())
    1191           0 :     return 0;
    1192             : 
    1193    58241466 :   return (dof_id_signed_type(_idx_buf[0]) < 0);
    1194             : }
    1195             : 
    1196             : 
    1197             : 
    1198             : inline
    1199             : std::pair<unsigned int, unsigned int>
    1200   186780162 : DofObject::var_to_vg_and_offset(const unsigned int s,
    1201             :                                 const unsigned int var) const
    1202             : {
    1203   117845853 :   std::pair<unsigned int, unsigned int> returnval(0,0);
    1204             : 
    1205   117845853 :   unsigned int & vg = returnval.first;
    1206   117845853 :   unsigned int & offset = returnval.second;
    1207             : 
    1208   117845853 :   unsigned int vg_start = 0;
    1209    16994311 :   for (; ; vg++)
    1210             :     {
    1211   133937039 :       libmesh_assert_less(vg, this->n_var_groups(s));
    1212             : 
    1213   209765938 :       const unsigned int vg_end = vg_start + this->n_vars(s,vg);
    1214   209765938 :       if (var < vg_end)
    1215             :         {
    1216   192769816 :           offset = var - vg_start;
    1217   186780162 :           return returnval;
    1218             :         }
    1219    16091186 :       vg_start = vg_end;
    1220    16945742 :     }
    1221             : }
    1222             : 
    1223             : 
    1224             : 
    1225             : inline
    1226   200406720 : bool DofObject::has_dofs (const unsigned int sys) const
    1227             : {
    1228   200406720 :   if (sys == libMesh::invalid_uint)
    1229             :     {
    1230   126742272 :       for (auto s : make_range(this->n_systems()))
    1231    40266558 :         if (this->n_vars(s))
    1232        3214 :           return true;
    1233             :     }
    1234             : 
    1235             :   else
    1236             :     {
    1237     5943733 :       libmesh_assert_less (sys, this->n_systems());
    1238             : 
    1239    77881701 :       if (this->n_vars(sys))
    1240     2626619 :         return true;
    1241             :     }
    1242             : 
    1243     4157612 :   return false;
    1244             : }
    1245             : 
    1246             : 
    1247             : 
    1248             : inline
    1249  1759917870 : unsigned int DofObject::start_idx (const unsigned int s) const
    1250             : {
    1251  1759917870 :   libmesh_assert_less (s, this->n_systems());
    1252  1759917870 :   libmesh_assert_less (s, _idx_buf.size());
    1253             : 
    1254  5274581099 :   return cast_int<unsigned int>(std::abs(dof_id_signed_type(_idx_buf[s])));
    1255             : }
    1256             : 
    1257             : 
    1258             : 
    1259             : inline
    1260  1414599769 : unsigned int DofObject::end_idx (const unsigned int s) const
    1261             : {
    1262  1019539922 :   libmesh_assert_less (s, this->n_systems());
    1263  1019539922 :   libmesh_assert_less (s, _idx_buf.size());
    1264             : 
    1265  1871012604 :   return ((s+1) == this->n_pseudo_systems()) ?
    1266   929420196 :     cast_int<unsigned int>(_idx_buf.size()) :
    1267  1063501901 :     cast_int<unsigned int>(_idx_buf[s+1]);
    1268             : }
    1269             : 
    1270             : 
    1271             : 
    1272             : inline
    1273  1230047476 : unsigned int DofObject::start_idx_ints () const
    1274             : {
    1275    28722888 :   libmesh_assert (this->has_extra_integers());
    1276             : 
    1277    28722888 :   unsigned int n_sys = this->n_systems();
    1278             : 
    1279    28722888 :   libmesh_assert_less(this->n_systems(), _idx_buf.size());
    1280  1382100076 :   return n_sys ? cast_int<unsigned int>(_idx_buf[this->n_systems()]) :
    1281  1230047476 :                  (n_sys+1);
    1282             : }
    1283             : 
    1284             : 
    1285             : 
    1286             : inline
    1287             : unsigned int DofObject::end_idx_ints () const
    1288             : {
    1289             :   libmesh_assert (this->has_extra_integers());
    1290             : 
    1291             :   return cast_int<unsigned int>(_idx_buf.size());
    1292             : }
    1293             : 
    1294             : 
    1295             : 
    1296             : inline
    1297     5653290 : void DofObject::set_vg_dof_base(const unsigned int s,
    1298             :                                 const unsigned int vg,
    1299             :                                 const dof_id_type db)
    1300             : {
    1301     5653290 :   libmesh_assert_less (s,  this->n_systems());
    1302     5653290 :   libmesh_assert_less (vg, this->n_var_groups(s));
    1303             : 
    1304             :   const unsigned int
    1305     5653290 :     start_idx_sys = this->start_idx(s);
    1306             : 
    1307     5653290 :   libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
    1308             : 
    1309    84781440 :   _idx_buf[start_idx_sys + 2*vg + 1] = db;
    1310             : 
    1311     5653290 :   libmesh_assert_equal_to (this->vg_dof_base(s,vg), db);
    1312    61377786 : }
    1313             : 
    1314             : 
    1315             : 
    1316             : inline
    1317    14758114 : dof_id_type DofObject::vg_dof_base(const unsigned int s,
    1318             :                                    const unsigned int vg) const
    1319             : {
    1320    14758114 :   libmesh_assert_less (s,  this->n_systems());
    1321    14758114 :   libmesh_assert_less (vg, this->n_var_groups(s));
    1322             : 
    1323             :   const unsigned int
    1324    14758114 :     start_idx_sys = this->start_idx(s);
    1325             : 
    1326    14758114 :   libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
    1327             : 
    1328             :   // #ifdef DEBUG
    1329             :   //   std::cout << " [ ";
    1330             :   //   for (auto i : _idx_buf)
    1331             :   //     std::cout << i << " ";
    1332             :   //   std::cout << "]\n";
    1333             :   // #endif
    1334             : 
    1335   123319460 :   return _idx_buf[start_idx_sys + 2*vg + 1];
    1336             : }
    1337             : 
    1338             : 
    1339             : 
    1340             : inline
    1341   200677575 : unsigned int DofObject::var_to_vg (const unsigned int s,
    1342             :                                    const unsigned int var) const
    1343             : {
    1344             :   const unsigned int
    1345   200677575 :     nvg = this->n_var_groups(s);
    1346             : 
    1347   207254760 :   for (unsigned int vg=0, vg_end=0; vg<nvg; vg++)
    1348             :     {
    1349   207254760 :       vg_end += this->n_vars(s,vg);
    1350   207254760 :       if (var < vg_end) return vg;
    1351             :     }
    1352             : 
    1353           0 :   libmesh_error_msg("Error: could not map variable " << var << " to variable group.");
    1354             : }
    1355             : 
    1356             : 
    1357             : 
    1358             : inline
    1359           0 : unsigned int DofObject::system_var_to_vg_var (const unsigned int s,
    1360             :                                               const unsigned int vg,
    1361             :                                               const unsigned int var) const
    1362             : {
    1363           0 :   unsigned int accumulated_sum=0;
    1364             : 
    1365           0 :   for (unsigned int vgc=0; vgc<vg; vgc++)
    1366           0 :     accumulated_sum += this->n_vars(s,vgc);
    1367             : 
    1368           0 :   libmesh_assert_less_equal (accumulated_sum, var);
    1369             : 
    1370           0 :   return (var - accumulated_sum);
    1371             : }
    1372             : 
    1373             : /**
    1374             :  * Comparison object to use with DofObject pointers.  This sorts by id(),
    1375             :  * so when we iterate over a set of DofObjects we visit the objects in
    1376             :  * order of increasing ID.
    1377             :  */
    1378             : struct CompareDofObjectsByID
    1379             : {
    1380           0 :   bool operator()(const DofObject * a,
    1381             :                   const DofObject * b) const
    1382             :   {
    1383           0 :     libmesh_assert (a);
    1384           0 :     libmesh_assert (b);
    1385             : 
    1386           0 :     return a->id() < b->id();
    1387             :   }
    1388             : };
    1389             : 
    1390             : struct CompareDofObjectsByPIDAndThenID
    1391             : {
    1392     3421870 :   bool operator()(const DofObject * a,
    1393             :                   const DofObject * b) const
    1394             :   {
    1395     3421870 :     libmesh_assert (a);
    1396     3421870 :     libmesh_assert (b);
    1397             : 
    1398   778449693 :     if (a->processor_id() < b->processor_id())
    1399       39639 :       return true;
    1400   656919575 :     if (b->processor_id() < a->processor_id())
    1401       33851 :       return false;
    1402             : 
    1403   563567293 :     return a->id() < b->id();
    1404             :   }
    1405             : };
    1406             : 
    1407             : } // namespace libMesh
    1408             : 
    1409             : 
    1410             : #endif // #ifndef LIBMESH_DOF_OBJECT_H

Generated by: LCOV version 1.14