LCOV - code coverage report
Current view: top level - include/numerics - static_condensation_dof_map.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4475 (55045b) with base a68cc6 Lines: 7 9 77.8 %
Date: 2026-06-03 14:29:06 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : #ifndef LIBMESH_STATIC_CONDENSATION_DOF_MAP_H
      19             : #define LIBMESH_STATIC_CONDENSATION_DOF_MAP_H
      20             : 
      21             : #include "libmesh/libmesh_config.h"
      22             : 
      23             : #include "libmesh/id_types.h"
      24             : #include "libmesh/libmesh_common.h"
      25             : #include "libmesh/dof_map_base.h"
      26             : #include "libmesh/variable.h"
      27             : #include "libmesh/sparsity_pattern.h"
      28             : #include "libmesh/utility.h"
      29             : 
      30             : #include <unordered_map>
      31             : #include <memory>
      32             : #include <vector>
      33             : 
      34             : namespace libMesh
      35             : {
      36             : class MeshBase;
      37             : class System;
      38             : class DofMap;
      39             : class Elem;
      40             : 
      41             : /**
      42             :  * A class holding degree of freedom information pertinent to static condensation.
      43             :  * Static condensation is a process for reducing the number of unknowns in a
      44             :  * linear(ized) system. It is often used in conjunction with a hybridized discontinuous Galerkin
      45             :  * (HDG) method to reduce the number of unknowns in the linear system to something more on the order
      46             :  * of a continuous Galerkin (CG) method as opposed to a discontinuous Galerkin method. In the HDG
      47             :  * example, degrees of freedom on the element interiors are condensed out and only the degrees of
      48             :  * freedom on element faces are retained in the condensed system. Static condensation is not only
      49             :  * applicable to HDG methods, however. One could also use static condensation with a high order CG
      50             :  * method, again removing internal degrees of freedom and leaving those on element boundaries.
      51             :  *
      52             :  * Users may query this class for condensed space degree of freedom information associated with
      53             :  * elements. Queries with nodes are not supported. This class also holds information for mapping
      54             :  * degree of freedom indices in the global, uncondensed space to local element degree of freedom
      55             :  * numbers. This information is essential in order to build the element Schur complement matrices
      56             :  * that are used to map global system vector and matrix data to the condensed system vector and
      57             :  * matrix data
      58             :  */
      59          96 : class StaticCondensationDofMap : public DofMapBase
      60             : {
      61             : public:
      62             :   StaticCondensationDofMap(MeshBase & mesh, System & system, const DofMap & dof_map);
      63             :   virtual ~StaticCondensationDofMap();
      64             : 
      65             :   //
      66             :   // Unique methods
      67             :   //
      68             : 
      69             :   /**
      70             :    * Build the element global to local index maps
      71             :    */
      72             :   void reinit();
      73             : 
      74             :   /**
      75             :    * Add \p vars to the list of variables not to condense. This can be useful when some variable's
      76             :    * equation is discretized with a DG method or if including the variable in the condensed block
      77             :    * diagonal would result in it being singular
      78             :    */
      79             :   void dont_condense_vars(const std::unordered_set<unsigned int> & vars);
      80             : 
      81             :   /**
      82             :    * @returns our list of variables for whom we do not condense out any dofs
      83             :    */
      84      611840 :   const std::unordered_set<unsigned int> & uncondensed_vars() const { return _uncondensed_vars; }
      85             : 
      86             :   virtual unsigned int n_variables() const override;
      87             : 
      88             :   virtual const Variable & variable(const unsigned int c) const override;
      89             : 
      90             :   virtual void dof_indices(const Elem * const elem,
      91             :                            std::vector<dof_id_type> & di,
      92             :                            const unsigned int vn,
      93             :                            int p_level = -12345) const override;
      94             : 
      95             :   virtual void dof_indices(const Node * const node,
      96             :                            std::vector<dof_id_type> & di,
      97             :                            const unsigned int vn) const override;
      98             : 
      99             :   /*
     100             :    * @returns The dummyish reduced system
     101             :    */
     102             :   const System & reduced_system() const;
     103             : 
     104             :   /*
     105             :    * @returns The mesh
     106             :    */
     107        3551 :   const MeshBase & mesh () const { return _mesh; }
     108             : 
     109             :   /**
     110             :    * Whether we are initialized
     111             :    */
     112        4130 :   bool initialized() const { return _sc_is_initialized; }
     113             : 
     114             :   virtual void clear() override;
     115             : 
     116             :   /**
     117             :    * Retrieve the dof index in the reduced system corresponding to the provided dof index in the
     118             :    * full system. This dof index should be a dof index involved in constraints
     119             :    */
     120             :   dof_id_type get_reduced_from_global_constraint_dof(dof_id_type full_dof) const;
     121             : 
     122             : private:
     123             :   /**
     124             :    * Add an uncondensed dof potentially along with constraining dofs which themselves must/will also
     125             :    * be uncondensed
     126             :    * @param full_dof_number The dof id in the full (uncondensed + condensed) system
     127             :    * @param involved_in_constraints Whether the \p full_dof_number is involved in constraints
     128             :    * @param uncondensed_local_to_global_map A map from uncondensed full dof numbering to local
     129             :    * (element) numbering for a given element
     130             :    * @param local_uncondensed_dofs_set Set of local uncondensed degrees of freedom (numbered in the
     131             :    * full system)
     132             :    * @param nonlocal_uncondensed_dofs Map from processor IDs to sets of nonlocal uncondensed degrees
     133             :    * of freedom (numbered in the full system)
     134             :    * @param elem_uncondensed_dofs Used for temporary storage of uncondensed degrees of freedom
     135             :    * active on an element
     136             :    * @param uncondensed_local_dof_number Counter for number of uncondensed dofs on an element
     137             :    * @param constraint_dofs Set of degrees of freedom numbered in the full system involved in
     138             :    * constraints
     139             :    */
     140             :   void add_uncondensed_dof_plus_constraint_dofs(
     141             :       dof_id_type full_dof_number,
     142             :       bool involved_in_constraints,
     143             :       std::unordered_map<dof_id_type, dof_id_type> & uncondensed_global_to_local_map,
     144             :       std::unordered_set<dof_id_type> & local_uncondensed_dofs_set,
     145             :       std::unordered_map<processor_id_type, std::unordered_set<dof_id_type>> &
     146             :           nonlocal_uncondensed_dofs,
     147             :       std::vector<dof_id_type> & elem_uncondensed_dofs,
     148             :       dof_id_type & uncondensed_local_dof_number,
     149             :       std::unordered_set<dof_id_type> & constraint_dofs);
     150             : 
     151             :   /**
     152             :    * Add an uncondensed dof
     153             :    * @param full_dof_number The dof id in the full (uncondensed + condensed) system
     154             :    * @param involved_in_constraints Whether the \p full_dof_number is involved in constraints
     155             :    * @param uncondensed_local_to_global_map A map from uncondensed full dof numbering to local
     156             :    * (element) numbering for a given element
     157             :    * @param local_uncondensed_dofs_set Set of local uncondensed degrees of freedom (numbered in the
     158             :    * full system)
     159             :    * @param nonlocal_uncondensed_dofs Map from processor IDs to sets of nonlocal uncondensed degrees
     160             :    * of freedom (numbered in the full system)
     161             :    * @param elem_uncondensed_dofs Used for temporary storage of uncondensed degrees of freedom
     162             :    * active on an element
     163             :    * @param uncondensed_local_dof_number Counter for number of uncondensed dofs on an element
     164             :    * @param constraint_dofs Set of degrees of freedom numbered in the full system involved in
     165             :    * constraints
     166             :    */
     167             :   void add_uncondensed_dof(
     168             :       dof_id_type full_dof_number,
     169             :       bool involved_in_constraints,
     170             :       std::unordered_map<dof_id_type, dof_id_type> & uncondensed_global_to_local_map,
     171             :       std::unordered_set<dof_id_type> & local_uncondensed_dofs_set,
     172             :       std::unordered_map<processor_id_type, std::unordered_set<dof_id_type>> &
     173             :           nonlocal_uncondensed_dofs,
     174             :       std::vector<dof_id_type> & elem_uncondensed_dofs,
     175             :       dof_id_type & uncondensed_local_dof_number,
     176             :       std::unordered_set<dof_id_type> & constraint_dofs);
     177             : 
     178             :   /**
     179             :    * Data stored on a per-element basis used to compute element Schur complements and their
     180             :    * applications to vectors
     181             :    */
     182             :   struct DofData
     183             :   {
     184             :     /// The uncondensed degrees of freedom with global numbering corresponding to the the \emph reduced
     185             :     /// system. Note that initially this will actually hold the indices corresponding to the fully
     186             :     /// sized problem, but we will swap it out by the time we are done initializing
     187             :     std::vector<std::vector<dof_id_type>> reduced_space_indices;
     188             : 
     189             :     /// A map from the global degree of freedom number for the full system (condensed + uncondensed)
     190             :     /// to an element local number. If this map is queried with a condensed dof, nothing will be
     191             :     /// found. The size of this container will be the number of uncondensed degrees of freedom whose
     192             :     /// basis functions are nonzero on the element
     193             :     std::unordered_map<dof_id_type, dof_id_type> uncondensed_global_to_local_map;
     194             :     /// A map from the global degree of freedom number for the full system (condensed + uncondensed)
     195             :     /// to an element local number. If this map is queried with an uncondensed dof, nothing will be
     196             :     /// found. The size of this container will be the number of condensed degrees of freedom whose
     197             :     /// basis functions are nonzero on the element
     198             :     std::unordered_map<dof_id_type, dof_id_type> condensed_global_to_local_map;
     199             :   };
     200             : 
     201             :   /// Friend the static condensation matrix class so they can inspect our degree of freedom data
     202             :   friend class StaticCondensation;
     203             : 
     204             :   /// A map from element ID to Schur complement data
     205             :   std::unordered_map<dof_id_type, DofData> _elem_to_dof_data;
     206             : 
     207             :   /// All the uncondensed degrees of freedom (numbered in the "full" uncondensed + condensed
     208             :   /// space). This data member is used for creating subvectors corresponding to only uncondensed
     209             :   /// dofs
     210             :   std::vector<dof_id_type> _local_uncondensed_dofs;
     211             : 
     212             :   MeshBase & _mesh;
     213             :   System & _system;
     214             :   const DofMap & _dof_map;
     215             : 
     216             :   /// Variables for which we will keep all dofs
     217             :   std::unordered_set<unsigned int> _uncondensed_vars;
     218             : 
     219             :   /// Whether our object has been initialized
     220             :   bool _sc_is_initialized;
     221             : 
     222             :   /// The variables in the reduced system
     223             :   std::vector<Variable> _reduced_vars;
     224             : 
     225             :   /// A dummyish system to help with DofObjects
     226             :   System * _reduced_system;
     227             : 
     228             :   /// Owned storage of the reduced system sparsity pattern
     229             :   std::unique_ptr<SparsityPattern::Build> _reduced_sp;
     230             : 
     231             :   /// Number of on-diagonal nonzeros per row in the reduced system
     232             :   std::vector<dof_id_type> _reduced_nnz;
     233             : 
     234             :   /// Number of off-diagonal nonzeros per row in the reduced system
     235             :   std::vector<dof_id_type> _reduced_noz;
     236             : 
     237             :   /// A small map from full system degrees of freedom to reduced/condensed system degrees of freedom
     238             :   /// involved in constraints. This may be leveraged by \p StaticCondensation::set during \p
     239             :   /// DofMap::enforce_constraints_on_jacobian at the very end of Jacobian evaluation
     240             :   std::unordered_map<dof_id_type, dof_id_type> _full_to_reduced_constraint_dofs;
     241             : };
     242             : 
     243             : inline void
     244         272 : StaticCondensationDofMap::dont_condense_vars(const std::unordered_set<unsigned int> & vars)
     245             : {
     246         272 :   _uncondensed_vars.insert(vars.begin(), vars.end());
     247         272 : }
     248             : 
     249             : inline const System & StaticCondensationDofMap::reduced_system() const
     250             : {
     251             :   libmesh_assert(_reduced_system);
     252             :   return *_reduced_system;
     253             : }
     254             : 
     255             : inline dof_id_type
     256           0 : StaticCondensationDofMap::get_reduced_from_global_constraint_dof(const dof_id_type full_dof) const
     257             : {
     258           0 :   return libmesh_map_find(_full_to_reduced_constraint_dofs, full_dof);
     259             : }
     260             : 
     261             : }
     262             : 
     263             : #endif // LIBMESH_STATIC_CONDENSATION_DOF_MAP_H

Generated by: LCOV version 1.14