LCOV - code coverage report
Current view: top level - include/numerics - static_condensation_dof_map.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 6 8 75.0 %
Date: 2025-08-19 19:27:09 Functions: 5 6 83.3 %
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             : #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          60 : 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        3786 :   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             :    * Whether we are initialized
     106             :    */
     107         490 :   bool initialized() const { return _sc_is_initialized; }
     108             : 
     109             :   virtual void clear() override;
     110             : 
     111             :   /**
     112             :    * Retrieve the dof index in the reduced system corresponding to the provided dof index in the
     113             :    * full system. This dof index should be a dof index involved in constraints
     114             :    */
     115             :   dof_id_type get_reduced_from_global_constraint_dof(dof_id_type full_dof) const;
     116             : 
     117             : private:
     118             :   /**
     119             :    * Add an uncondensed dof potentially along with constraining dofs which themselves must/will also
     120             :    * be uncondensed
     121             :    * @param full_dof_number The dof id in the full (uncondensed + condensed) system
     122             :    * @param involved_in_constraints Whether the \p full_dof_number is involved in constraints
     123             :    * @param uncondensed_local_to_global_map A map from uncondensed full dof numbering to local
     124             :    * (element) numbering for a given element
     125             :    * @param local_uncondensed_dofs_set Set of local uncondensed degrees of freedom (numbered in the
     126             :    * full system)
     127             :    * @param nonlocal_uncondensed_dofs Map from processor IDs to sets of nonlocal uncondensed degrees
     128             :    * of freedom (numbered in the full system)
     129             :    * @param elem_uncondensed_dofs Used for temporary storage of uncondensed degrees of freedom
     130             :    * active on an element
     131             :    * @param uncondensed_local_dof_number Counter for number of uncondensed dofs on an element
     132             :    * @param constraint_dofs Set of degrees of freedom numbered in the full system involved in
     133             :    * constraints
     134             :    */
     135             :   void add_uncondensed_dof_plus_constraint_dofs(
     136             :       dof_id_type full_dof_number,
     137             :       bool involved_in_constraints,
     138             :       std::unordered_map<dof_id_type, dof_id_type> & uncondensed_global_to_local_map,
     139             :       std::unordered_set<dof_id_type> & local_uncondensed_dofs_set,
     140             :       std::unordered_map<processor_id_type, std::unordered_set<dof_id_type>> &
     141             :           nonlocal_uncondensed_dofs,
     142             :       std::vector<dof_id_type> & elem_uncondensed_dofs,
     143             :       dof_id_type & uncondensed_local_dof_number,
     144             :       std::unordered_set<dof_id_type> & constraint_dofs);
     145             : 
     146             :   /**
     147             :    * Add an uncondensed dof
     148             :    * @param full_dof_number The dof id in the full (uncondensed + condensed) system
     149             :    * @param involved_in_constraints Whether the \p full_dof_number is involved in constraints
     150             :    * @param uncondensed_local_to_global_map A map from uncondensed full dof numbering to local
     151             :    * (element) numbering for a given element
     152             :    * @param local_uncondensed_dofs_set Set of local uncondensed degrees of freedom (numbered in the
     153             :    * full system)
     154             :    * @param nonlocal_uncondensed_dofs Map from processor IDs to sets of nonlocal uncondensed degrees
     155             :    * of freedom (numbered in the full system)
     156             :    * @param elem_uncondensed_dofs Used for temporary storage of uncondensed degrees of freedom
     157             :    * active on an element
     158             :    * @param uncondensed_local_dof_number Counter for number of uncondensed dofs on an element
     159             :    * @param constraint_dofs Set of degrees of freedom numbered in the full system involved in
     160             :    * constraints
     161             :    */
     162             :   void add_uncondensed_dof(
     163             :       dof_id_type full_dof_number,
     164             :       bool involved_in_constraints,
     165             :       std::unordered_map<dof_id_type, dof_id_type> & uncondensed_global_to_local_map,
     166             :       std::unordered_set<dof_id_type> & local_uncondensed_dofs_set,
     167             :       std::unordered_map<processor_id_type, std::unordered_set<dof_id_type>> &
     168             :           nonlocal_uncondensed_dofs,
     169             :       std::vector<dof_id_type> & elem_uncondensed_dofs,
     170             :       dof_id_type & uncondensed_local_dof_number,
     171             :       std::unordered_set<dof_id_type> & constraint_dofs);
     172             : 
     173             :   /**
     174             :    * Data stored on a per-element basis used to compute element Schur complements and their
     175             :    * applications to vectors
     176             :    */
     177             :   struct DofData
     178             :   {
     179             :     /// The uncondensed degrees of freedom with global numbering corresponding to the the \emph reduced
     180             :     /// system. Note that initially this will actually hold the indices corresponding to the fully
     181             :     /// sized problem, but we will swap it out by the time we are done initializing
     182             :     std::vector<std::vector<dof_id_type>> reduced_space_indices;
     183             : 
     184             :     /// A map from the global degree of freedom number for the full system (condensed + uncondensed)
     185             :     /// to an element local number. If this map is queried with a condensed dof, nothing will be
     186             :     /// found. The size of this container will be the number of uncondensed degrees of freedom whose
     187             :     /// basis functions are nonzero on the element
     188             :     std::unordered_map<dof_id_type, dof_id_type> uncondensed_global_to_local_map;
     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 an uncondensed dof, nothing will be
     191             :     /// found. The size of this container will be the number of condensed degrees of freedom whose
     192             :     /// basis functions are nonzero on the element
     193             :     std::unordered_map<dof_id_type, dof_id_type> condensed_global_to_local_map;
     194             :   };
     195             : 
     196             :   /// Friend the static condensation matrix class so they can inspect our degree of freedom data
     197             :   friend class StaticCondensation;
     198             : 
     199             :   /// A map from element ID to Schur complement data
     200             :   std::unordered_map<dof_id_type, DofData> _elem_to_dof_data;
     201             : 
     202             :   /// All the uncondensed degrees of freedom (numbered in the "full" uncondensed + condensed
     203             :   /// space). This data member is used for creating subvectors corresponding to only uncondensed
     204             :   /// dofs
     205             :   std::vector<dof_id_type> _local_uncondensed_dofs;
     206             : 
     207             :   MeshBase & _mesh;
     208             :   System & _system;
     209             :   const DofMap & _dof_map;
     210             : 
     211             :   /// Variables for which we will keep all dofs
     212             :   std::unordered_set<unsigned int> _uncondensed_vars;
     213             : 
     214             :   /// Whether our object has been initialized
     215             :   bool _sc_is_initialized;
     216             : 
     217             :   /// The variables in the reduced system
     218             :   std::vector<Variable> _reduced_vars;
     219             : 
     220             :   /// A dummyish system to help with DofObjects
     221             :   System * _reduced_system;
     222             : 
     223             :   /// Owned storage of the reduced system sparsity pattern
     224             :   std::unique_ptr<SparsityPattern::Build> _reduced_sp;
     225             : 
     226             :   /// Number of on-diagonal nonzeros per row in the reduced system
     227             :   std::vector<dof_id_type> _reduced_nnz;
     228             : 
     229             :   /// Number of off-diagonal nonzeros per row in the reduced system
     230             :   std::vector<dof_id_type> _reduced_noz;
     231             : 
     232             :   /// A small map from full system degrees of freedom to reduced/condensed system degrees of freedom
     233             :   /// involved in constraints. This may be leveraged by \p StaticCondensation::set during \p
     234             :   /// DofMap::enforce_constraints_on_jacobian at the very end of Jacobian evaluation
     235             :   std::unordered_map<dof_id_type, dof_id_type> _full_to_reduced_constraint_dofs;
     236             : };
     237             : 
     238             : inline void
     239         272 : StaticCondensationDofMap::dont_condense_vars(const std::unordered_set<unsigned int> & vars)
     240             : {
     241         272 :   _uncondensed_vars.insert(vars.begin(), vars.end());
     242         272 : }
     243             : 
     244             : inline const System & StaticCondensationDofMap::reduced_system() const
     245             : {
     246             :   libmesh_assert(_reduced_system);
     247             :   return *_reduced_system;
     248             : }
     249             : 
     250             : inline dof_id_type
     251           0 : StaticCondensationDofMap::get_reduced_from_global_constraint_dof(const dof_id_type full_dof) const
     252             : {
     253           0 :   return libmesh_map_find(_full_to_reduced_constraint_dofs, full_dof);
     254             : }
     255             : 
     256             : }
     257             : 
     258             : #endif // LIBMESH_STATIC_CONDENSATION_DOF_MAP_H

Generated by: LCOV version 1.14