14 #include "libmesh/replicated_mesh.h" 15 #include "libmesh/distributed_mesh.h" 16 #include "libmesh/boundary_info.h" 17 #include "libmesh/mesh_modification.h" 18 #include "libmesh/mesh_tools.h" 28 params.
addRequiredParam<std::vector<MeshGeneratorName>>(
"inputs",
"The input MeshGenerators.");
30 "x_width", 0,
"x_width>=0",
"The tile width in the x direction");
32 "y_width", 0,
"y_width>=0",
"The tile width in the y direction");
34 "z_width", 0,
"z_width>=0",
"The tile width in the z direction");
39 params.
addParam<BoundaryName>(
"left_boundary",
"left",
"name of the left (x) boundary");
40 params.
addParam<BoundaryName>(
"right_boundary",
"right",
"name of the right (x) boundary");
43 params.
addParam<BoundaryName>(
"top_boundary",
"top",
"name of the top (y) boundary");
44 params.
addParam<BoundaryName>(
"bottom_boundary",
"bottom",
"name of the bottom (y) boundary");
47 "pattern",
"A double-indexed array starting with the upper-left corner");
49 params.
addClassDescription(
"Creates a 2D mesh from a specified set of unique 'tiles' meshes and " 50 "a two-dimensional pattern.");
57 _input_names(getParam<
std::vector<MeshGeneratorName>>(
"inputs")),
58 _mesh_ptrs(getMeshes(
"inputs")),
59 _pattern(getParam<
std::vector<
std::vector<unsigned
int>>>(
"pattern")),
60 _x_width(getParam<
Real>(
"x_width")),
61 _y_width(getParam<
Real>(
"y_width")),
62 _z_width(getParam<
Real>(
"z_width"))
69 " is larger than the the maximum possible index, which is determined by the " 70 "number of MeshGenerators provided in inputs");
73 std::unique_ptr<MeshBase>
79 std::unique_ptr<MeshBase>
83 std::vector<std::unique_ptr<ReplicatedMesh>> local_meshes;
84 auto & meshes = input_meshes ? *input_meshes : local_meshes;
89 const std::vector<BoundaryName> boundary_names = {getParam<BoundaryName>(
"left_boundary"),
90 getParam<BoundaryName>(
"right_boundary"),
91 getParam<BoundaryName>(
"top_boundary"),
92 getParam<BoundaryName>(
"bottom_boundary")};
93 const std::vector<std::string> boundary_param_names = {
94 "left_boundary",
"right_boundary",
"top_boundary",
"bottom_boundary"};
97 std::vector<std::vector<boundary_id_type>> input_bids(
99 bool have_common_ids =
true;
102 std::vector<std::vector<boundary_id_type>> input_bids_unique(
_input_names.size());
105 size_t set_length = 0;
109 std::map<std::string, size_t> boundary_name_to_index_map;
112 std::set<boundary_id_type> all_boundary_ids;
123 "' is not a replicated mesh.\n\n",
125 " only works with inputs that are replicated.\n\n",
126 "Try running without distributed mesh.");
131 mooseAssert(ids.size() == boundary_names.size(),
132 "Unexpected number of ids returned for MooseMeshUtils::getBoundaryIDs");
135 std::map<boundary_id_type, size_t> seen_bid_to_index_map;
144 boundary_param_names[side],
145 "' parameter with value '",
146 boundary_names[side],
147 "' does not exist in input mesh '",
151 input_bids[i][side] = ids[side];
158 if (
std::count(input_bids_unique[i].begin(), input_bids_unique[i].end(), ids[side]) == 0)
160 input_bids_unique[i].push_back(ids[side]);
161 seen_bid_to_index_map[ids[side]] = index;
162 boundary_name_to_index_map[boundary_param_names[side]] = index++;
165 boundary_name_to_index_map[boundary_param_names[side]] = seen_bid_to_index_map[ids[side]];
170 if (ids[side] != input_bids[i - 1][side])
171 have_common_ids =
false;
173 if (
std::count(input_bids_unique[i].begin(), input_bids_unique[i].end(), ids[side]) == 0)
174 input_bids_unique[i].push_back(ids[side]);
179 if (i > 0 && set_length != input_bids_unique.size())
181 "Input meshes have incompatible boundary ids. This can occur when input meshes have " 182 "the same boundary id for multiple boundaries, but in a way that is different " 183 "between the meshes. Try assigning each left/right/top/bottom to its own boundary id.");
185 set_length = input_bids_unique.size();
188 const auto all_ids = meshes[i]->get_boundary_info().get_boundary_ids();
191 all_boundary_ids.insert(all_ids.begin(), all_ids.end());
196 auto bbox = MeshTools::create_bounding_box(*meshes[0]);
198 _x_width = bbox.max()(0) - bbox.min()(0);
200 _y_width = bbox.max()(1) - bbox.min()(1);
202 _z_width = bbox.max()(2) - bbox.min()(2);
205 std::vector<boundary_id_type> stitch_bids;
208 stitch_bids = input_bids_unique[0];
214 if (!all_boundary_ids.count(
id))
216 stitch_bids.push_back(
id);
219 if (stitch_bids.size() == input_bids_unique[0].size())
226 MeshTools::Modification::change_boundary_id(
227 *meshes[i], input_bids_unique[i][side], stitch_bids[side]);
231 std::vector<std::unique_ptr<ReplicatedMesh>> row_meshes(
_pattern.size());
234 const boundary_id_type &left_bid(stitch_bids[boundary_name_to_index_map[
"left_boundary"]]),
235 right_bid(stitch_bids[boundary_name_to_index_map[
"right_boundary"]]),
236 top_bid(stitch_bids[boundary_name_to_index_map[
"top_boundary"]]),
237 bottom_bid(stitch_bids[boundary_name_to_index_map[
"bottom_boundary"]]);
248 auto clone = meshes[
_pattern[i][j]]->clone();
251 MeshTools::Modification::translate(*row_meshes[i], deltax, -deltay, 0);
256 ReplicatedMesh & cell_mesh = *meshes[
_pattern[i][j]];
259 MeshTools::Modification::translate(cell_mesh, deltax, -deltay, 0);
262 auto & main_subdomain_map = row_meshes[i]->set_subdomain_name_map();
265 const auto & increment_subdomain_map = cell_mesh.get_subdomain_name_map();
268 row_meshes[i]->stitch_meshes(cell_mesh,
276 MeshTools::Modification::translate(cell_mesh, -deltax, deltay, 0);
285 auto & main_subdomain_map = row_meshes[0]->set_subdomain_name_map();
288 const auto & increment_subdomain_map = row_meshes[i]->get_subdomain_name_map();
291 row_meshes[0]->stitch_meshes(*row_meshes[i],
300 if (!have_common_ids)
302 MeshTools::Modification::change_boundary_id(
303 *row_meshes[0], stitch_bids[side], input_bids_unique[0][side]);
305 row_meshes[0]->unset_is_prepared();
311 std::map<subdomain_id_type, std::string> & main_subdomain_map,
312 const std::map<subdomain_id_type, std::string> & increment_subdomain_map)
315 main_subdomain_map.insert(increment_subdomain_map.begin(), increment_subdomain_map.end());
317 std::set<SubdomainName> main_subdomain_map_name_list;
318 for (
auto const & id_name_pair : main_subdomain_map)
320 const auto name_to_insert = id_name_pair.second;
321 if (main_subdomain_map_name_list.find(name_to_insert) != main_subdomain_map_name_list.end())
323 "Two of the input meshes contain a subdomain with the name '" + name_to_insert +
324 "' which corresponds to two conflicting subdomain ids.");
325 main_subdomain_map_name_list.emplace(name_to_insert);
Reads one or more 2D mesh files and stitches them together based on a provided two-dimensional patter...
void mergeSubdomainNameMaps(std::map< subdomain_id_type, std::string > &main_subdomain_map, const std::map< subdomain_id_type, std::string > &increment_subdomain_map)
Merges the subdomain name maps between two meshes, throws an error if input maps contain shared subdo...
PatternedMeshGenerator(const InputParameters ¶meters)
void paramError(const std::string ¶m, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
const std::vector< std::vector< unsigned int > > & _pattern
The pattern, starting with the upper left corner.
const BoundaryID INVALID_BOUNDARY_ID
registerMooseObject("MooseApp", PatternedMeshGenerator)
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
static InputParameters validParams()
const std::vector< std::unique_ptr< MeshBase > * > _mesh_ptrs
Holds pointers to the meshes before they are generated.
const std::string & type() const
Get the type of this class.
std::vector< BoundaryID > getBoundaryIDs(const libMesh::MeshBase &mesh, const std::vector< BoundaryName > &boundary_name, bool generate_unknown, const std::set< BoundaryID > &mesh_boundary_ids)
Gets the boundary IDs with their names.
static InputParameters validParams()
std::string stringify(const T &t)
conversion to string
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
MeshGenerators are objects that can modify or add to an existing mesh.
void ErrorVector unsigned int
auto index_range(const T &sizable)
const std::vector< MeshGeneratorName > & _input_names
The mesh generators to read.