LCOV - code coverage report
Current view: top level - include/base - dof_object.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4286 (66ff4b) with base 03bcc7 Lines: 220 239 92.1 %
Date: 2025-10-22 02:54:50 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   530898339 :   ~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     8981932 :   DofObject * get_old_dof_object() { return old_dof_object.get(); }
      97     2838622 :   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     7307791 :   const DofObject & get_old_dof_object_ref() const
     111             :   {
     112     7307791 :     libmesh_assert(old_dof_object);
     113     7307791 :     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             :   /**
     185             :    * Sets the \p unique_id for this \p DofObject
     186             :    */
     187             :   void set_unique_id (unique_id_type new_id);
     188             : 
     189             :   /**
     190             :    * Sets the \p id for this \p DofObject
     191             :    */
     192    62854816 :   void set_id (const dof_id_type dofid)
     193  1364182445 :   { this->set_id() = dofid; }
     194             : 
     195             :   /**
     196             :    * \returns \p true if this \p DofObject has a valid \p id set,
     197             :    * \p false otherwise.
     198             :    */
     199             :   bool valid_id () const;
     200             : 
     201             :   /**
     202             :    * \returns \p true if this \p DofObject has a valid \p unique_id set,
     203             :    * \p false otherwise.
     204             :    */
     205             :   bool valid_unique_id () const;
     206             : 
     207             :   /**
     208             :    * \returns The processor that this DofObject belongs to.
     209             :    *
     210             :    * When partitioning and DoF numbering have been performed by
     211             :    * libMesh, every current DoF on this DofObject will belong to its
     212             :    * processor.
     213             :    */
     214             :   processor_id_type processor_id () const;
     215             : 
     216             :   /**
     217             :    * \returns The processor that this DofObject belongs to as a
     218             :    * writable reference.
     219             :    */
     220             :   processor_id_type & processor_id ();
     221             : 
     222             :   /**
     223             :    * Sets the \p processor_id for this \p DofObject.
     224             :    */
     225             :   void processor_id (const processor_id_type pid);
     226             : 
     227             :   /**
     228             :    * \returns \p true if this \p DofObject has a valid \p id set,
     229             :    * \p false otherwise.
     230             :    */
     231             :   bool valid_processor_id () const;
     232             : 
     233             :   /**
     234             :    * \returns The number of systems associated with this
     235             :    * \p DofObject
     236             :    */
     237             :   unsigned int n_systems() const;
     238             : 
     239             :   /**
     240             :    * \returns The total number of pseudo-systems associated with this
     241             :    * \p DofObject :
     242             :    * n_systems(), plus one iff \p this->has_extra_integers()
     243             :    */
     244             :   unsigned int n_pseudo_systems() const;
     245             : 
     246             :   /**
     247             :    * Sets the number of systems for this \p DofObject.  If this number
     248             :    * is a change, also clears all variable count and DoF indexing
     249             :    * associated with this \p DofObject.
     250             :    *
     251             :    * If any extra integers are associated with this \p DofObject,
     252             :    * their count and values are unchanged.
     253             :    */
     254             :   void set_n_systems (const unsigned int s);
     255             : 
     256             :   /**
     257             :    * Sets the value on this object of the extra integer associated
     258             :    * with \p index, which should have been obtained via a call to \p
     259             :    * MeshBase::add_elem_integer or \p MeshBase::add_node_integer
     260             :    */
     261             :   void set_extra_integer (const unsigned int index, const dof_id_type value);
     262             : 
     263             :   /**
     264             :    * Gets the value on this object of the extra integer associated
     265             :    * with \p index, which should have been obtained via a call to \p
     266             :    * MeshBase::add_elem_integer or \p MeshBase::add_node_integer
     267             :    */
     268             :   dof_id_type get_extra_integer (const unsigned int index) const;
     269             : 
     270             :   /**
     271             :    * Sets the value on this object of the extra datum associated
     272             :    * with \p index, which should have been obtained via a call to \p
     273             :    * MeshBase::add_elem_datum or \p MeshBase::add_node_datum using
     274             :    * the same type T.
     275             :    */
     276             :   template <typename T>
     277             :   void set_extra_datum (const unsigned int index, const T value);
     278             : 
     279             :   /**
     280             :    * Gets 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             :   T get_extra_datum (const unsigned int index) const;
     287             : 
     288             : 
     289             :   /**
     290             :    * Adds an additional system to the \p DofObject
     291             :    */
     292             :   void add_system ();
     293             : 
     294             :   /**
     295             :    * \returns The number of \p VariableGroup variable groups
     296             :    * associated with system \p s for this \p DofObject
     297             :    */
     298             :   unsigned int n_var_groups(const unsigned int s) const;
     299             : 
     300             :   /**
     301             :    * \returns The number of \p Variable variables associated
     302             :    * with \p VariableGroup \p vg in system \p s for this \p DofObject
     303             :    */
     304             :   unsigned int n_vars(const unsigned int s,
     305             :                       const unsigned int vg) const;
     306             : 
     307             :   /**
     308             :    * \returns The number of \p Variable variables associated
     309             :    * with system \p s for this \p DofObject
     310             :    */
     311             :   unsigned int n_vars(const unsigned int s) const;
     312             : 
     313             :   /**
     314             :    * Sets number of variables in each group associated with system \p s for this
     315             :    * \p DofObject. Implicit in this is also setting the number of \p VariableGroup
     316             :    * variable groups for the system.
     317             :    * Has the effect of setting the number of components
     318             :    * to 0 even when called even with (nvg == this->n_var_groups(s)).
     319             :    */
     320             :   void set_n_vars_per_group(const unsigned int s,
     321             :                             const std::vector<unsigned int> & nvpg);
     322             : 
     323             :   /**
     324             :    * \returns The number of components for variable \p var
     325             :    * of system \p s associated with this \p DofObject.
     326             :    * For example, the \p HIERARCHIC shape functions may
     327             :    * have multiple DoFs associated with one node.  Another
     328             :    * example is the \p MONOMIALs, where only the elements
     329             :    * hold the DoFs.  For the different spatial directions,
     330             :    * and orders, see \p FE.
     331             :    */
     332             :   unsigned int n_comp(const unsigned int s,
     333             :                       const unsigned int var) const;
     334             : 
     335             :   /**
     336             :    * \returns The number of components for \p VariableGroup \p vg
     337             :    * of system \p s associated with this \p DofObject.
     338             :    * For example, the \p HIERARCHIC shape functions may
     339             :    * have multiple DoFs associated with one node.  Another
     340             :    * example is the \p MONOMIALs, where only the elements
     341             :    * hold the DoFs.  For the different spatial directions,
     342             :    * and orders, see \p FE.
     343             :    */
     344             :   unsigned int n_comp_group(const unsigned int s,
     345             :                             const unsigned int vg) const;
     346             : 
     347             :   /**
     348             :    * Sets the number of components for \p Variable \p var
     349             :    * of system \p s associated with this \p DofObject
     350             :    */
     351             :   void set_n_comp(const unsigned int s,
     352             :                   const unsigned int var,
     353             :                   const unsigned int ncomp);
     354             : 
     355             :   /**
     356             :    * Sets the number of components for \p VariableGroup \p vg
     357             :    * of system \p s associated with this \p DofObject
     358             :    */
     359             :   void set_n_comp_group(const unsigned int s,
     360             :                         const unsigned int vg,
     361             :                         const unsigned int ncomp);
     362             : 
     363             :   /**
     364             :    * \returns The global degree of freedom number for variable \p var,
     365             :    * component \p comp for system \p s associated with this \p DofObject
     366             :    *
     367             :    * When partitioning and DoF numbering have been performed by
     368             :    * libMesh, every current DoF on this DofObject will belong to its
     369             :    * processor.
     370             :    */
     371             :   dof_id_type dof_number(const unsigned int s,
     372             :                          const unsigned int var,
     373             :                          const unsigned int comp) const;
     374             : 
     375             :   /**
     376             :    * \returns The global degree of freedom number for variable group
     377             :    * \p vg, variable index \p vig within the group, component \p comp
     378             :    * out of \p n_comp, for system \p s on this \p DofObject
     379             :    *
     380             :    * Even users who need to call dof_number from user code probably
     381             :    * don't want to call this overload.
     382             :    */
     383             :   dof_id_type dof_number(const unsigned int s,
     384             :                          const unsigned int vg,
     385             :                          const unsigned int vig,
     386             :                          const unsigned int comp,
     387             :                          const unsigned int n_comp) const;
     388             : 
     389             :   /**
     390             :    * \returns A pair consisting of the variable group number and the
     391             :    * offset index from the start of that group for variable \p var on
     392             :    * system \p s associated with this \p DofObject
     393             :    */
     394             :   std::pair<unsigned int, unsigned int>
     395             :   var_to_vg_and_offset(const unsigned int s,
     396             :                        const unsigned int var) const;
     397             : 
     398             :   /**
     399             :    * Sets the global degree of freedom number for variable \p var,
     400             :    * component \p comp for system \p s associated with this \p DofObject
     401             :    */
     402             :   void set_dof_number(const unsigned int s,
     403             :                       const unsigned int var,
     404             :                       const unsigned int comp,
     405             :                       const dof_id_type dn);
     406             : 
     407             :   /**
     408             :    * \returns \p true if any system has variables which have been assigned,
     409             :    * \p false otherwise.
     410             :    */
     411             :   bool has_dofs(const unsigned int s=libMesh::invalid_uint) const;
     412             : 
     413             :   /**
     414             :    * \p VariableGroup DoF indices are indexed as
     415             :    * id = base + var_in_vg*ncomp + comp
     416             :    * This method allows for direct access to the base.
     417             :    */
     418             :   void set_vg_dof_base(const unsigned int s,
     419             :                        const unsigned int vg,
     420             :                        const dof_id_type db);
     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             :   dof_id_type vg_dof_base(const unsigned int s,
     428             :                           const unsigned int vg) const;
     429             : 
     430             :   /**
     431             :    * Assigns a set of extra integers to this \p DofObject.  There will
     432             :    * now be \p n_integers associated; this *replaces*, not augments,
     433             :    * any previous count.
     434             :    *
     435             :    * Any newly-added values will initially be DofObject::invalid_id
     436             :    *
     437             :    * If non-integer data is in the set, each datum of type T should be
     438             :    * counted sizeof(T)/sizeof(dof_id_type) times in \p n_integers.
     439             :    */
     440             :   void add_extra_integers (const unsigned int n_integers);
     441             : 
     442             :   /**
     443             :    * Assigns a set of extra integers to this \p DofObject.  There will
     444             :    * now be \p n_integers associated; this *replaces*, not augments,
     445             :    * any previous count.
     446             :    *
     447             :    * Any newly-added values will be copied from \p default_values.
     448             :    *
     449             :    * If non-integer data is in the set, each datum of type T should be
     450             :    * counted sizeof(T)/sizeof(dof_id_type) times in \p n_integers, and
     451             :    * its data should be expressed in \p default_values as per memcpy.
     452             :    */
     453             :   void add_extra_integers (const unsigned int n_integers,
     454             :                            const std::vector<dof_id_type> & default_values);
     455             : 
     456             :   /**
     457             :    * Returns how many extra integers are associated to the \p DofObject
     458             :    *
     459             :    * If non-integer data has been associated, each datum of type T
     460             :    * counts for sizeof(T)/sizeof(dof_id_type) times in the return
     461             :    * value.
     462             :    */
     463             :   unsigned int n_extra_integers () const;
     464             : 
     465             :   /**
     466             :    * Returns whether extra integers are associated to the \p DofObject
     467             :    */
     468             :   bool has_extra_integers () const;
     469             : 
     470             :   /**
     471             :    * An invalid \p id to distinguish an uninitialized \p DofObject
     472             :    */
     473             :   static constexpr dof_id_type invalid_id = static_cast<dof_id_type>(-1);
     474             : 
     475             :   /**
     476             :    * An invalid \p unique_id to distinguish an uninitialized \p DofObject
     477             :    */
     478             :   static constexpr unique_id_type invalid_unique_id = static_cast<unique_id_type>(-1);
     479             : 
     480             :   /**
     481             :    * An invalid \p processor_id to distinguish DoFs that have
     482             :    * not been assigned to a processor.
     483             :    */
     484             :   static constexpr processor_id_type invalid_processor_id = static_cast<processor_id_type>(-1);
     485             : 
     486             :   /**
     487             :    * If we pack our indices into an buffer for communications, how
     488             :    * many ints do we need?
     489             :    */
     490             :   unsigned int packed_indexing_size() const;
     491             : 
     492             :   /**
     493             :    * If we have indices packed into an buffer for communications, how
     494             :    * much of that buffer applies to this dof object?
     495             :    */
     496             :   static unsigned int unpackable_indexing_size
     497             :   (std::vector<largest_id_type>::const_iterator begin);
     498             : 
     499             :   /**
     500             :    * A method for creating our index buffer from packed data -
     501             :    * basically with our current implementation we investigate the size
     502             :    * term and then copy.
     503             :    */
     504             :   void unpack_indexing(std::vector<largest_id_type>::const_iterator begin);
     505             : 
     506             :   /**
     507             :    * A method for creating packed data from our index buffer -
     508             :    * basically a copy with prepended size with our current
     509             :    * implementation.
     510             :    */
     511             :   void pack_indexing(std::back_insert_iterator<std::vector<largest_id_type>> target) const;
     512             : 
     513             :   /**
     514             :    * Print our buffer for debugging.
     515             :    */
     516             :   void debug_buffer () const;
     517             : 
     518             :   /**
     519             :    * Print out info for debugging.
     520             :    */
     521             :   void print_dof_info() const;
     522             : 
     523             :   // Deep copy (or almost-copy) of DofObjects is solely for a couple
     524             :   // tricky internal uses.
     525             : private:
     526             : 
     527             :   /**
     528             :    * "Copy"-constructor.  Does not copy old_dof_object, but leaves it
     529             :    * null in the new object.
     530             :    */
     531             :   DofObject (const DofObject &);
     532             : 
     533             :   /**
     534             :    * Convenient factory function that calls either the (deep) copy
     535             :    * constructor or the default constructor depending on the input
     536             :    * arg. Like the copy constructor, this function is also private. We
     537             :    * can't use std::make_unique to construct a DofObject since the
     538             :    * copy constructor is private, but we can at least encapsulate the
     539             :    * code which calls "new" directly.
     540             :    */
     541             :   std::unique_ptr<DofObject>
     542             :   construct(const DofObject * other = nullptr);
     543             : 
     544             :   /**
     545             :    * Deep-copying assignment operator
     546             :    */
     547             :   DofObject & operator= (const DofObject & dof_obj);
     548             : 
     549             :   /**
     550             :    * Utility function - for variable \p var in system \p s, figure out what
     551             :    * variable group it lives in.
     552             :    */
     553             :   unsigned int var_to_vg (const unsigned int s,
     554             :                           const unsigned int var) const;
     555             : 
     556             :   /**
     557             :    * Utility function - for variable \p var in system \p s, figure out what
     558             :    * variable group it lives in.
     559             :    */
     560             :   unsigned int system_var_to_vg_var (const unsigned int s,
     561             :                                      const unsigned int vg,
     562             :                                      const unsigned int var) const;
     563             : 
     564             :   /**
     565             :    * A globally unique id, guaranteed not to change as the mesh is repartitioned or adapted
     566             :    */
     567             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     568             :   unique_id_type _unique_id;
     569             : #endif
     570             : 
     571             :   /**
     572             :    * The \p id of the \p DofObject
     573             :    */
     574             :   dof_id_type _id;
     575             : 
     576             :   /**
     577             :    * The \p processor_id of the \p DofObject.
     578             :    * Degrees of freedom are wholly owned by processors,
     579             :    * however they may be duplicated on other processors.
     580             :    *
     581             :    * This is stored as an unsigned short int since we cannot
     582             :    * expect to be solving on 65000+ processors any time soon,
     583             :    * can we??
     584             :    */
     585             :   processor_id_type _processor_id;
     586             : 
     587             :   /**
     588             :    * DoF index information.  This is packed into a contiguous buffer of the following format:
     589             :    *
     590             :    * \verbatim
     591             :    * [hdr end_0 end_1 ... end_{nps-2} (ncv_0 idx_0 ncv_1 idx_1 ... ncv_nv idx_nv)_0
     592             :    *                                  (ncv_0 idx_0 ncv_1 idx_1 ... ncv_nv idx_nv)_1
     593             :    *                                   ...
     594             :    *                                  (ncv_0 idx_0 ncv_1 idx_1 ... ncv_nv idx_nv)_{nps-2} ]
     595             :    * \endverbatim
     596             :    *
     597             :    * 'hdr' determines whether this \p DofObject \p has_extra_integers()
     598             :    * associated with it; iff so then it is negative.
     599             :    *
     600             :    * The total number of "pseudo systems" is nps := abs(hdr).
     601             :    *
     602             :    * The total number of true systems is
     603             :    * \verbatim
     604             :    * ns = hdr,            hdr >= 0
     605             :    *    = abs(hdr) - 1,   otherwise.
     606             :    * \endverbatim
     607             :    *
     608             :    * 'end_s' is the index past the end of the variable group (or
     609             :    * integer) storage for (pseudo) system \p s.
     610             :    *
     611             :    * \note We specifically do not store the end for the last (pseudo)
     612             :    * system - this always _idx_buf.size().
     613             :    *
     614             :    * As a first example, consider the case of 4 systems, with 3, 0, 1,
     615             :    * 2 variable groups, respectively.  The _idx_buf then looks like:
     616             :    *
     617             :    * \verbatim
     618             :    * [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)]
     619             :    * [0  1  2  3         4     5     6     7     8     9         10    11      12    13    14    15]
     620             :    * \endverbatim
     621             :    *
     622             :    * The ending index for each (pseudo) system is then given by:
     623             :    *
     624             :    * \verbatim
     625             :    * end_s = _idx_buf.size(),                        s == (nps-1),
     626             :    *       = _idx_buf[s+1] + has_extra_integers(),   otherwise.
     627             :    * \endverbatim
     628             :    *
     629             :    * The starting indices are not specifically stored, but rather inferred as follows:
     630             :    *
     631             :    * start_s = abs(_idx_buf[s])
     632             :    *
     633             :    * Now, the defining characteristic of the \p VariableGroup is that it supports
     634             :    * an arbitrary number of variables of the same type.  At the \p DofObject level, what
     635             :    * that means is that each \p Variable in the \p VariableGroup will have the same number
     636             :    * of nonzero components, and they can all be indexed from the same base number.  We use this
     637             :    * information in the ncv_# and idx_# entries as follows:
     638             :    *
     639             :    * ncv_# = n_vars*ncv_magic + n_comp      for variable group #
     640             :    * idx_# = base_offset                    for variable group #
     641             :    *
     642             :    * the DoF index for a particular component c of variable v within that group is then given by
     643             :    *
     644             :    * idx_var = idx_# + n_comp*v + c
     645             :    *
     646             :    * \note There is a subtlety here - "variable v within that group" usually means nothing to the
     647             :    * user. This class is either indexed with variable group numbers, or variable numbers counted
     648             :    * *within the system*. So for a system with 2 variable groups, 4 and 8 variables each,
     649             :    * the 5th variable in the system is the 1st variable in 2nd variable group.
     650             :    * (Now of course 0-base everything...  but you get the idea.)
     651             :    *
     652             :    * When hdr is *negative* when cast to a signed type, then we
     653             :    * interpret that to mean there exists one pseudo-system following
     654             :    * the true systems, one for which the _idx_buf data stores the
     655             :    * values associated with add_extra_integer entries, not ncv and idx
     656             :    * data associated with system variables.  We still return only the
     657             :    * number of true systems for n_systems(), but we report
     658             :    * has_extra_integers() as true iff hdr is negative, and abs(hdr)
     659             :    * will reflect the total number of pseudo-systems, n_systems()+1.
     660             :    *
     661             :    * E.g. if we had added two extra integers to the example case
     662             :    * above, the _idx_buf then looks like:
     663             :    *
     664             :    * \verbatim
     665             :    * [-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)]
     666             :    * [0   1  2  3  4         5     6     7     8     9    10         11    12      13    14    15    16      17    18]
     667             :    * \endverbatim
     668             :    */
     669             :   typedef dof_id_type index_t;
     670             :   typedef std::vector<index_t> index_buffer_t;
     671             :   index_buffer_t _idx_buf;
     672             : 
     673             :   /**
     674             :    * Above we introduced the chimera ncv, which is a hybrid of the form
     675             :    * ncv = ncv_magic*nv + nc
     676             :    * where nv are the number of identical variables of a given type,
     677             :    * and nc is the number of components for this set of variables.
     678             :    *
     679             :    * It is hoped that by setting this to a power of two, an optimizing compiler
     680             :    * will recognize later that  #/ncv_magic is simply a bitshift
     681             :    */
     682             :   static const index_t ncv_magic = 256; // = 2^8, in case we want to manually bitshift
     683             :   static const index_t ncv_magic_exp = 8; // Let's manually bitshift
     684             : 
     685             :   /**
     686             :    * The starting index for system \p s.
     687             :    */
     688             :   unsigned int start_idx(const unsigned int s) const;
     689             : 
     690             :   /**
     691             :    * The ending index for system \p s.
     692             :    */
     693             :   unsigned int end_idx(const unsigned int s) const;
     694             : 
     695             :   /**
     696             :    * The starting index for an extra_integers pseudosystem
     697             :    */
     698             :   unsigned int start_idx_ints() const;
     699             : 
     700             :   /**
     701             :    * The ending index for an extra_integers pseudosystem
     702             :    */
     703             :   unsigned int end_idx_ints() const;
     704             : 
     705             :   // methods only available for unit testing
     706             : #ifdef LIBMESH_IS_UNIT_TESTING
     707             : public:
     708             :   void set_buffer (const std::vector<dof_id_type> & buf)
     709             :   { _idx_buf = buf; }
     710             : #endif
     711             : };
     712             : 
     713             : 
     714             : 
     715             : //------------------------------------------------------
     716             : // Inline functions
     717             : inline
     718  1222687102 : DofObject::DofObject () :
     719             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     720   746902509 :   _unique_id (invalid_unique_id),
     721             : #endif
     722   746902509 :   _id (invalid_id),
     723  1222687102 :   _processor_id (invalid_processor_id)
     724             : {
     725    58179999 :   this->invalidate();
     726  1222687102 : }
     727             : 
     728             : 
     729             : 
     730             : inline
     731             : std::unique_ptr<DofObject>
     732    26304010 : DofObject::construct(const DofObject * other)
     733             : {
     734             :   return other
     735    26303701 :     ? std::unique_ptr<DofObject>(new DofObject(*other))
     736    39651952 :     : std::unique_ptr<DofObject>(new DofObject());
     737             : }
     738             : 
     739             : 
     740             : 
     741             : inline
     742   956470246 : void DofObject::invalidate_dofs (const unsigned int sys_num)
     743             : {
     744    62632471 :   const unsigned int n_sys = this->n_systems();
     745             :   // If the user does not specify the system number...
     746   956470246 :   if (sys_num >= n_sys)
     747             :     {
     748   892702986 :       for (auto s : make_range(n_sys))
     749           0 :         for (auto vg : make_range(this->n_var_groups(s)))
     750           0 :           if (this->n_comp_group(s,vg))
     751           0 :             this->set_vg_dof_base(s,vg,invalid_id);
     752             :     }
     753             :   // ...otherwise invalidate the dofs for all systems
     754             :   else
     755   145091848 :     for (auto vg : make_range(this->n_var_groups(sys_num)))
     756    81324588 :       if (this->n_comp_group(sys_num,vg))
     757     2329376 :         this->set_vg_dof_base(sys_num,vg,invalid_id);
     758   956470246 : }
     759             : 
     760             : 
     761             : 
     762             : inline
     763    58179999 : void DofObject::invalidate_id ()
     764             : {
     765    58179999 :   this->set_id (invalid_id);
     766    58179999 : }
     767             : 
     768             : 
     769             : 
     770             : inline
     771    59860475 : void DofObject::invalidate_processor_id ()
     772             : {
     773    59860475 :   this->processor_id (invalid_processor_id);
     774    59860475 : }
     775             : 
     776             : 
     777             : 
     778             : inline
     779    58179999 : void DofObject::invalidate ()
     780             : {
     781  1222687102 :   this->invalidate_dofs ();
     782    58179999 :   this->invalidate_id ();
     783    58179999 :   this->invalidate_processor_id ();
     784    58179999 : }
     785             : 
     786             : 
     787             : 
     788             : inline
     789             : void DofObject::clear_dofs ()
     790             : {
     791             :   this->set_n_systems(0);
     792             : }
     793             : 
     794             : 
     795             : 
     796             : inline
     797      357872 : unsigned int DofObject::n_dofs (const unsigned int s,
     798             :                                 const unsigned int var) const
     799             : {
     800       38345 :   libmesh_assert_less (s, this->n_systems());
     801             : 
     802       38345 :   unsigned int num = 0;
     803             : 
     804             :   // Count all variables
     805      357872 :   if (var == libMesh::invalid_uint)
     806      103184 :     for (auto v : make_range(this->n_vars(s)))
     807       77388 :       num += this->n_comp(s,v);
     808             : 
     809             :   // Only count specified variable
     810             :   else
     811      332076 :     num = this->n_comp(s,var);
     812             : 
     813      357872 :   return num;
     814             : }
     815             : 
     816             : 
     817             : 
     818             : inline
     819  3669722722 : dof_id_type DofObject::id () const
     820             : {
     821  9724923896 :   return _id;
     822             : }
     823             : 
     824             : 
     825             : 
     826             : inline
     827    68449875 : dof_id_type & DofObject::set_id ()
     828             : {
     829    68449875 :   return _id;
     830             : }
     831             : 
     832             : 
     833             : 
     834             : inline
     835    37114194 : unique_id_type DofObject::unique_id () const
     836             : {
     837             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     838    37114194 :   libmesh_assert (this->valid_unique_id());
     839   141530000 :   return _unique_id;
     840             : #else
     841             :   return invalid_unique_id;
     842             : #endif
     843             : }
     844             : 
     845             : 
     846             : 
     847             : inline
     848     2626051 : void DofObject::set_unique_id (unique_id_type new_id)
     849             : {
     850             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     851   175017095 :   _unique_id = new_id;
     852             : #else
     853             :   libmesh_ignore(new_id);
     854             :   libmesh_not_implemented();
     855             : #endif
     856    23323508 : }
     857             : 
     858             : 
     859             : 
     860             : inline
     861      904452 : bool DofObject::valid_id () const
     862             : {
     863   216424205 :   return (DofObject::invalid_id != _id);
     864             : }
     865             : 
     866             : 
     867             : 
     868             : inline
     869    39495282 : bool DofObject::valid_unique_id () const
     870             : {
     871             : #ifdef LIBMESH_ENABLE_UNIQUE_ID
     872   343007723 :   return (DofObject::invalid_unique_id != _unique_id);
     873             : #else
     874             :   return false;
     875             : #endif
     876             : }
     877             : 
     878             : 
     879             : 
     880             : inline
     881    77927082 : processor_id_type DofObject::processor_id () const
     882             : {
     883  1247886478 :   return _processor_id;
     884             : }
     885             : 
     886             : 
     887             : 
     888             : inline
     889   330003618 : processor_id_type & DofObject::processor_id ()
     890             : {
     891   586580427 :   return _processor_id;
     892             : }
     893             : 
     894             : 
     895             : 
     896             : inline
     897    91257134 : void DofObject::processor_id (const processor_id_type pid)
     898             : {
     899  1450510023 :   this->processor_id() = pid;
     900    91257134 : }
     901             : 
     902             : 
     903             : 
     904             : inline
     905       41506 : bool DofObject::valid_processor_id () const
     906             : {
     907       41506 :   return (DofObject::invalid_processor_id != _processor_id);
     908             : }
     909             : 
     910             : 
     911             : 
     912             : inline
     913  4858348374 : unsigned int DofObject::n_systems () const
     914             : {
     915  7376293291 :   const int hdr = _idx_buf.empty() ?
     916  6282185694 :     0 : cast_int<int>(dof_id_signed_type(_idx_buf[0]));
     917  7252249975 :   return hdr >= 0 ? hdr : (-hdr-1);
     918             : }
     919             : 
     920             : 
     921             : 
     922             : inline
     923  1019577120 : unsigned int DofObject::n_pseudo_systems () const
     924             : {
     925  1444837841 :   const int hdr = _idx_buf.empty() ?
     926  1444838083 :     0 : cast_int<int>(dof_id_signed_type(_idx_buf[0]));
     927  1444838083 :   return std::abs(hdr);
     928             : }
     929             : 
     930             : 
     931             : 
     932             : inline
     933  1418397003 : unsigned int DofObject::n_var_groups(const unsigned int s) const
     934             : {
     935  1018118738 :   libmesh_assert_less (s, this->n_systems());
     936             : 
     937  1418397003 :   return (this->end_idx(s) - this->start_idx(s)) / 2;
     938             : }
     939             : 
     940             : 
     941             : 
     942             : inline
     943   392492319 : unsigned int DofObject::n_vars(const unsigned int s,
     944             :                                const unsigned int vg) const
     945             : {
     946   392492319 :   libmesh_assert_less (s,  this->n_systems());
     947   392492319 :   libmesh_assert_less (vg, this->n_var_groups(s));
     948             : 
     949   392492319 :   const unsigned int start_idx_sys = this->start_idx(s);
     950             : 
     951   392492319 :   libmesh_assert_less ((start_idx_sys + 2*vg), _idx_buf.size());
     952             : 
     953             :   return (cast_int<unsigned int>
     954   742359694 :           (_idx_buf[start_idx_sys + 2*vg]) >> ncv_magic_exp);
     955             : }
     956             : 
     957             : 
     958             : 
     959             : inline
     960   211108549 : unsigned int DofObject::n_vars(const unsigned int s) const
     961             : {
     962    72116903 :   libmesh_assert_less (s, this->n_systems());
     963             : 
     964   211108549 :   const unsigned int nvg = this->n_var_groups(s);
     965             : 
     966    72116903 :   unsigned int val=0;
     967             : 
     968   381824792 :   for (unsigned int vg=0; vg<nvg; vg++)
     969   170716243 :     val += this->n_vars(s,vg);
     970             : 
     971   211108549 :   return val;
     972             : }
     973             : 
     974             : 
     975             : 
     976             : 
     977             : inline
     978   203519640 : unsigned int DofObject::n_comp(const unsigned int s,
     979             :                                const unsigned int var) const
     980             : {
     981    40790444 :   libmesh_assert_less (s,   this->n_systems());
     982    40790444 :   libmesh_assert_less (var, this->n_vars(s));
     983             : 
     984   203519640 :   return this->n_comp_group(s,this->var_to_vg(s,var));
     985             : }
     986             : 
     987             : 
     988             : 
     989             : 
     990             : inline
     991   205785958 : unsigned int DofObject::n_comp_group(const unsigned int s,
     992             :                                      const unsigned int vg) const
     993             : {
     994   205785958 :   libmesh_assert_less (s,  this->n_systems());
     995   205785958 :   libmesh_assert_less (vg, this->n_var_groups(s));
     996             : 
     997             :   const unsigned int
     998   205785958 :     start_idx_sys = this->start_idx(s);
     999             : 
    1000   205785958 :   libmesh_assert_less ((start_idx_sys + 2*vg), _idx_buf.size());
    1001             : 
    1002  2338982772 :   return (_idx_buf[start_idx_sys + 2*vg] % ncv_magic);
    1003             : }
    1004             : 
    1005             : 
    1006             : 
    1007             : inline
    1008    86545805 : dof_id_type DofObject::dof_number(const unsigned int s,
    1009             :                                   const unsigned int var,
    1010             :                                   const unsigned int comp) const
    1011             : {
    1012    12876505 :   libmesh_assert_less (s,    this->n_systems());
    1013    12876505 :   libmesh_assert_less (var,  this->n_vars(s));
    1014    12876505 :   libmesh_assert_less (comp, this->n_comp(s,var));
    1015             : 
    1016             :   const std::pair<unsigned int, unsigned int>
    1017    80834533 :     vg_vig = this->var_to_vg_and_offset(s,var);
    1018             : 
    1019             :   const unsigned int
    1020    80834533 :     n_comp = this->n_comp_group(s,vg_vig.first);
    1021             : 
    1022    80834533 :   return this->dof_number(s, vg_vig.first, vg_vig.second,
    1023    99422310 :                           comp, n_comp);
    1024             : }
    1025             : 
    1026             : 
    1027             : 
    1028             : inline
    1029  1545997016 : dof_id_type DofObject::dof_number(const unsigned int s,
    1030             :                                   const unsigned int vg,
    1031             :                                   const unsigned int vig,
    1032             :                                   const unsigned int comp,
    1033             :                                   const unsigned int n_comp) const
    1034             : {
    1035   122824661 :   libmesh_assert_less (s,   this->n_systems());
    1036   122824661 :   libmesh_assert_less (vg,  this->n_var_groups(s));
    1037   122824661 :   libmesh_assert_less (vig, this->n_vars(s,vg));
    1038             : 
    1039             :   const unsigned int
    1040   122824661 :     start_idx_sys = this->start_idx(s);
    1041             : 
    1042   122824661 :   libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
    1043             : 
    1044             :   const dof_id_type
    1045  1565111948 :     base_idx = _idx_buf[start_idx_sys + 2*vg + 1];
    1046             : 
    1047             :   // if the first component is invalid, they
    1048             :   // are all invalid
    1049  1560000604 :   if (base_idx == invalid_id)
    1050           0 :     return invalid_id;
    1051             : 
    1052             :   // otherwise the index is the first component
    1053             :   // index augmented by the component number
    1054             :   else
    1055  1560000604 :     return cast_int<dof_id_type>(base_idx + vig*n_comp + comp);
    1056             : }
    1057             : 
    1058             : 
    1059             : 
    1060             : inline
    1061             : void
    1062      332414 : DofObject::set_extra_integer(const unsigned int index,
    1063             :                              const dof_id_type value)
    1064             : {
    1065           0 :   libmesh_assert_less(index, this->n_extra_integers());
    1066           0 :   libmesh_assert_less(this->n_pseudo_systems(), _idx_buf.size());
    1067             : 
    1068      350483 :   const unsigned int start_idx_i = this->start_idx_ints();
    1069             : 
    1070           0 :   libmesh_assert_less(start_idx_i+index, _idx_buf.size());
    1071      366776 :   _idx_buf[start_idx_i+index] = value;
    1072      332414 : }
    1073             : 
    1074             : 
    1075             : 
    1076             : inline
    1077             : dof_id_type
    1078      389569 : DofObject::get_extra_integer (const unsigned int index) const
    1079             : {
    1080      119736 :   libmesh_assert_less(index, this->n_extra_integers());
    1081      119736 :   libmesh_assert_less(this->n_systems(), _idx_buf.size());
    1082             : 
    1083      405650 :   const unsigned int start_idx_i = this->start_idx_ints();
    1084             : 
    1085      119736 :   libmesh_assert_less(start_idx_i+index, _idx_buf.size());
    1086      421731 :   return _idx_buf[start_idx_i+index];
    1087             : }
    1088             : 
    1089             : 
    1090             : 
    1091             : // If we're using a type T that's a class with no trivial
    1092             : // copy-assignment, -Wclass-memaccess will scream about doing it with
    1093             : // memcpy, even if (as with boost::multiprecision::float128) this is a
    1094             : // false positive.
    1095             : #include "libmesh/ignore_warnings.h"
    1096             : 
    1097             : 
    1098             : 
    1099             : template <typename T>
    1100             : inline
    1101             : void
    1102       63510 : DofObject::set_extra_datum(const unsigned int index,
    1103             :                            const T value)
    1104             : {
    1105             : #ifndef NDEBUG
    1106        4356 :   const unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
    1107             : #endif
    1108        4356 :   libmesh_assert_less(index+n_more_integers, this->n_extra_integers());
    1109        4356 :   libmesh_assert_less(this->n_pseudo_systems(), _idx_buf.size());
    1110             : 
    1111       69369 :   const unsigned int start_idx_i = this->start_idx_ints();
    1112             : 
    1113        4356 :   libmesh_assert_less(start_idx_i+index+n_more_integers, _idx_buf.size());
    1114       75228 :   std::memcpy(&_idx_buf[start_idx_i+index], &value, sizeof(T));
    1115       63510 : }
    1116             : 
    1117             : 
    1118             : 
    1119             : template <typename T>
    1120             : inline
    1121             : T
    1122  1107115539 : DofObject::get_extra_datum (const unsigned int index) const
    1123             : {
    1124             : #ifndef NDEBUG
    1125    14188212 :   const unsigned int n_more_integers = (sizeof(T)-1)/sizeof(dof_id_type);
    1126             : #endif
    1127    14188212 :   libmesh_assert_less(index+n_more_integers, this->n_extra_integers());
    1128    14188212 :   libmesh_assert_less(this->n_systems(), _idx_buf.size());
    1129             : 
    1130  1213316725 :   const unsigned int start_idx_i = this->start_idx_ints();
    1131             : 
    1132    14188212 :   libmesh_assert_less(start_idx_i+index+n_more_integers, _idx_buf.size());
    1133             :   T returnval;
    1134  1319517911 :   std::memcpy(&returnval, &_idx_buf[start_idx_i+index], sizeof(T));
    1135  1107115539 :   return returnval;
    1136             : }
    1137             : 
    1138             : 
    1139             : 
    1140             : #include "libmesh/restore_warnings.h"
    1141             : 
    1142             : 
    1143             : 
    1144             : inline
    1145             : unsigned int
    1146   201856966 : DofObject::n_extra_integers () const
    1147             : {
    1148   201856966 :   if (_idx_buf.empty())
    1149     3801481 :     return 0;
    1150             : 
    1151    83754581 :   const int hdr = dof_id_signed_type(_idx_buf[0]);
    1152    83754581 :   if (hdr >= 0)
    1153     6789810 :     return 0;
    1154             : 
    1155    15905271 :   const unsigned int start_idx_i = this->start_idx_ints();
    1156             : 
    1157    15905271 :   return _idx_buf.size() - start_idx_i;
    1158             : }
    1159             : 
    1160             : 
    1161             : 
    1162             : inline
    1163             : bool
    1164    30500722 : DofObject::has_extra_integers () const
    1165             : {
    1166    58152536 :   if (_idx_buf.empty())
    1167           0 :     return 0;
    1168             : 
    1169    58152536 :   return (dof_id_signed_type(_idx_buf[0]) < 0);
    1170             : }
    1171             : 
    1172             : 
    1173             : 
    1174             : inline
    1175             : std::pair<unsigned int, unsigned int>
    1176   190871128 : DofObject::var_to_vg_and_offset(const unsigned int s,
    1177             :                                 const unsigned int var) const
    1178             : {
    1179   117849711 :   std::pair<unsigned int, unsigned int> returnval(0,0);
    1180             : 
    1181   117849711 :   unsigned int & vg = returnval.first;
    1182   117849711 :   unsigned int & offset = returnval.second;
    1183             : 
    1184   117849711 :   unsigned int vg_start = 0;
    1185    16994311 :   for (; ; vg++)
    1186             :     {
    1187   133940897 :       libmesh_assert_less(vg, this->n_var_groups(s));
    1188             : 
    1189   214304627 :       const unsigned int vg_end = vg_start + this->n_vars(s,vg);
    1190   214304627 :       if (var < vg_end)
    1191             :         {
    1192   197308505 :           offset = var - vg_start;
    1193   190871128 :           return returnval;
    1194             :         }
    1195    16091186 :       vg_start = vg_end;
    1196    16945742 :     }
    1197             : }
    1198             : 
    1199             : 
    1200             : 
    1201             : inline
    1202   200246560 : bool DofObject::has_dofs (const unsigned int sys) const
    1203             : {
    1204   200246560 :   if (sys == libMesh::invalid_uint)
    1205             :     {
    1206   126742384 :       for (auto s : make_range(this->n_systems()))
    1207    40266872 :         if (this->n_vars(s))
    1208        3214 :           return true;
    1209             :     }
    1210             : 
    1211             :   else
    1212             :     {
    1213     5939667 :       libmesh_assert_less (sys, this->n_systems());
    1214             : 
    1215    77721598 :       if (this->n_vars(sys))
    1216     2626987 :         return true;
    1217             :     }
    1218             : 
    1219     4153174 :   return false;
    1220             : }
    1221             : 
    1222             : 
    1223             : 
    1224             : inline
    1225  1759980814 : unsigned int DofObject::start_idx (const unsigned int s) const
    1226             : {
    1227  1759980814 :   libmesh_assert_less (s, this->n_systems());
    1228  1759980814 :   libmesh_assert_less (s, _idx_buf.size());
    1229             : 
    1230  5475576977 :   return cast_int<unsigned int>(std::abs(dof_id_signed_type(_idx_buf[s])));
    1231             : }
    1232             : 
    1233             : 
    1234             : 
    1235             : inline
    1236  1414179724 : unsigned int DofObject::end_idx (const unsigned int s) const
    1237             : {
    1238  1019572764 :   libmesh_assert_less (s, this->n_systems());
    1239  1019572764 :   libmesh_assert_less (s, _idx_buf.size());
    1240             : 
    1241  1870094690 :   return ((s+1) == this->n_pseudo_systems()) ?
    1242   929453038 :     cast_int<unsigned int>(_idx_buf.size()) :
    1243  1063534743 :     cast_int<unsigned int>(_idx_buf[s+1]);
    1244             : }
    1245             : 
    1246             : 
    1247             : 
    1248             : inline
    1249  1230047476 : unsigned int DofObject::start_idx_ints () const
    1250             : {
    1251    28722888 :   libmesh_assert (this->has_extra_integers());
    1252             : 
    1253    28722888 :   unsigned int n_sys = this->n_systems();
    1254             : 
    1255    28722888 :   libmesh_assert_less(this->n_systems(), _idx_buf.size());
    1256  1382100076 :   return n_sys ? cast_int<unsigned int>(_idx_buf[this->n_systems()]) :
    1257  1230047476 :                  (n_sys+1);
    1258             : }
    1259             : 
    1260             : 
    1261             : 
    1262             : inline
    1263             : unsigned int DofObject::end_idx_ints () const
    1264             : {
    1265             :   libmesh_assert (this->has_extra_integers());
    1266             : 
    1267             :   return cast_int<unsigned int>(_idx_buf.size());
    1268             : }
    1269             : 
    1270             : 
    1271             : 
    1272             : inline
    1273     5653242 : void DofObject::set_vg_dof_base(const unsigned int s,
    1274             :                                 const unsigned int vg,
    1275             :                                 const dof_id_type db)
    1276             : {
    1277     5653242 :   libmesh_assert_less (s,  this->n_systems());
    1278     5653242 :   libmesh_assert_less (vg, this->n_var_groups(s));
    1279             : 
    1280             :   const unsigned int
    1281     5653242 :     start_idx_sys = this->start_idx(s);
    1282             : 
    1283     5653242 :   libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
    1284             : 
    1285    84486350 :   _idx_buf[start_idx_sys + 2*vg + 1] = db;
    1286             : 
    1287     5653242 :   libmesh_assert_equal_to (this->vg_dof_base(s,vg), db);
    1288    61147622 : }
    1289             : 
    1290             : 
    1291             : 
    1292             : inline
    1293    14758114 : dof_id_type DofObject::vg_dof_base(const unsigned int s,
    1294             :                                    const unsigned int vg) const
    1295             : {
    1296    14758114 :   libmesh_assert_less (s,  this->n_systems());
    1297    14758114 :   libmesh_assert_less (vg, this->n_var_groups(s));
    1298             : 
    1299             :   const unsigned int
    1300    14758114 :     start_idx_sys = this->start_idx(s);
    1301             : 
    1302    14758114 :   libmesh_assert_less ((start_idx_sys + 2*vg + 1), _idx_buf.size());
    1303             : 
    1304             :   // #ifdef DEBUG
    1305             :   //   std::cout << " [ ";
    1306             :   //   for (auto i : _idx_buf)
    1307             :   //     std::cout << i << " ";
    1308             :   //   std::cout << "]\n";
    1309             :   // #endif
    1310             : 
    1311   123032380 :   return _idx_buf[start_idx_sys + 2*vg + 1];
    1312             : }
    1313             : 
    1314             : 
    1315             : 
    1316             : inline
    1317   200671311 : unsigned int DofObject::var_to_vg (const unsigned int s,
    1318             :                                    const unsigned int var) const
    1319             : {
    1320             :   const unsigned int
    1321   200671311 :     nvg = this->n_var_groups(s);
    1322             : 
    1323   207248496 :   for (unsigned int vg=0, vg_end=0; vg<nvg; vg++)
    1324             :     {
    1325   207248496 :       vg_end += this->n_vars(s,vg);
    1326   207248496 :       if (var < vg_end) return vg;
    1327             :     }
    1328             : 
    1329           0 :   libmesh_error_msg("Error: could not map variable " << var << " to variable group.");
    1330             : }
    1331             : 
    1332             : 
    1333             : 
    1334             : inline
    1335           0 : unsigned int DofObject::system_var_to_vg_var (const unsigned int s,
    1336             :                                               const unsigned int vg,
    1337             :                                               const unsigned int var) const
    1338             : {
    1339           0 :   unsigned int accumulated_sum=0;
    1340             : 
    1341           0 :   for (unsigned int vgc=0; vgc<vg; vgc++)
    1342           0 :     accumulated_sum += this->n_vars(s,vgc);
    1343             : 
    1344           0 :   libmesh_assert_less_equal (accumulated_sum, var);
    1345             : 
    1346           0 :   return (var - accumulated_sum);
    1347             : }
    1348             : 
    1349             : /**
    1350             :  * Comparison object to use with DofObject pointers.  This sorts by id(),
    1351             :  * so when we iterate over a set of DofObjects we visit the objects in
    1352             :  * order of increasing ID.
    1353             :  */
    1354             : struct CompareDofObjectsByID
    1355             : {
    1356           0 :   bool operator()(const DofObject * a,
    1357             :                   const DofObject * b) const
    1358             :   {
    1359           0 :     libmesh_assert (a);
    1360           0 :     libmesh_assert (b);
    1361             : 
    1362           0 :     return a->id() < b->id();
    1363             :   }
    1364             : };
    1365             : 
    1366             : struct CompareDofObjectsByPIDAndThenID
    1367             : {
    1368     3421826 :   bool operator()(const DofObject * a,
    1369             :                   const DofObject * b) const
    1370             :   {
    1371     3421826 :     libmesh_assert (a);
    1372     3421826 :     libmesh_assert (b);
    1373             : 
    1374   778331600 :     if (a->processor_id() < b->processor_id())
    1375       39639 :       return true;
    1376   656792706 :     if (b->processor_id() < a->processor_id())
    1377       33851 :       return false;
    1378             : 
    1379   563573874 :     return a->id() < b->id();
    1380             :   }
    1381             : };
    1382             : 
    1383             : } // namespace libMesh
    1384             : 
    1385             : 
    1386             : #endif // #ifndef LIBMESH_DOF_OBJECT_H

Generated by: LCOV version 1.14