10 #ifdef MOOSE_MFEM_ENABLED 23 "Class to construct an MFEMSubMesh formed from the set of elements that have least one " 24 "vertex on the specified cut plane, that lie on one side of the plane, " 25 "and that are restricted to the set of user-specified subdomains.");
27 "The boundary associated with the mesh cut.");
29 "transition_subdomain_boundary",
30 "Name to assign boundary of transition subdomain not shared with cut surface.");
32 "transition_subdomain",
33 "The name of the subdomain to be created on the mesh comprised of the set of elements " 34 "adjacent to the cut surface on one side.");
37 "The name of the subdomain attribute to be created comprised of the set of all elements " 38 "of the closed geometry, including the new transition region.");
45 _cut_boundary(getParam<BoundaryName>(
"cut_boundary")),
46 _cut_submesh(
std::make_shared<mfem::ParSubMesh>(mfem::ParSubMesh::CreateFromBoundary(
47 getMFEMProblem().
mesh().getMFEMParMesh(),
48 getMesh().bdr_attribute_sets.GetAttributeSet(_cut_boundary)))),
49 _transition_subdomain_boundary(getParam<BoundaryName>(
"transition_subdomain_boundary")),
50 _transition_subdomain(getParam<SubdomainName>(
"transition_subdomain")),
51 _closed_subdomain(getParam<SubdomainName>(
"closed_subdomain")),
60 _submesh = std::make_shared<mfem::ParSubMesh>(mfem::ParSubMesh::CreateFromDomain(
62 _submesh->attribute_sets.attr_sets =
getMesh().attribute_sets.attr_sets;
63 _submesh->bdr_attribute_sets.attr_sets =
getMesh().bdr_attribute_sets.attr_sets;
69 int mpi_comm_rank = 0;
70 int mpi_comm_size = 1;
76 const mfem::Array<int> & parent_cut_element_id_map =
_cut_submesh->GetParentElementIDMap();
77 int rank_with_submesh = -1;
78 if (parent_cut_element_id_map.Size() > 0)
80 int reference_face = parent_cut_element_id_map[0];
82 rank_with_submesh = mpi_comm_rank;
84 MPI_Allreduce(MPI_IN_PLACE,
97 mfem::Array<int> transition_els;
98 std::vector<HYPRE_BigInt> global_cut_vert_ids;
99 mfem::Array<HYPRE_BigInt> gi;
100 parent_mesh.GetGlobalVertexIndices(gi);
101 std::unique_ptr<mfem::Table> vert_to_elem(parent_mesh.GetVertexToElementTable());
102 const mfem::Array<int> & cut_to_parent_vertex_id_map =
_cut_submesh->GetParentVertexIDMap();
105 int cut_vert = cut_to_parent_vertex_id_map[i];
106 global_cut_vert_ids.push_back(gi[cut_vert]);
107 int ne = vert_to_elem->RowSize(cut_vert);
108 const int * els_adj_to_cut = vert_to_elem->GetRow(cut_vert);
109 for (
int i = 0; i < ne; i++)
111 const int el_adj_to_cut = els_adj_to_cut[i];
113 sideOfCut(el_adj_to_cut, cut_vert, parent_mesh) == 1)
114 transition_els.Append(el_adj_to_cut);
119 int n_cut_vertices = global_cut_vert_ids.size();
120 std::vector<int> cut_vert_sizes(mpi_comm_size, 0);
121 MPI_Allgather(&n_cut_vertices,
129 std::vector<int> n_vert_offset(mpi_comm_size, 0);
130 for (
int i = 1; i < mpi_comm_size; i++)
131 n_vert_offset[i] = n_vert_offset[i - 1] + cut_vert_sizes[i - 1];
132 int global_n_cut_vertices = 0;
133 for (
int i = 0; i < mpi_comm_size; i++)
134 global_n_cut_vertices += cut_vert_sizes[i];
137 std::vector<HYPRE_BigInt> all_cut_verts(global_n_cut_vertices, 0);
138 MPI_Allgatherv(&global_cut_vert_ids[0],
148 for (
int g = 1, sv = 0; g < parent_mesh.GetNGroups(); g++)
150 for (
int gv = 0; gv < parent_mesh.GroupNVertices(g); gv++, sv++)
153 int cut_vert = parent_mesh.GroupVertex(g, gv);
154 for (std::size_t i = 0; i < all_cut_verts.size(); i += 1)
156 if (gi[cut_vert] == all_cut_verts[i])
158 int ne = vert_to_elem->RowSize(cut_vert);
159 const int * els_adj_to_cut =
160 vert_to_elem->GetRow(cut_vert);
161 for (
int i = 0; i < ne; i++)
163 const int el_adj_to_cut = els_adj_to_cut[i];
165 sideOfCut(el_adj_to_cut, cut_vert, parent_mesh) == 1)
166 transition_els.Append(el_adj_to_cut);
173 transition_els.Sort();
174 transition_els.Unique();
182 MFEM_ASSERT(
mesh->SpatialDimension() == 3,
183 "MFEMCutTransitionSubMesh only works in 3-dimensional meshes!");
185 mfem::Array<int> face_verts;
186 std::vector<mfem::Vector> v;
187 mesh.GetFaceVertices(face, face_verts);
190 for (
auto vtx : face_verts)
192 mfem::Vector vtx_coords(3);
193 for (
int j = 0; j < 3; ++j)
194 vtx_coords[j] =
mesh.GetVertex(vtx)[j];
195 v.push_back(vtx_coords);
201 v[0].cross3D(v[1], normal);
202 normal /= normal.Norml2();
208 const int & el_vertex_on_cut,
209 mfem::ParMesh & parent_mesh)
211 const int sdim = parent_mesh.SpaceDimension();
212 mfem::Vector el_center(3);
213 parent_mesh.GetElementCenter(el, el_center);
214 mfem::Vector vertex_coords(parent_mesh.GetVertex(el_vertex_on_cut), sdim);
215 mfem::Vector relative_center(sdim);
216 for (
int j = 0; j < sdim; j++)
217 relative_center[j] = el_center[j] - vertex_coords[j];
227 mfem::Array<int> & transition_els)
230 const int old_max_attr = parent_mesh.attributes.Max();
231 mfem::Array<int> new_attrs(old_max_attr);
232 for (
int i = 0; i < new_attrs.Size(); ++i)
233 new_attrs[i] = i + 1;
234 for (
int i = 0; i < transition_els.Size(); ++i)
236 const auto & transition_el = transition_els[i];
237 const int old_attr = parent_mesh.GetAttribute(transition_el);
238 new_attrs[old_attr - 1] = old_max_attr + old_attr % old_max_attr + 1;
243 mfem::Array<int> global_new_attrs(old_max_attr);
244 global_new_attrs = -1;
245 MPI_Allreduce(new_attrs,
253 for (
int i = 0; i < transition_els.Size(); ++i)
255 const auto & transition_el = transition_els[i];
256 const int old_attr = parent_mesh.GetAttribute(transition_el);
257 if (old_attr < old_max_attr + 1)
258 parent_mesh.SetAttribute(transition_el, global_new_attrs[old_attr - 1]);
261 mfem::AttributeSets & attr_sets = parent_mesh.attribute_sets;
262 mfem::AttributeSets & bdr_attr_sets = parent_mesh.bdr_attribute_sets;
269 const std::set<std::string> attr_set_names = attr_sets.GetAttributeSetNames();
270 for (
int old_attr = 1; old_attr < global_new_attrs.Size() + 1; ++old_attr)
272 int new_attr = global_new_attrs[old_attr - 1];
274 if (new_attr > old_max_attr)
277 for (
auto const & attr_set_name : attr_set_names)
279 const mfem::Array<int> & attr_set = attr_sets.GetAttributeSet(attr_set_name);
281 if (attr_set.Find(old_attr) != -1)
282 attr_sets.AddToAttributeSet(attr_set_name, new_attr);
291 parent_mesh.bdr_attributes.Max() + 1);
293 parent_mesh.SetAttributes();
298 const mfem::Array<int> & subdomains,
299 const mfem::ParMesh & mesh)
305 for (
const auto & subdomain : subdomains)
306 if (
mesh.GetAttribute(element) == subdomain)
Modifies the MFEM Mesh to label a subdomain consisting of elements adjacent to an interior surface on...
const SubdomainName & _closed_subdomain
virtual MFEMMesh & mesh() override
Overwritten mesh() method from base MooseMesh to retrieve the correct mesh type, in this case MFEMMes...
virtual void buildSubMesh() override
Constructs the submesh.
const BoundaryName & _transition_subdomain_boundary
const mfem::Array< int > & getSubdomainAttributes()
void labelMesh(mfem::ParMesh &parent_mesh)
Add attributes to the parent mesh representing the cut transition region.
registerMooseObject("MooseApp", MFEMCutTransitionSubMesh)
int sideOfCut(const int &el, const int &el_vertex_on_cut, mfem::ParMesh &mesh)
Checks whether an element lies on the positive or negative side of the cut plane. ...
static InputParameters validParams()
MFEMCutTransitionSubMesh(const InputParameters ¶meters)
const SubdomainName & _transition_subdomain
Base class for construction of a mfem::ParSubMesh object.
bool isInDomain(const int &el, const mfem::Array< int > &subdomains, const mfem::ParMesh &mesh)
Checks whether a given element is within a certain domain or vector of domains.
std::shared_ptr< mfem::ParSubMesh > _cut_submesh
void setAttributes(mfem::ParMesh &parent_mesh, mfem::Array< int > &transition_els)
Set new attributes for the provided transition region elements.
mfem::ParMesh & getMFEMParMesh()
Accessors for the _mfem_par_mesh object.
MFEMProblem & getMFEMProblem()
Returns a reference to the MFEMProblem instance.
static InputParameters validParams()
const mfem::ParMesh & getMesh() const
mfem::Vector findFaceNormal(const mfem::ParMesh &mesh, const int &face)
Finds the normal vector of a face in the mesh from its vertices.
std::shared_ptr< mfem::ParSubMesh > _submesh
Stores the constructed submesh.
static InputParameters validParams()
Base class for construction of an object that is restricted to a subset of subdomains of the problem ...