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