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]],
88 parent_vertex_ids_[lv[1]]);
89 parent_edge_ids_.
Append(parent_edge_id);
93 parent_to_submesh_edge_ids_ = -1;
94 for (
int i = 0; i < parent_edge_ids_.
Size(); i++)
96 parent_to_submesh_edge_ids_[parent_edge_ids_[i]] = i;
102 parent_element_ids_);
105 parent_to_submesh_face_ids_ = -1;
106 for (
int i = 0; i < parent_face_ids_.
Size(); i++)
108 parent_to_submesh_face_ids_[parent_face_ids_[i]] = i;
118 Array<int> sub_par_vert(sub_vert.Size());
119 for (
int j = 0; j < sub_vert.Size(); j++)
121 sub_par_vert[j] = parent_vertex_ids_[sub_vert[j]];
127 if (par_vert.Size() == 3)
146 Array<int> sub_par_vert(sub_vert.Size());
147 for (
int j = 0; j < sub_vert.Size(); j++)
149 sub_par_vert[j] = parent_vertex_ids_[sub_vert[j]];
154 if (from == SubMesh::From::Boundary)
166 if (par_vert.Size() == 3)
179 ListOfIntegerSets groups;
182 group.Recreate(1, &
MyRank);
183 groups.Insert(group);
190 FindSharedVerticesRanks(rhvtx);
191 AppendSharedVerticesGroups(groups, rhvtx);
194 FindSharedEdgesRanks(rhe);
195 AppendSharedEdgesGroups(groups, rhe);
200 FindSharedFacesRanks(rht, rhq);
201 AppendSharedFacesGroups(groups, rht, rhq);
207 int ngroups = groups.Size()-1;
209 int nsverts, nsedges, nstrias, nsquads;
210 BuildVertexGroup(ngroups, rhvtx, nsverts);
211 BuildEdgeGroup(ngroups, rhe, nsedges);
214 BuildFaceGroup(ngroups, rht, nstrias, rhq, nsquads);
227 BuildSharedVerticesMapping(nsverts, rhvtx);
228 BuildSharedEdgesMapping(nsedges, rhe);
231 BuildSharedFacesMapping(nstrias, rht, nsquads, rhq);
238 int num_of_faces_or_edges =
252 for (
int i = 0; i < num_of_faces_or_edges; i++)
264 for (
int i = 0, j = 0; i < num_of_faces_or_edges; i++)
269 if (from == SubMesh::From::Domain &&
Dim >= 2)
271 int pbeid =
Dim == 3 ? parent_face_to_be[parent_face_ids_[i]] :
272 parent_face_to_be[parent_edge_ids_[i]];
279 boundary[j]->SetAttribute(max_bdr_attr + 1);
299 const GridFunction *parent_nodes = parent_.
GetNodes();
302 const FiniteElementSpace *parent_fes = parent_nodes->FESpace();
305 parent_fes->FEColl()->GetOrder(),
306 parent_fes->IsDGSpace(),
308 parent_fes->GetOrdering());
310 const ParGridFunction* pn =
dynamic_cast<const ParGridFunction*
> 313 "Internal error. Object is supposed to be ParGridFunction.");
315 ParGridFunction* n =
dynamic_cast<ParGridFunction*
> 318 "Internal error. Object is supposed to be ParGridFunction.");
333 void ParSubMesh::FindSharedVerticesRanks(Array<int> &rhvtx)
336 GroupCommunicator svert_comm(parent_.
gtopo);
339 int nsvtx = svert_comm.GroupLDofTable().Size_of_connections();
341 rhvtx.SetSize(nsvtx);
346 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
349 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
350 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
353 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
354 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
356 const int my_group_id = my_group_id_ptr-group_lproc;
361 int submesh_vertex_id = parent_to_submesh_vertex_ids_[plvtx];
362 if (submesh_vertex_id != -1)
364 rhvtx[sv] |= 1 << my_group_id;
371 svert_comm.Bcast<
int>(rhvtx, 0);
374 void ParSubMesh::FindSharedEdgesRanks(Array<int> &rhe)
377 GroupCommunicator sedge_comm(parent_.
gtopo);
380 int nsedges = sedge_comm.GroupLDofTable().Size_of_connections();
383 rhe.SetSize(nsedges);
388 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
391 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
392 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
395 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
396 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
399 const int my_group_id = my_group_id_ptr-group_lproc;
401 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
405 int submesh_edge_id = parent_to_submesh_edge_ids_[ple];
406 if (submesh_edge_id != -1)
408 rhe[se] |= 1 << my_group_id;
415 sedge_comm.Bcast<
int>(rhe, 0);
418 void ParSubMesh::FindSharedFacesRanks(Array<int>& rht, Array<int> &rhq)
420 GroupCommunicator squad_comm(parent_.
gtopo);
423 int nsquad = squad_comm.GroupLDofTable().Size_of_connections();
436 int submesh_face_id = parent_to_submesh_face_ids_[plq];
437 if (submesh_face_id != -1)
446 squad_comm.Bcast<
int>(rhq, 0);
448 GroupCommunicator stria_comm(parent_.
gtopo);
451 int nstria = stria_comm.GroupLDofTable().Size_of_connections();
456 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
464 int submesh_face_id = parent_to_submesh_face_ids_[plt];
465 if (submesh_face_id != -1)
474 stria_comm.Bcast<
int>(rht, 0);
478 void ParSubMesh::AppendSharedVerticesGroups(ListOfIntegerSets &groups,
483 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
486 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
487 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
490 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
491 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
493 const int my_group_id = my_group_id_ptr-group_lproc;
499 int submesh_vtx = parent_to_submesh_vertex_ids_[plvtx];
502 if (submesh_vtx == -1)
507 else if (rhvtx[sv] & ~(1 << my_group_id))
510 MFEM_ASSERT(rhvtx[sv] & (1 << my_group_id),
"error again");
513 Array<int> &ranks = group;
515 for (
int i = 0; i < group_sz; i++)
517 if ((rhvtx[sv] >> i) & 1)
522 MFEM_ASSERT(ranks.Size() >= 2,
"internal error");
524 rhvtx[sv] = groups.Insert(group) - 1;
535 void ParSubMesh::AppendSharedEdgesGroups(ListOfIntegerSets &groups,
540 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
543 MFEM_VERIFY((
unsigned int)group_sz <= 8*
sizeof(
int),
544 "Group size too large. Groups with more than 32 ranks are not supported, yet.");
547 const int* my_group_id_ptr = std::find(group_lproc, group_lproc+group_sz, 0);
548 MFEM_ASSERT(my_group_id_ptr != group_lproc+group_sz,
"internal error");
550 const int my_group_id = my_group_id_ptr-group_lproc;
552 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
556 int submesh_edge = parent_to_submesh_edge_ids_[ple];
559 if (submesh_edge == -1)
564 else if (rhe[se] & ~(1 << my_group_id))
569 Array<int> &ranks = group;
571 for (
int i = 0; i < group_sz; i++)
573 if ((rhe[se] >> i) & 1)
578 MFEM_ASSERT(ranks.Size() >= 2,
"internal error");
580 rhe[se] = groups.Insert(group) - 1;
591 void ParSubMesh::AppendSharedFacesGroups(ListOfIntegerSets &groups,
592 Array<int>& rht, Array<int> &rhq)
594 IntegerSet quad_group;
602 MFEM_ASSERT(group_sz == 2,
"internal error");
606 int submesh_face_id = parent_to_submesh_face_ids_[plq];
609 if (submesh_face_id == -1)
614 else if (rhq[
sq] == group_sz)
620 Array<int> &ranks = quad_group;
625 rhq[
sq] = groups.Insert(quad_group) - 1;
635 IntegerSet tria_group;
637 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
643 MFEM_ASSERT(group_sz == 2,
"internal error");
647 int submesh_face_id = parent_to_submesh_face_ids_[plt];
650 if (submesh_face_id == -1)
655 else if (rht[st] == group_sz)
661 Array<int> &ranks = tria_group;
666 rht[st] = groups.Insert(tria_group) - 1;
677 void ParSubMesh::BuildVertexGroup(
int ngroups,
const Array<int>& rhvtx,
681 for (
int i = 0; i < rhvtx.Size(); i++)
691 for (
int i = 0; i < rhvtx.Size(); i++)
701 void ParSubMesh::BuildEdgeGroup(
int ngroups,
const Array<int>& rhe,
705 for (
int i = 0; i < rhe.Size(); i++)
715 for (
int i = 0; i < rhe.Size(); i++)
725 void ParSubMesh::BuildFaceGroup(
int ngroups,
const Array<int>& rht,
726 int& nstrias,
const Array<int>& rhq,
int& nsquads)
729 for (
int i = 0; i < rhq.Size(); i++)
739 for (
int i = 0; i < rhq.Size(); i++)
749 for (
int i = 0; i < rht.Size(); i++)
759 for (
int i = 0; i < rht.Size(); i++)
769 void ParSubMesh::BuildSharedVerticesMapping(
const int nsverts,
770 const Array<int>& rhvtx)
774 for (
int g = 1, sv = 0; g < parent_.
GetNGroups(); g++)
780 int submesh_vtx_id = parent_to_submesh_vertex_ids_[plvtx];
781 if ((submesh_vtx_id == -1) || (rhvtx[sv] == -1))
793 void ParSubMesh::BuildSharedEdgesMapping(
const int sedges_ct,
794 const Array<int>& rhe)
799 for (
int g = 1, se = 0; g < parent_.
GetNGroups(); g++)
801 for (
int ge = 0; ge < parent_.
GroupNEdges(g); ge++, se++)
805 int submesh_edge_id = parent_to_submesh_edge_ids_[ple];
806 if ((submesh_edge_id == -1) || rhe[se] == -1)
815 int v0 = parent_to_submesh_vertex_ids_[vert[(1-o)/2]];
816 int v1 = parent_to_submesh_vertex_ids_[vert[(1+o)/2]];
827 void ParSubMesh::BuildSharedFacesMapping(
const int nstrias,
828 const Array<int>& rht,
829 const int nsquads,
const Array<int>& rhq)
838 for (
int g = 1, st = 0; g < parent_.
GetNGroups(); g++)
844 int submesh_face_id = parent_to_submesh_face_ids_[plt];
845 if ((submesh_face_id == -1) || rht[st] == -1)
888 int submesh_face_id = parent_to_submesh_face_ids_[plq];
889 if ((submesh_face_id == -1) || rhq[
sq] == -1)
946 #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.
static int ComposeQuadOrientations(int ori_a_b, int ori_b_c)
void GetSharedTriCommunicator(int ordering, GroupCommunicator &stria_comm) const
Get the shared face triangles GroupCommunicator.
Array< Element * > boundary
int Dimension() const
Dimension of the reference space used within the elements.
void GetVertexToVertexTable(DSTable &) const
bool Nonconforming() const
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void GetBdrElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of boundary element i.
int GetNeighborRank(int i) const
Return the MPI rank of neighbor 'i'.
int GetNEdges() const
Return the number of edges.
Array< Vert3 > shared_trias
static int GetQuadOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
void GroupEdge(int group, int i, int &edge, int &o) const
Subdomain representation of a topological parent in another ParMesh.
std::function< double(const Vector &)> f(double mass_coeff)
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
void ExchangeFaceNbrData()
void GetBdrElementFace(int i, int *f, int *o) const
Return the index and the orientation of the face of bdr element i. (3D)
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.
void GetElementVertices(int i, Array< int > &v) const
Returns the indices of the vertices of element i.
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.
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
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
Determine the sets of unique attribute values in domain and boundary elements.
int SpaceDimension() const
Dimension of the physical space containing the mesh.
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
static int GetTriOrientation(const int *base, const int *test)
Returns the orientation of "test" relative to "base".
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.
static int ComposeTriOrientations(int ori_a_b, int ori_b_c)