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_REDUCED_DOF_MAP_H
19 : #define LIBMESH_REDUCED_DOF_MAP_H
20 :
21 : #include "libmesh/libmesh_common.h"
22 : #include "libmesh/dof_map_base.h"
23 : #include "libmesh/variable.h"
24 : #include "libmesh/sparsity_pattern.h"
25 :
26 : #include <memory>
27 : #include <string>
28 : #include <unordered_map>
29 : #include <unordered_set>
30 : #include <vector>
31 :
32 : namespace libMesh
33 : {
34 : class MeshBase;
35 : class System;
36 : class DofMap;
37 : class Elem;
38 : class Node;
39 :
40 : /**
41 : * A degree of freedom map for a reduced space: a subset of the degrees of freedom of a full \p
42 : * DofMap, renumbered contiguously. Each retained degree of freedom keeps the rank that owns it in
43 : * the full space, so the reduced numbering on each rank preserves the full numbering order.
44 : *
45 : * Subclasses select the retained degrees of freedom through \p retain_field_dof() and \p
46 : * retain_scalar_dof(). Static condensation, for instance, retains the degrees of freedom on
47 : * element boundaries, and constraint elimination retains the unconstrained ones. The constraining
48 : * degrees of freedom of every constrained degree of freedom on an element are retained as well,
49 : * whether or not the constrained one is, because constrained element matrices and vectors couple
50 : * them.
51 : *
52 : * This class provides the reduced numbering (\p reduced_dof()), the reduced degrees of freedom of
53 : * each local element and variable (\p dof_indices()), the variables present in the reduced space
54 : * along with a stand-in \p System for them, and the sparsity pattern of matrices in the reduced
55 : * space. This is the information needed to assemble reduced matrices and to build field splits
56 : * of the reduced space.
57 : */
58 128 : class ReducedDofMap : public DofMapBase
59 : {
60 : public:
61 : virtual ~ReducedDofMap();
62 :
63 : /**
64 : * Build the reduced space from the current state of the full degree of freedom map
65 : */
66 : virtual void reinit();
67 :
68 : virtual void clear() override;
69 :
70 : /**
71 : * Whether \p reinit() has built the reduced space
72 : */
73 400 : bool initialized() const { return _initialized; }
74 :
75 : virtual unsigned int n_variables() const override;
76 :
77 : virtual const Variable & variable(const unsigned int c) const override;
78 :
79 : /**
80 : * Fills \p di with the reduced degree of freedom indices of variable \p vn on the active local
81 : * element \p elem, including the constraining degrees of freedom of its constrained degrees of
82 : * freedom
83 : */
84 : virtual void dof_indices(const Elem * const elem,
85 : std::vector<dof_id_type> & di,
86 : const unsigned int vn,
87 : int p_level = -12345) const override;
88 :
89 : /**
90 : * Reduced degree of freedom maps are queried by element only
91 : */
92 : virtual void dof_indices(const Node * const node,
93 : std::vector<dof_id_type> & di,
94 : const unsigned int vn) const override;
95 :
96 : /**
97 : * \returns The reduced index of \p full_dof. \p full_dof must be retained and must be either
98 : * local or used by a local element
99 : */
100 : dof_id_type reduced_dof(dof_id_type full_dof) const;
101 :
102 : /**
103 : * \returns The local retained degrees of freedom in the full numbering, sorted. The reduced
104 : * index of entry \p i is <tt>first_dof() + i</tt>
105 : */
106 0 : const std::vector<dof_id_type> & local_retained_dofs() const { return _local_retained_dofs; }
107 :
108 : /**
109 : * Nests this reduced space in \p parent's, or in the full space if \p parent is null. Only
110 : * degrees of freedom that \p parent retains can be retained, and the parent space is the space
111 : * this one reduces: its vectors are the ones operators on this space are prolonged to and
112 : * restricted from. Takes effect at the next \p reinit(), which must follow the parent's
113 : */
114 360 : void set_parent(const ReducedDofMap * parent) { _parent = parent; }
115 :
116 : /**
117 : * \returns The reduced space this one is nested in, or null for the full space
118 : */
119 75518 : const ReducedDofMap * parent() const { return _parent; }
120 :
121 : /**
122 : * \returns The index of \p full_dof in the parent space, or \p DofObject::invalid_id if the
123 : * parent does not retain it. \p full_dof must be local or used by an active local element
124 : */
125 : dof_id_type parent_dof(dof_id_type full_dof) const;
126 :
127 : /**
128 : * \returns The number of degrees of freedom in the parent space, globally and locally, and the
129 : * parent index range of this rank
130 : */
131 : dof_id_type parent_n_dofs() const;
132 : dof_id_type parent_n_local_dofs() const;
133 : dof_id_type parent_first_dof() const;
134 : dof_id_type parent_end_dof() const;
135 :
136 : /**
137 : * \returns The local retained degrees of freedom in the parent numbering, sorted. Entry \p i is
138 : * the parent index of reduced index <tt>first_dof() + i</tt>
139 : */
140 756 : const std::vector<dof_id_type> & local_retained_parent_dofs() const
141 2268 : { return _local_retained_parent_dofs; }
142 :
143 : /**
144 : * \returns The nonlocal reduced degrees of freedom used by active local elements, sorted: the
145 : * ghost entries of a ghosted vector on this space
146 : */
147 6 : const std::vector<dof_id_type> & send_list() const { return _send_list; }
148 :
149 : /**
150 : * \returns The ghost entries of a ghosted vector on the parent space
151 : */
152 : const std::vector<dof_id_type> & parent_send_list() const;
153 :
154 : /**
155 : * Whether field degree of freedom \p field_dof is retained: the parent retains it and \p
156 : * retain_field_dof() accepts it
157 : */
158 : bool retains_field_dof(const Elem & elem,
159 : unsigned int node_num,
160 : unsigned int var_num,
161 : dof_id_type field_dof) const;
162 :
163 : /**
164 : * Whether SCALAR degree of freedom \p scalar_dof is retained: the parent retains it and \p
165 : * retain_scalar_dof() accepts it
166 : */
167 : bool retains_scalar_dof(dof_id_type scalar_dof) const;
168 :
169 : /**
170 : * \returns The reduced degree of freedom indices on the active local element with id \p
171 : * elem_id, by reduced variable number. Concatenated, these are in the order in which \p
172 : * retained_dof_added() saw them
173 : */
174 : const std::vector<std::vector<dof_id_type>> & elem_dof_indices(dof_id_type elem_id) const;
175 :
176 : /**
177 : * \returns The stand-in system that holds the variables of the reduced space
178 : */
179 : const System & reduced_system() const;
180 :
181 : /**
182 : * \returns The mesh
183 : */
184 : const MeshBase & mesh() const { return _mesh; }
185 :
186 : /**
187 : * \returns The sparsity pattern of matrices in the reduced space. Its rows are indexed by the
188 : * local full degrees of freedom; use \p reduced_n_nz() and \p reduced_n_oz() for preallocation
189 : */
190 : const SparsityPattern::Build & reduced_sparsity() const;
191 :
192 : /**
193 : * \returns The number of on-processor nonzeros in each local row of the reduced space
194 : */
195 396 : const std::vector<dof_id_type> & reduced_n_nz() const { return _reduced_nnz; }
196 :
197 : /**
198 : * \returns The number of off-processor nonzeros in each local row of the reduced space
199 : */
200 396 : const std::vector<dof_id_type> & reduced_n_oz() const { return _reduced_noz; }
201 :
202 : /**
203 : * \returns The reduced index of \p full_dof, or \p DofObject::invalid_id if \p full_dof is
204 : * not retained. \p full_dof must be local or used by an active local element
205 : */
206 : dof_id_type find_reduced_dof(dof_id_type full_dof) const;
207 :
208 : /**
209 : * This space's rule for retaining field degree of freedom \p field_dof of variable \p var_num on
210 : * \p elem, among those the parent retains. \p node_num is the element-local node holding it, or
211 : * \p invalid_uint for an element degree of freedom
212 : */
213 : virtual bool retain_field_dof(const Elem & elem,
214 : unsigned int node_num,
215 : unsigned int var_num,
216 : dof_id_type field_dof) const = 0;
217 :
218 : /**
219 : * This space's rule for retaining degree of freedom \p scalar_dof of a SCALAR variable, among
220 : * those the parent retains
221 : */
222 108 : virtual bool retain_scalar_dof(dof_id_type /*scalar_dof*/) const { return true; }
223 :
224 : protected:
225 : /**
226 : * @param reduced_system_name The name of the stand-in system holding the reduced variables
227 : */
228 : ReducedDofMap(MeshBase & mesh,
229 : System & system,
230 : const DofMap & dof_map,
231 : std::string reduced_system_name);
232 :
233 : /**
234 : * Called by \p reinit() each time \p full_dof is first retained on \p elem, in the order of the
235 : * element's reduced indices
236 : */
237 : virtual void retained_dof_added(const Elem & elem, dof_id_type full_dof);
238 :
239 : /**
240 : * Called by \p reinit() for each field degree of freedom on \p elem that the parent retains and
241 : * \p retain_field_dof() rejects
242 : */
243 : virtual void unretained_dof_found(const Elem & elem, dof_id_type full_dof);
244 :
245 : MeshBase & _mesh;
246 : System & _system;
247 : const DofMap & _dof_map;
248 :
249 : private:
250 : /**
251 : * Retain \p full_dof on \p elem, along with its constraining degrees of freedom, recursively
252 : * @param elem_seen The full degrees of freedom already retained on \p elem
253 : * @param elem_var_dofs The retained full degrees of freedom of the current variable on \p elem
254 : */
255 : void retain_dof_and_constraining_dofs(const Elem * elem,
256 : dof_id_type full_dof,
257 : std::unordered_set<dof_id_type> & elem_seen,
258 : std::vector<dof_id_type> & elem_var_dofs);
259 :
260 : /**
261 : * Retain on \p elem the constraining degrees of freedom of \p full_dof, if it is constrained
262 : */
263 : void retain_constraining_dofs(const Elem * elem,
264 : dof_id_type full_dof,
265 : std::unordered_set<dof_id_type> & elem_seen,
266 : std::vector<dof_id_type> & elem_var_dofs);
267 :
268 : /**
269 : * Record that \p full_dof is retained, on this rank or on its owner
270 : */
271 : void retain_dof(dof_id_type full_dof);
272 :
273 : /// The name of the stand-in reduced system
274 : const std::string _reduced_system_name;
275 :
276 : /// The reduced space this one is nested in, or null for the full space
277 : const ReducedDofMap * _parent;
278 :
279 : /// The local retained degrees of freedom in the parent numbering, sorted
280 : std::vector<dof_id_type> _local_retained_parent_dofs;
281 :
282 : /// The nonlocal reduced degrees of freedom used by active local elements, sorted
283 : std::vector<dof_id_type> _send_list;
284 :
285 : /// Whether \p reinit() has built the reduced space
286 : bool _initialized;
287 :
288 : /// The local retained degrees of freedom in the full numbering, sorted
289 : std::vector<dof_id_type> _local_retained_dofs;
290 :
291 : /// The reduced index of each local full degree of freedom, offset by the first local full degree
292 : /// of freedom. Unretained degrees of freedom map to \p DofObject::invalid_id
293 : std::vector<dof_id_type> _local_full_to_reduced;
294 :
295 : /// The reduced indices of the nonlocal degrees of freedom on local elements, \p
296 : /// DofObject::invalid_id for unretained ones
297 : std::unordered_map<dof_id_type, dof_id_type> _nonlocal_full_to_reduced;
298 :
299 : /// Local retained degrees of freedom, nonlocal retained ones by owner, and nonlocal unretained
300 : /// ones on local elements. Only used during \p reinit()
301 : std::unordered_set<dof_id_type> _local_retained_set;
302 : std::unordered_map<processor_id_type, std::unordered_set<dof_id_type>> _nonlocal_retained;
303 : std::unordered_set<dof_id_type> _nonlocal_unretained;
304 :
305 : /// The reduced degrees of freedom of each active local element, by reduced variable number
306 : std::unordered_map<dof_id_type, std::vector<std::vector<dof_id_type>>> _elem_reduced_dofs;
307 :
308 : /// The variables in the reduced space
309 : std::vector<Variable> _reduced_vars;
310 :
311 : /// A stand-in system to give the reduced variables a system number
312 : System * _reduced_system;
313 :
314 : /// The reduced space sparsity pattern
315 : std::unique_ptr<SparsityPattern::Build> _reduced_sp;
316 :
317 : /// Number of on-processor nonzeros in each local row of the reduced space
318 : std::vector<dof_id_type> _reduced_nnz;
319 :
320 : /// Number of off-processor nonzeros in each local row of the reduced space
321 : std::vector<dof_id_type> _reduced_noz;
322 : };
323 :
324 : inline const System & ReducedDofMap::reduced_system() const
325 : {
326 : libmesh_assert(_reduced_system);
327 : return *_reduced_system;
328 : }
329 :
330 120 : inline const SparsityPattern::Build & ReducedDofMap::reduced_sparsity() const
331 : {
332 120 : libmesh_assert(_reduced_sp);
333 120 : return *_reduced_sp;
334 : }
335 :
336 : }
337 :
338 : #endif // LIBMESH_REDUCED_DOF_MAP_H
|