11 #include "InputParameters.h"
12 #include "MooseTypes.h"
13 #include "CastUniquePointer.h"
14 #include "MooseUtils.h"
15 #include "MooseMeshUtils.h"
17 #include "libmesh/distributed_mesh.h"
18 #include "libmesh/elem.h"
19 #include "libmesh/linear_partitioner.h"
20 #include "libmesh/centroid_partitioner.h"
21 #include "libmesh/parmetis_partitioner.h"
22 #include "libmesh/hilbert_sfc_partitioner.h"
23 #include "libmesh/morton_sfc_partitioner.h"
24 #include "libmesh/enum_elem_type.h"
27 #include "libmesh/edge_edge2.h"
28 #include "libmesh/edge_edge3.h"
29 #include "libmesh/edge_edge4.h"
30 #include "libmesh/face_tri3.h"
31 #include "libmesh/face_tri6.h"
32 #include "libmesh/face_quad4.h"
33 #include "libmesh/face_quad8.h"
34 #include "libmesh/face_quad9.h"
48 params.addRequiredParam<MeshGeneratorName>(
"input",
"The mesh we want to modify");
49 params.addRequiredParam<boundary_id_type>(
"sideset",
50 "The sideset that will be divided into patches");
51 params.addRequiredRangeCheckedParam<
unsigned int>(
52 "n_patches",
"n_patches>0",
"Number of patches");
54 MooseEnum partitioning(
"default=-3 metis=-2 parmetis=-1 linear=0 centroid hilbert_sfc morton_sfc",
56 params.addParam<MooseEnum>(
59 "Specifies a mesh partitioner to use when splitting the mesh for a parallel computation.");
60 MooseEnum direction(
"x y z radial");
61 params.addParam<MooseEnum>(
"centroid_partitioner_direction",
63 "Specifies the sort direction if using the centroid partitioner. "
64 "Available options: x, y, z, radial");
66 params.addParamNamesToGroup(
"partitioner centroid_partitioner_direction",
"Partitioning");
68 params.addClassDescription(
69 "Divides the given sideset into smaller patches of roughly equal size.");
75 : MeshGenerator(parameters),
76 _input(getMesh(
"input")),
77 _n_patches(getParam<unsigned int>(
"n_patches")),
78 _sideset(getParam<boundary_id_type>(
"sideset")),
79 _partitioner_name(getParam<MooseEnum>(
"partitioner"))
83 std::unique_ptr<MeshBase>
86 std::unique_ptr<MeshBase> mesh = std::move(
_input);
88 _mesh->errorIfDistributedMesh(
"PatchSidesetGenerator");
91 BoundaryInfo & boundary_info = mesh->get_boundary_info();
94 auto side_list = boundary_info.build_active_side_list();
98 libmesh_make_unique<libMesh::ReplicatedMesh>(comm(), mesh->mesh_dimension() - 1);
99 boundary_mesh->set_mesh_dimension(mesh->mesh_dimension() - 1);
100 boundary_mesh->set_spatial_dimension(mesh->mesh_dimension());
103 std::vector<Node *> boundary_nodes;
106 std::map<dof_id_type, dof_id_type> mesh_node_id_to_boundary_node_id;
108 dof_id_type boundary_node_id = 0;
111 std::map<dof_id_type, std::tuple<dof_id_type, unsigned short int, boundary_id_type>>
112 boundary_elem_to_mesh_elem;
113 for (
auto & side : side_list)
118 const Elem * elem = mesh->elem_ptr(std::get<0>(side));
121 std::unique_ptr<const Elem> boundary_elem = elem->side_ptr(std::get<1>(side));
124 std::vector<dof_id_type> bnd_elem_node_ids(boundary_elem->n_nodes());
127 for (
unsigned int j = 0; j < boundary_elem->n_nodes(); ++j)
129 const Node * node = boundary_elem->node_ptr(j);
132 if (mesh_node_id_to_boundary_node_id.find(node->id()) ==
133 mesh_node_id_to_boundary_node_id.end())
136 mesh_node_id_to_boundary_node_id.insert(
137 std::pair<dof_id_type, dof_id_type>(node->id(), boundary_node_id));
142 boundary_nodes.push_back(boundary_mesh->add_point(pt, boundary_node_id));
145 bnd_elem_node_ids[j] = boundary_node_id;
151 bnd_elem_node_ids[j] = mesh_node_id_to_boundary_node_id.find(node->id())->second;
159 boundary_elem_to_mesh_elem.insert(
160 std::pair<dof_id_type, std::tuple<dof_id_type, unsigned short int, boundary_id_type>>(
161 new_bnd_elem->id(), side));
166 for (
unsigned int j = 0; j < boundary_elem->n_nodes(); ++j)
168 dof_id_type old_node_id = boundary_elem->node_ptr(j)->id();
169 if (mesh_node_id_to_boundary_node_id.find(old_node_id) ==
170 mesh_node_id_to_boundary_node_id.end())
171 mooseError(
"Node id", old_node_id,
" not linked to new node id.");
172 dof_id_type new_node_id = mesh_node_id_to_boundary_node_id.find(old_node_id)->second;
173 new_bnd_elem->set_node(j) = boundary_nodes[new_node_id];
179 boundary_mesh->prepare_for_use();
180 MooseMesh::setPartitioner(*boundary_mesh,
_partitioner_name,
false, _pars, *
this);
184 std::vector<BoundaryName> sideset_names =
187 std::vector<boundary_id_type> boundary_ids =
188 MooseMeshUtils::getBoundaryIDs(*mesh, sideset_names,
true);
190 mooseAssert(sideset_names.size() ==
_n_patches,
191 "sideset_names must have as many entries as user-requested number of patches.");
192 mooseAssert(boundary_ids.size() ==
_n_patches,
193 "boundary_ids must have as many entries as user-requested number of patches.");
197 for (
const auto & elem : boundary_mesh->active_element_ptr_range())
199 if (boundary_elem_to_mesh_elem.find(elem->id()) == boundary_elem_to_mesh_elem.end())
200 mooseError(
"Element in the boundary mesh with id ",
202 " not found in boundary_elem_to_mesh_elem.");
204 auto side = boundary_elem_to_mesh_elem.find(elem->id())->second;
206 mooseAssert(elem->processor_id() < boundary_ids.size(),
207 "Processor id larger than number of patches.");
208 boundary_info.add_side(
209 std::get<0>(side), std::get<1>(side), boundary_ids[elem->processor_id()]);
213 for (
unsigned int j = 0; j < boundary_ids.size(); ++j)
215 boundary_info.sideset_name(boundary_ids[j]) = sideset_names[j];
216 boundary_info.nodeset_name(boundary_ids[j]) = sideset_names[j];
222 std::vector<BoundaryName>
225 std::vector<BoundaryName> rv;
228 std::stringstream ss;
229 ss << base_name <<
"_" << j;
230 rv.push_back(ss.str());
241 return mesh.add_elem(
new libMesh::Edge2);
243 return mesh.add_elem(
new libMesh::Edge3);
245 return mesh.add_elem(
new libMesh::Edge4);
247 return mesh.add_elem(
new libMesh::Tri3);
249 return mesh.add_elem(
new libMesh::Tri6);
251 return mesh.add_elem(
new libMesh::Quad4);
253 return mesh.add_elem(
new libMesh::Quad8);
255 return mesh.add_elem(
new libMesh::Quad9);
257 mooseError(
"Unsupported element type (libMesh elem_type enum): ", type);