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);
182 for (
int i = 0; i < num_of_faces_or_edges; i++)
192 Array<int> parent_face_to_be;
197 for (
int i = 0, j = 0; i < num_of_faces_or_edges; i++)
205 int pbeid = parent_face_to_be[parent_face_ids_[i]];
232 const GridFunction *parent_nodes = parent_.
GetNodes();
235 const FiniteElementSpace *parent_fes = parent_nodes->FESpace();
238 parent_fes->FEColl()->GetOrder(),
239 parent_fes->IsDGSpace(),
241 parent_fes->GetOrdering());
243 const ParGridFunction* pn =
dynamic_cast<const ParGridFunction*
> 246 "Internal error. Object is supposed to be ParGridFunction.");
248 ParGridFunction* n =
dynamic_cast<ParGridFunction*
> 251 "Internal error. Object is supposed to be ParGridFunction.");
266 void ParSubMesh::FindSharedVerticesRanks(Array<int> &rhvtx)
269 GroupCommunicator svert_comm(parent_.
gtopo);
272 int nsvtx = svert_comm.GroupLDofTable().Size_of_connections();
274 rhvtx.SetSize(nsvtx);
279 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
282 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
283 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
286 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
287 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
289 const int my_group_id = my_group_id_ptr-group_lproc;
294 int submesh_vertex_id = parent_to_submesh_vertex_ids_[plvtx];
295 if (submesh_vertex_id != -1)
297 rhvtx[sv] |= 1 << my_group_id;
304 svert_comm.Bcast<
int>(rhvtx, 0);
307 void ParSubMesh::FindSharedEdgesRanks(Array<int> &rhe)
310 GroupCommunicator sedge_comm(parent_.
gtopo);
313 int nsedges = sedge_comm.GroupLDofTable().Size_of_connections();
316 rhe.SetSize(nsedges);
321 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
324 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
325 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
328 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
329 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
332 const int my_group_id = my_group_id_ptr-group_lproc;
334 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
338 int submesh_edge_id = parent_to_submesh_edge_ids_[ple];
339 if (submesh_edge_id != -1)
341 rhe[se] |= 1 << my_group_id;
348 sedge_comm.Bcast<
int>(rhe, 0);
351 void ParSubMesh::FindSharedFacesRanks(Array<int>& rht, Array<int> &rhq)
353 GroupCommunicator squad_comm(parent_.
gtopo);
356 int nsquad = squad_comm.GroupLDofTable().Size_of_connections();
369 int submesh_face_id = parent_to_submesh_face_ids_[plq];
370 if (submesh_face_id != -1)
379 squad_comm.Bcast<
int>(rhq, 0);
381 GroupCommunicator stria_comm(parent_.
gtopo);
384 int nstria = stria_comm.GroupLDofTable().Size_of_connections();
389 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
397 int submesh_face_id = parent_to_submesh_face_ids_[plt];
398 if (submesh_face_id != -1)
407 stria_comm.Bcast<
int>(rht, 0);
411 void ParSubMesh::AppendSharedVerticesGroups(ListOfIntegerSets &groups,
416 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
419 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
420 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
423 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
424 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
426 const int my_group_id = my_group_id_ptr-group_lproc;
432 int submesh_vtx = parent_to_submesh_vertex_ids_[plvtx];
435 if (submesh_vtx == -1)
440 else if (rhvtx[sv] & ~(1 << my_group_id))
443 MFEM_ASSERT(rhvtx[sv] & (1 << my_group_id),
"error again");
446 Array<int> &ranks = group;
448 for (
int i = 0; i < group_sz; i++)
450 if ((rhvtx[sv] >> i) & 1)
455 MFEM_ASSERT(ranks.Size() >= 2,
"internal error");
457 rhvtx[sv] = groups.Insert(group) - 1;
468 void ParSubMesh::AppendSharedEdgesGroups(ListOfIntegerSets &groups,
473 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
476 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
477 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
480 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
481 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
483 const int my_group_id = my_group_id_ptr-group_lproc;
485 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
489 int submesh_edge = parent_to_submesh_edge_ids_[ple];
492 if (submesh_edge == -1)
497 else if (rhe[se] & ~(1 << my_group_id))
502 Array<int> &ranks = group;
504 for (
int i = 0; i < group_sz; i++)
506 if ((rhe[se] >> i) & 1)
511 MFEM_ASSERT(ranks.Size() >= 2,
"internal error");
513 rhe[se] = groups.Insert(group) - 1;
524 void ParSubMesh::AppendSharedFacesGroups(ListOfIntegerSets &groups,
525 Array<int>& rht, Array<int> &rhq)
527 IntegerSet quad_group;
535 MFEM_ASSERT(group_sz == 2,
"internal error");
539 int submesh_face_id = parent_to_submesh_face_ids_[plq];
542 if (submesh_face_id == -1)
547 else if (rhq[
sq] == group_sz)
553 Array<int> &ranks = quad_group;
558 rhq[
sq] = groups.Insert(quad_group) - 1;
568 IntegerSet tria_group;
570 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
576 MFEM_ASSERT(group_sz == 2,
"internal error");
580 int submesh_face_id = parent_to_submesh_face_ids_[plt];
583 if (submesh_face_id == -1)
588 else if (rht[st] == group_sz)
594 Array<int> &ranks = tria_group;
599 rht[st] = groups.Insert(tria_group) - 1;
610 void ParSubMesh::BuildVertexGroup(
int ngroups,
const Array<int>& rhvtx,
614 for (
int i = 0; i < rhvtx.Size(); i++)
624 for (
int i = 0; i < rhvtx.Size(); i++)
634 void ParSubMesh::BuildEdgeGroup(
int ngroups,
const Array<int>& rhe,
638 for (
int i = 0; i < rhe.Size(); i++)
648 for (
int i = 0; i < rhe.Size(); i++)
658 void ParSubMesh::BuildFaceGroup(
int ngroups,
const Array<int>& rht,
659 int& nstrias,
const Array<int>& rhq,
int& nsquads)
662 for (
int i = 0; i < rhq.Size(); i++)
672 for (
int i = 0; i < rhq.Size(); i++)
682 for (
int i = 0; i < rht.Size(); i++)
692 for (
int i = 0; i < rht.Size(); i++)
702 void ParSubMesh::BuildSharedVerticesMapping(
const int nsverts,
703 const Array<int>& rhvtx)
707 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
713 int submesh_vtx_id = parent_to_submesh_vertex_ids_[plvtx];
714 if ((submesh_vtx_id == -1) || (rhvtx[sv] == -1))
726 void ParSubMesh::BuildSharedEdgesMapping(
const int sedges_ct,
727 const Array<int>& rhe)
732 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
734 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
738 int submesh_edge_id = parent_to_submesh_edge_ids_[ple];
739 if ((submesh_edge_id == -1) || rhe[se] == -1)
755 void ParSubMesh::BuildSharedFacesMapping(
const int nstrias,
756 const Array<int>& rht,
757 const int nsquads,
const Array<int>& rhq)
769 int submesh_face_id = parent_to_submesh_face_ids_[plq];
770 if ((submesh_face_id == -1) || rhq[
sq] == -1)
779 shared_quads.Append(Vert4(vert[0], vert[1], vert[2], vert[3]));
785 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
791 int submesh_face_id = parent_to_submesh_face_ids_[plt];
792 if ((submesh_face_id == -1) || rht[st] == -1)
822 #endif // MFEM_USE_MPI void Create(ListOfIntegerSets &groups, int mpitag)
Set up the group topology given the list of sets of shared entities.
static ParSubMesh CreateFromBoundary(const ParMesh &parent, Array< int > &boundary_attributes)
Create a surface ParSubMesh from it's parent.
Array< int > GetFaceToBdrElMap() const
void GetSharedVertexCommunicator(int ordering, GroupCommunicator &svert_comm) const
Get the shared vertices GroupCommunicator.
void GetSharedQuadCommunicator(int ordering, GroupCommunicator &squad_comm) const
Get the shared face quadrilaterals GroupCommunicator.
void MakeI(int nrows)
Next 7 methods are used together with the default constructor.
void GetSharedTriCommunicator(int ordering, GroupCommunicator &stria_comm) const
Get the shared face triangles GroupCommunicator.
Array< Element * > boundary
void GetVertexToVertexTable(DSTable &) const
bool Nonconforming() const
int GetNeighborRank(int i) const
Return the MPI rank of neighbor 'i'.
int GetNEdges() const
Return the number of edges.
Array< Vert3 > shared_trias
void GroupEdge(int group, int i, int &edge, int &o) const
Subdomain representation of a topological parent in another ParMesh.
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void ExchangeFaceNbrData()
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.
int GroupNVertices(int group) const
int GroupVertex(int group, int i) const
void AddConnection(int r, int c)
STable3D * GetElementToFaceTable(int ret_ftbl=0)
void GetEdgeVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of edge i.
void GetFaceVertices(int i, Array< int > &vert) const
Returns the indices of the vertices of face i.
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.
const int * GetGroup(int g) const
Return a pointer to a list of neighbors for a given group. Neighbor 0 is the local processor...
int GetElementToEdgeTable(Table &, Array< int > &)
void GetSharedEdgeCommunicator(int ordering, GroupCommunicator &sedge_comm) const
Get the shared edges GroupCommunicator.
Array< Vert4 > shared_quads
int GroupNTriangles(int group) const
int GetBdrAttribute(int i) const
Return the attribute of boundary element i.
void Transfer(const ParGridFunction &src, ParGridFunction &dst) const
Transfer the source ParGridFunction to the destination ParGridFunction.
static const int GENERATED_ATTRIBUTE
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
int SpaceDimension() const
From
Indicator from which part of the parent Mesh the SubMesh is created.
int GetGroupSize(int g) const
Get the number of processors in a group.
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
Set the curvature of the mesh nodes using the given polynomial degree.
int Size() const
Return the logical size of the array.
FaceInformation GetFaceInformation(int f) const
void SetComm(MPI_Comm comm)
Set the MPI communicator to 'comm'.
int GetNFaces() const
Return the number of faces in a 3D mesh.
int GroupNEdges(int group) const
Array< int > svert_lvert
Shared to local index mapping.
int GroupNQuadrilaterals(int group) const
void GetNodes(Vector &node_coord) const
Class for parallel grid function.
static void Transfer(const ParGridFunction &src, ParGridFunction &dst)
Transfer the dofs of a ParGridFunction.
void GroupQuadrilateral(int group, int i, int &face, int &o) const
void GroupTriangle(int group, int i, int &face, int &o) const
Class for parallel meshes.