MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
psubmesh.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_PSUBMESH
13#define MFEM_PSUBMESH
14
16
17#ifdef MFEM_USE_MPI
18
19#include "ptransfermap.hpp"
20#include "../pmesh.hpp"
22#include "submesh.hpp"
23
24namespace mfem
25{
26
27class ParNCSubMesh;
28
29/**
30 * @brief Subdomain representation of a topological parent in another ParMesh.
31 *
32 * ParSubMesh is a subdomain representation of a ParMesh defined on its parents
33 * attributes. The current implementation creates either a domain or surface
34 * subset of the parent Mesh and reuses the parallel distribution.
35 *
36 * The attributes are taken from the parent. That means if a volume is extracted
37 * from a volume, it has the same domain attribute as the parent. Its boundary
38 * attributes are generated (there will be one boundary attribute 1 for all of
39 * the boundaries).
40 *
41 * If a surface is extracted from a volume, the boundary attribute from the
42 * parent is assigned to be the new domain attribute. Its boundary attributes
43 * are generated (there will be one boundary attribute 1 for all of the
44 * boundaries).
45 *
46 * For more customized boundary attributes, the resulting ParSubMesh has to be
47 * postprocessed.
48 *
49 * ParSubMesh maintains the parallel distribution of the elements on
50 * corresponding processors.
51 */
52
53class ParSubMesh : public ParMesh
54{
55 friend class ParNCSubMesh;
56public:
57 using From = SubMesh::From; ///< Convenience type-alias.
58 ParSubMesh() = delete;
59
60 /**
61 * @brief Create a domain ParSubMesh from its parent.
62 *
63 * The ParSubMesh object expects the parent ParMesh object to be valid for
64 * the entire object lifetime. The @a domain_attributes have to mark exactly
65 * one connected subset of the parent Mesh.
66 *
67 * @param[in] parent Parent ParMesh
68 * @param[in] domain_attributes Domain attributes to extract
69 */
70 static ParSubMesh CreateFromDomain(const ParMesh &parent,
71 const Array<int> &domain_attributes);
72
73 /**
74 * @brief Create a surface ParSubMesh from its parent.
75 *
76 * The ParSubMesh object expects the parent ParMesh object to be valid for the
77 * entire object lifetime. The @a boundary_attributes have to mark exactly one
78 * connected subset of the parent Mesh.
79 *
80 * @param[in] parent Parent ParMesh
81 * @param[in] boundary_attributes Boundary attributes to extract
82 */
83 static ParSubMesh CreateFromBoundary(const ParMesh &parent,
84 const Array<int> &boundary_attributes);
85
86 /**
87 * @brief Get the parent ParMesh object
88 */
89 const ParMesh* GetParent() const
90 {
91 return &parent_;
92 }
93
94 /**
95 * @brief Get the From indicator.
96 *
97 * Indicates whether the ParSubMesh has been created from a domain or
98 * surface.
99 */
101 {
102 return from_;
103 }
104
105 /**
106 * @brief Get the parent element id map.
107 *
108 * ParSubMesh element id (array index) to parent ParMesh element id.
109 */
111 {
112 return parent_element_ids_;
113 }
114
115 /**
116 * @brief Get the parent vertex id map.
117 *
118 * ParSubMesh vertex id (array index) to parent ParMesh vertex id.
119 */
121 {
122 return parent_vertex_ids_;
123 }
124
125 /**
126 * @brief Get the parent edge id map
127 *
128 * Submesh edge id (array index) to parent Mesh edge id.
129 */
131 {
132 return parent_edge_ids_;
133 }
134
135 /**
136 * @brief Get the parent face id map.
137 *
138 * ParSubMesh face id (array index) to parent ParMesh face id.
139 */
141 {
142 return parent_face_ids_;
143 }
144
145 /**
146 * @brief Get the relative face orientations
147 *
148 * ParSubMesh element id (array index) to parent ParMesh face orientation.
149 */
151 {
152 return parent_face_ori_;
153 }
154
155 /**
156 * @brief Get the submesh element corresponding to a parent element. -1 ==
157 * not present.
158 * @param pe The parent element id.
159 * @return int
160 */
162 {
163 return (pe == -1 || pe >= parent_to_submesh_element_ids_.Size())
164 ? -1 : parent_to_submesh_element_ids_[pe];
165 }
166
167 /**
168 * @brief Get the submesh vertex corresponding to a parent element. -1 == not
169 * present.
170 * @param pv The parent vertex id.
171 * @return int
172 */
174 {
175 return (pv == -1 || pv >= parent_to_submesh_vertex_ids_.Size())
176 ? -1 : parent_to_submesh_vertex_ids_[pv];
177 }
178
179 /**
180 * @brief Get the submesh edge corresponding to a parent element. -1 == not
181 * present.
182 * @param pe The parent edge id.
183 * @return int
184 */
185 int GetSubMeshEdgeFromParent(int pe) const
186 {
187 return (pe == -1 || pe >= parent_to_submesh_edge_ids_.Size())
188 ? pe : parent_to_submesh_edge_ids_[pe];
189 }
190
191 /**
192 * @brief Get the submesh face corresponding to a parent element. -1 == not
193 * present.
194 * @param pf The parent face id.
195 * @return int
196 */
197 int GetSubMeshFaceFromParent(int pf) const
198 {
199 return (pf == -1 || pf >= parent_to_submesh_face_ids_.Size())
200 ? pf : parent_to_submesh_face_ids_[pf];
201 }
202
203 /**
204 * @brief Transfer the dofs of a ParGridFunction.
205 *
206 * The @a src ParGridFunction can either be defined on a ParMesh or a
207 * ParSubMesh and is transferred appropriately.
208 *
209 * @note Either @a src or @a dst has to be defined on a ParSubMesh.
210 *
211 * @param[in] src
212 * @param[out] dst
213 */
214 static void Transfer(const ParGridFunction &src, ParGridFunction &dst);
215
216 /**
217 * @brief Create a Transfer Map object.
218 *
219 * The @a src ParGridFunction can either be defined on a ParMesh or a
220 * ParSubMesh and is transferred appropriately.
221 *
222 * @note Either @a src or @a dst has to be defined on a ParSubMesh.
223 */
225 const ParGridFunction &dst);
226
227 /**
228 * @brief Check if ParMesh @a m is a ParSubMesh.
229 *
230 * @param m The input ParMesh
231 */
232 static bool IsParSubMesh(const ParMesh *m)
233 {
234 return dynamic_cast<const ParSubMesh *>(m) != nullptr;
235 }
236
237private:
238 ParSubMesh(const ParMesh &parent, SubMesh::From from,
239 const Array<int> &attributes);
240
241 /**
242 * @brief Find shared vertices on the ParSubMesh.
243 *
244 * Uses the parent GroupCommunicator to determine shared vertices.
245 * Collective. Limited to 32 ranks.
246 *
247 * Array of integer bitfields to indicate if rank X (bit location) has shared
248 * vtx Y (array index).
249 *
250 * Example with 4 ranks and X shared vertices.
251 * * R0-R3 indicate ranks 0 to 3
252 * * v0-v3 indicate vertices 0 to 3
253 * The array is used as follows (only relevant bits shown):
254 *
255 * rhvtx[0] = [0...0 1 0 1] Rank 0 and 2 have shared vertex 0
256 * rhvtx[1] = [0...0 1 1 1] Rank 0, 1 and 2 have shared vertex 1
257 * rhvtx[2] = [0...0 0 1 1] Rank 0 and 1 have shared vertex 2
258 * rhvtx[3] = [0...1 0 1 0] Rank 1 and 3 have shared vertex 3. Corner case
259 * which shows that a rank can contribute the shared vertex, but the adjacent
260 * element or edge might not be included in the relevant SubMesh.
261 *
262 * +--------------+--------------+...
263 * | |v0 |
264 * | R0 | R2 | R3
265 * | | |
266 * +--------------+--------------+...
267 * | |v1 |
268 * | R0 | R1 | R3
269 * | |v2 |v3
270 * +--------------+--------------+...
271 *
272 * @param[out] rhvtx Encoding of which rank contains which vertex.
273 */
274 void FindSharedVerticesRanks(Array<int> &rhvtx);
275
276 /**
277 * @brief Find shared edges on the ParSubMesh.
278 *
279 * Uses the parent GroupCommunicator to determine shared edges. Collective.
280 * Limited to groups containing less than 32 ranks.
281 *
282 * See FindSharedVerticesRanks for the encoding for @a rhe.
283 *
284 * @param[out] rhe Encoding of which rank contains which edge.
285 */
286 void FindSharedEdgesRanks(Array<int> &rhe);
287
288
289 /**
290 * @brief Find shared faces on the ParSubMesh.
291 *
292 * Uses the parent GroupCommunicator to determine shared faces. Collective.
293 *
294 * The encoded output arrays @a rhq and @a rht contain either 0, 1 or 2 for
295 * each shared face.
296 *
297 * 0: Face might have been a shared face in the parent ParMesh, but is
298 * not contained in the ParSubMesh.
299 * 1: Face is contained in the ParSubMesh but only on one rank.
300 * 2: Face is contained in the ParSubMesh and shared by two ranks. This
301 * is the only feasible entity of a shared face in a ParSubMesh.
302 *
303 * @param[out] rhq Encoding of which rank contains which face quadrilateral.
304 */
305 void FindSharedFacesRanks(Array<int>& rht, Array<int> &rhq);
306
307 /**
308 * @brief Append shared vertices encoded in @a rhvtx to @a groups.
309 *
310 * @param[in,out] groups
311 * @param[in,out] rhvtx Encoding of which rank contains which vertex. The
312 * output is reused s.t. the array index i (the vertex id) is the associated
313 * group.
314 */
315 void AppendSharedVerticesGroups(ListOfIntegerSets &groups, Array<int> &rhvtx);
316
317 /**
318 * @brief Append shared edges encoded in @a rhe to @a groups.
319 *
320 * @param[in,out] groups
321 * @param[in,out] rhe Encoding of which rank contains which edge. The output
322 * is reused s.t. the array index i (the edge id) is the associated group.
323 */
324 void AppendSharedEdgesGroups(ListOfIntegerSets &groups, Array<int> &rhe);
325
326 /**
327 * @brief Append shared faces encoded in @a rhq and @a rht to @a groups.
328 *
329 * @param[in,out] groups
330 * @param[in,out] rht Encoding of which rank contains which face triangle.
331 * The output is reused s.t. the array index i (the face triangle id) is the
332 * associated group. "Rank Has Triangle"
333 * @param[in,out] rhq Encoding of which rank contains which face
334 * quadrilateral. The output is reused s.t. the array index i (the face
335 * quadrilateral id) is the associated group. "Rank Has Quad"
336 */
337 void AppendSharedFacesGroups(ListOfIntegerSets &groups, Array<int>& rht,
338 Array<int> &rhq);
339
340 /**
341 * @brief Build vertex group.
342 *
343 * @param[in] ngroups Number of groups.
344 * @param[in] rhvtx Encoding of which rank contains which vertex.
345 * @param[in] nsverts Number of shared vertices.
346 */
347 void BuildVertexGroup(int ngroups, const Array<int>& rhvtx, int& nsverts);
348
349 /**
350 * @brief Build edge group.
351 *
352 * @param[in] ngroups Number of groups.
353 * @param[in] rhe Encoding of which rank contains which edge.
354 * @param[in] nsedges Number of shared edges.
355 */
356 void BuildEdgeGroup(int ngroups, const Array<int>& rhe, int& nsedges);
357
358 /**
359 * @brief Build face group.
360 *
361 * @param[in] ngroups Number of groups.
362 * @param[in] rht Encoding of which rank contains which face triangle.
363 * @param[in] nstrias Number of shared face triangles.
364 * @param[in] rhq Encoding of which rank contains which face quadrilateral.
365 * @param[in] nsquads Number of shared face quadrilaterals.
366 */
367 void BuildFaceGroup(int ngroups, const Array<int>& rht, int& nstrias,
368 const Array<int>& rhq, int& nsquads);
369
370 /**
371 * @brief Build the shared vertex to local vertex mapping.
372 *
373 * @param nsverts Number of shared vertices.
374 * @param rhvtx Encoding of which rank contains which vertex.
375 */
376 void BuildSharedVerticesMapping(const int nsverts, const Array<int>& rhvtx);
377
378 /**
379 * @brief Build the shared edge to local edge mapping.
380 *
381 * @param[in] nsedges Number of shared edges.
382 * @param[in] rhe Encoding of which rank contains which edge.
383 */
384 void BuildSharedEdgesMapping(const int nsedges, const Array<int>& rhe);
385
386 /**
387 * @brief Build the shared faces to local faces mapping.
388 *
389 * Shared faces are divided into triangles and quadrilaterals.
390 *
391 * @param[in] nstrias Number of shared face triangles.
392 * @param[in] rht Encoding of which rank contains which face triangle.
393 * @param[in] nsquads Number of shared face quadrilaterals.
394 * @param[in] rhq Encoding of which rank contains which face quadrilateral.
395 */
396 void BuildSharedFacesMapping(const int nstrias, const Array<int>& rht,
397 const int nsquads, const Array<int>& rhq);
398
399
400 std::unordered_map<int, int>
401 FindGhostBoundaryElementAttributes() const;
402
403 /// The parent Mesh
404 const ParMesh &parent_;
405
406 /// Optional nonconformal submesh. Managed via pncmesh pointer in base class.
407 ParNCSubMesh *pncsubmesh_;
408
409 /// Indicator from which part of the parent ParMesh the ParSubMesh is going
410 /// to be created.
411 SubMesh::From from_;
412
413 /// Attributes on the parent ParMesh on which the ParSubMesh is created.
414 /// Could either be domain or boundary attributes (determined by from_).
415 Array<int> attributes_;
416
417 /// Mapping from ParSubMesh element ids (index of the array), to the parent
418 /// ParMesh element ids.
419 Array<int> parent_element_ids_;
420
421 /// Mapping from ParSubMesh vertex ids (index of the array), to the parent
422 /// ParMesh vertex ids.
423 Array<int> parent_vertex_ids_;
424
425 /// Mapping from ParSubMesh edge ids (index of the array), to the parent
426 /// ParMesh edge ids.
427 Array<int> parent_edge_ids_;
428
429 /// Mapping from ParSubMesh face ids (index of the array), to the parent
430 /// ParMesh face ids.
431 Array<int> parent_face_ids_;
432
433 /// Mapping from SubMesh face ids (index of the array), to the orientation of
434 /// the face relative to the parent face.
435 Array<int> parent_face_ori_;
436
437 /// Mapping from parent ParMesh element ids (index of the array), to the
438 /// ParSubMesh element ids. Inverse map of parent_element_ids_.
439 Array<int> parent_to_submesh_element_ids_;
440
441 /// Mapping from parent ParMesh vertex ids (index of the array), to the
442 /// ParSubMesh vertex ids. Inverse map of parent_vertex_ids_.
443 Array<int> parent_to_submesh_vertex_ids_;
444
445 /// Mapping from parent ParMesh edge ids (index of the array), to the
446 /// ParSubMesh edge ids. Inverse map of parent_edge_ids_.
447 Array<int> parent_to_submesh_edge_ids_;
448
449 /// Mapping from parent ParMesh face ids (index of the array), to the
450 /// ParSubMesh face ids. Inverse map of parent_face_ids_.
451 Array<int> parent_to_submesh_face_ids_;
452};
453
454} // namespace mfem
455
456#endif // MFEM_USE_MPI
457
458#endif
int Size() const
Return the logical size of the array.
Definition array.hpp:147
List of integer sets.
Definition sets.hpp:51
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:288
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:34
Class representing a Parallel Nonconformal SubMesh. This is only used by ParSubMesh.
Subdomain representation of a topological parent in another ParMesh.
Definition psubmesh.hpp:54
int GetSubMeshEdgeFromParent(int pe) const
Get the submesh edge corresponding to a parent element. -1 == not present.
Definition psubmesh.hpp:185
static bool IsParSubMesh(const ParMesh *m)
Check if ParMesh m is a ParSubMesh.
Definition psubmesh.hpp:232
const Array< int > & GetParentElementIDMap() const
Get the parent element id map.
Definition psubmesh.hpp:110
int GetSubMeshFaceFromParent(int pf) const
Get the submesh face corresponding to a parent element. -1 == not present.
Definition psubmesh.hpp:197
int GetSubMeshVertexFromParent(int pv) const
Get the submesh vertex corresponding to a parent element. -1 == not present.
Definition psubmesh.hpp:173
static ParSubMesh CreateFromDomain(const ParMesh &parent, const Array< int > &domain_attributes)
Create a domain ParSubMesh from its parent.
Definition psubmesh.cpp:27
static ParTransferMap CreateTransferMap(const ParGridFunction &src, const ParGridFunction &dst)
Create a Transfer Map object.
const Array< int > & GetParentVertexIDMap() const
Get the parent vertex id map.
Definition psubmesh.hpp:120
const Array< int > & GetParentEdgeIDMap() const
Get the parent edge id map.
Definition psubmesh.hpp:130
const Array< int > & GetParentFaceOrientations() const
Get the relative face orientations.
Definition psubmesh.hpp:150
const ParMesh * GetParent() const
Get the parent ParMesh object.
Definition psubmesh.hpp:89
ParSubMesh()=delete
const Array< int > & GetParentFaceIDMap() const
Get the parent face id map.
Definition psubmesh.hpp:140
int GetSubMeshElementFromParent(int pe) const
Get the submesh element corresponding to a parent element. -1 == not present.
Definition psubmesh.hpp:161
static void Transfer(const ParGridFunction &src, ParGridFunction &dst)
Transfer the dofs of a ParGridFunction.
static ParSubMesh CreateFromBoundary(const ParMesh &parent, const Array< int > &boundary_attributes)
Create a surface ParSubMesh from its parent.
Definition psubmesh.cpp:33
SubMesh::From GetFrom() const
Get the From indicator.
Definition psubmesh.hpp:100
ParTransferMap represents a mapping of degrees of freedom from a source ParGridFunction to a destinat...
From
Indicator from which part of the parent Mesh the SubMesh is created.
Definition submesh.hpp:49