12 #include "../../config/config.hpp"
17 #include <unordered_set>
21 #include "../segment.hpp"
29 return ParSubMesh(parent, SubMesh::From::Domain, domain_attributes);
35 return ParSubMesh(parent, SubMesh::From::Boundary, boundary_attributes);
39 Array<int> &attributes) : parent_(parent), from_(from), attributes_(attributes)
43 MFEM_ABORT(
"SubMesh does not support non-conforming meshes");
50 if (from == SubMesh::From::Domain)
54 std::tie(parent_vertex_ids_,
58 else if (from == SubMesh::From::Boundary)
62 std::tie(parent_vertex_ids_,
73 parent_to_submesh_vertex_ids_ = -1;
74 for (
int i = 0; i < parent_vertex_ids_.
Size(); i++)
76 parent_to_submesh_vertex_ids_[parent_vertex_ids_[i]] = i;
79 DSTable v2v(parent_.
GetNV());
87 int parent_edge_id = v2v(parent_vertex_ids_[lv[0]], parent_vertex_ids_[lv[1]]);
88 parent_edge_ids_.
Append(parent_edge_id);
92 parent_to_submesh_edge_ids_ = -1;
93 for (
int i = 0; i < parent_edge_ids_.
Size(); i++)
95 parent_to_submesh_edge_ids_[parent_edge_ids_[i]] = i;
101 parent_element_ids_);
104 parent_to_submesh_face_ids_ = -1;
105 for (
int i = 0; i < parent_face_ids_.
Size(); i++)
107 parent_to_submesh_face_ids_[parent_face_ids_[i]] = i;
111 ListOfIntegerSets groups;
114 group.Recreate(1, &
MyRank);
115 groups.Insert(group);
122 FindSharedVerticesRanks(rhvtx);
123 AppendSharedVerticesGroups(groups, rhvtx);
126 FindSharedEdgesRanks(rhe);
127 AppendSharedEdgesGroups(groups, rhe);
132 FindSharedFacesRanks(rht, rhq);
133 AppendSharedFacesGroups(groups, rht, rhq);
139 int ngroups = groups.Size()-1;
141 int nsverts, nsedges, nstrias, nsquads;
142 BuildVertexGroup(ngroups, rhvtx, nsverts);
143 BuildEdgeGroup(ngroups, rhe, nsedges);
146 BuildFaceGroup(ngroups, rht, nstrias, rhq, nsquads);
159 BuildSharedVerticesMapping(nsverts, rhvtx);
160 BuildSharedEdgesMapping(nsedges, rhe);
163 BuildSharedFacesMapping(nstrias, rht, nsquads, rhq);
191 Array<int> parent_face_to_be;
204 int pbeid = parent_face_to_be[parent_face_ids_[i]];
227 const GridFunction *parent_nodes = parent_.
GetNodes();
230 const FiniteElementSpace *parent_fes = parent_nodes->FESpace();
233 parent_fes->FEColl()->GetOrder(),
234 parent_fes->IsDGSpace(),
236 parent_fes->GetOrdering());
238 const ParGridFunction* pn =
dynamic_cast<const ParGridFunction*
>
241 "Internal error. Object is supposed to be ParGridFunction.");
243 ParGridFunction* n =
dynamic_cast<ParGridFunction*
>
246 "Internal error. Object is supposed to be ParGridFunction.");
258 void ParSubMesh::FindSharedVerticesRanks(Array<int> &rhvtx)
261 GroupCommunicator svert_comm(parent_.
gtopo);
264 int nsvtx = svert_comm.GroupLDofTable().Size_of_connections();
266 rhvtx.SetSize(nsvtx);
271 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
274 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
275 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
278 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
279 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
281 const int my_group_id = my_group_id_ptr-group_lproc;
286 int submesh_vertex_id = parent_to_submesh_vertex_ids_[plvtx];
287 if (submesh_vertex_id != -1)
289 rhvtx[sv] |= 1 << my_group_id;
296 svert_comm.Bcast<
int>(rhvtx, 0);
299 void ParSubMesh::FindSharedEdgesRanks(Array<int> &rhe)
302 GroupCommunicator sedge_comm(parent_.
gtopo);
305 int nsedges = sedge_comm.GroupLDofTable().Size_of_connections();
308 rhe.SetSize(nsedges);
313 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
316 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
317 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
320 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
321 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
324 const int my_group_id = my_group_id_ptr-group_lproc;
326 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
330 int submesh_edge_id = parent_to_submesh_edge_ids_[ple];
331 if (submesh_edge_id != -1)
333 rhe[se] |= 1 << my_group_id;
340 sedge_comm.Bcast<
int>(rhe, 0);
343 void ParSubMesh::FindSharedFacesRanks(Array<int>& rht, Array<int> &rhq)
345 GroupCommunicator squad_comm(parent_.
gtopo);
348 int nsquad = squad_comm.GroupLDofTable().Size_of_connections();
361 int submesh_face_id = parent_to_submesh_face_ids_[plq];
362 if (submesh_face_id != -1)
371 squad_comm.Bcast<
int>(rhq, 0);
373 GroupCommunicator stria_comm(parent_.
gtopo);
376 int nstria = stria_comm.GroupLDofTable().Size_of_connections();
381 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
389 int submesh_face_id = parent_to_submesh_face_ids_[plt];
390 if (submesh_face_id != -1)
399 stria_comm.Bcast<
int>(rht, 0);
403 void ParSubMesh::AppendSharedVerticesGroups(ListOfIntegerSets &groups,
408 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
411 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
412 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
415 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
416 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
418 const int my_group_id = my_group_id_ptr-group_lproc;
424 int submesh_vtx = parent_to_submesh_vertex_ids_[plvtx];
427 if (submesh_vtx == -1)
432 else if (rhvtx[sv] & ~(1 << my_group_id))
435 MFEM_ASSERT(rhvtx[sv] & (1 << my_group_id),
"error again");
438 Array<int> &ranks = group;
440 for (
int i = 0; i < group_sz; i++)
442 if ((rhvtx[sv] >> i) & 1)
447 MFEM_ASSERT(ranks.Size() >= 2,
"internal error");
449 rhvtx[sv] = groups.Insert(group) - 1;
460 void ParSubMesh::AppendSharedEdgesGroups(ListOfIntegerSets &groups,
465 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
468 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
469 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
472 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
473 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
475 const int my_group_id = my_group_id_ptr-group_lproc;
477 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
481 int submesh_edge = parent_to_submesh_edge_ids_[ple];
484 if (submesh_edge == -1)
489 else if (rhe[se] & ~(1 << my_group_id))
494 Array<int> &ranks = group;
496 for (
int i = 0; i < group_sz; i++)
498 if ((rhe[se] >> i) & 1)
503 MFEM_ASSERT(ranks.Size() >= 2,
"internal error");
505 rhe[se] = groups.Insert(group) - 1;
516 void ParSubMesh::AppendSharedFacesGroups(ListOfIntegerSets &groups,
517 Array<int>& rht, Array<int> &rhq)
519 IntegerSet quad_group;
527 MFEM_ASSERT(group_sz == 2,
"internal error");
531 int submesh_face_id = parent_to_submesh_face_ids_[plq];
534 if (submesh_face_id == -1)
539 else if (rhq[
sq] == group_sz)
545 Array<int> &ranks = quad_group;
550 rhq[
sq] = groups.Insert(quad_group) - 1;
560 IntegerSet tria_group;
562 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
568 MFEM_ASSERT(group_sz == 2,
"internal error");
572 int submesh_face_id = parent_to_submesh_face_ids_[plt];
575 if (submesh_face_id == -1)
580 else if (rht[st] == group_sz)
586 Array<int> &ranks = tria_group;
591 rht[st] = groups.Insert(tria_group) - 1;
602 void ParSubMesh::BuildVertexGroup(
int ngroups,
const Array<int>& rhvtx,
606 for (
int i = 0; i < rhvtx.Size(); i++)
616 for (
int i = 0; i < rhvtx.Size(); i++)
626 void ParSubMesh::BuildEdgeGroup(
int ngroups,
const Array<int>& rhe,
630 for (
int i = 0; i < rhe.Size(); i++)
640 for (
int i = 0; i < rhe.Size(); i++)
650 void ParSubMesh::BuildFaceGroup(
int ngroups,
const Array<int>& rht,
651 int& nstrias,
const Array<int>& rhq,
int& nsquads)
654 for (
int i = 0; i < rhq.Size(); i++)
664 for (
int i = 0; i < rhq.Size(); i++)
674 for (
int i = 0; i < rht.Size(); i++)
684 for (
int i = 0; i < rht.Size(); i++)
694 void ParSubMesh::BuildSharedVerticesMapping(
const int nsverts,
695 const Array<int>& rhvtx)
699 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
705 int submesh_vtx_id = parent_to_submesh_vertex_ids_[plvtx];
706 if ((submesh_vtx_id == -1) || (rhvtx[sv] == -1))
718 void ParSubMesh::BuildSharedEdgesMapping(
const int sedges_ct,
719 const Array<int>& rhe)
724 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
726 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
730 int submesh_edge_id = parent_to_submesh_edge_ids_[ple];
731 if ((submesh_edge_id == -1) || rhe[se] == -1)
747 void ParSubMesh::BuildSharedFacesMapping(
const int nstrias,
748 const Array<int>& rht,
749 const int nsquads,
const Array<int>& rhq)
761 int submesh_face_id = parent_to_submesh_face_ids_[plq];
762 if ((submesh_face_id == -1) || rhq[
sq] == -1)
771 shared_quads.Append(Vert4(vert[0], vert[1], vert[2], vert[3]));
777 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
783 int submesh_face_id = parent_to_submesh_face_ids_[plt];
784 if ((submesh_face_id == -1) || rht[st] == -1)
814 #endif // MFEM_USE_MPI
void Create(ListOfIntegerSets &groups, int mpitag)
Set up the group topology given the list of sets of shared entities.
int Size() const
Return the logical size of the array.
void GroupQuadrilateral(int group, int i, int &face, int &o) const
static ParSubMesh CreateFromBoundary(const ParMesh &parent, Array< int > &boundary_attributes)
Create a surface ParSubMesh from it's parent.
FaceInformation GetFaceInformation(int f) const
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
int GroupNVertices(int group) const
int GroupNEdges(int group) const
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
int GroupNTriangles(int group) const
Array< Element * > boundary
void GetSharedVertexCommunicator(int ordering, GroupCommunicator &svert_comm) const
Get the shared vertices GroupCommunicator.
int GetGroupSize(int g) const
Get the number of processors in a group.
const int * GetGroup(int g) const
Return a pointer to a list of neighbors for a given group. Neighbor 0 is the local processor...
void GetFaceVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of face i.
Array< Vert3 > shared_trias
void GetVertexToVertexTable(DSTable &) const
Subdomain representation of a topological parent in another ParMesh.
void ExchangeFaceNbrData()
bool Nonconforming() const
void Finalize(bool refine=false, bool fix_orientation=false) override
Finalize the construction of a general Mesh.
static void Sum(OpData< T >)
Reduce operation Sum, instantiated for int and double.
Array< Element * > shared_edges
int Append(const T &el)
Append element 'el' to array, resize if necessary.
static ParSubMesh CreateFromDomain(const ParMesh &parent, Array< int > &domain_attributes)
Create a domain ParSubMesh from it's parent.
void AddConnection(int r, int c)
STable3D * GetElementToFaceTable(int ret_ftbl=0)
void Transfer(const ParGridFunction &src, ParGridFunction &dst) const
Transfer the source ParGridFunction to the destination ParGridFunction.
ParTransferMap represents a mapping of degrees of freedom from a source ParGridFunction to a destinat...
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
int GetElementToEdgeTable(Table &, Array< int > &)
Array< Vert4 > shared_quads
int SpaceDimension() const
int GroupNQuadrilaterals(int group) const
void GetSharedTriCommunicator(int ordering, GroupCommunicator &stria_comm) const
Get the shared face triangles GroupCommunicator.
static const int GENERATED_ATTRIBUTE
int GetNeighborRank(int i) const
Return the MPI rank of neighbor 'i'.
std::tuple< Array< int >, Array< int > > AddElementsToMesh(const Mesh &parent, Mesh &mesh, const Array< int > &attributes, bool from_boundary)
Given a Mesh parent and another Mesh mesh using the list of attributes in attributes, this function adds matching elements with those attributes from parent to mesh.
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
void AddAColumnInRow(int r)
GridFunction * GetNodes()
Return a pointer to the internal node GridFunction (may be NULL).
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Array< int > BuildFaceMap(const Mesh &pm, const Mesh &sm, const Array< int > &parent_element_ids)
Given two meshes that have a parent to SubMesh relationship create a face map, using a SubMesh to par...
void InitMesh(int Dim_, int spaceDim_, int NVert, int NElem, int NBdrElem)
Begin construction of a mesh.
void SetAttributes() override
void GetSharedEdgeCommunicator(int ordering, GroupCommunicator &sedge_comm) const
Get the shared edges GroupCommunicator.
From
Indicator from which part of the parent Mesh the SubMesh is created.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void GroupEdge(int group, int i, int &edge, int &o) const
void GetSharedQuadCommunicator(int ordering, GroupCommunicator &squad_comm) const
Get the shared face quadrilaterals GroupCommunicator.
static ParTransferMap CreateTransferMap(const ParGridFunction &src, const ParGridFunction &dst)
Create a Transfer Map object.
Table group_svert
Shared objects in each group.
void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1) override
void GroupTriangle(int group, int i, int &face, int &o) const
int GroupVertex(int group, int i) const
void SetComm(MPI_Comm comm)
Set the MPI communicator to 'comm'.
int GetNEdges() const
Return the number of edges.
int GetNFaces() const
Return the number of faces in a 3D mesh.
void GetNodes(Vector &node_coord) const
Array< int > GetFaceToBdrElMap() const
Array< int > svert_lvert
Shared to local index mapping.
Class for parallel grid function.
static void Transfer(const ParGridFunction &src, ParGridFunction &dst)
Transfer the dofs of a ParGridFunction.
Class for parallel meshes.