16 #include "libmesh/unstructured_mesh.h" 25 MooseEnum algorithm(
"BINARY EXHAUSTIVE",
"BINARY");
27 params.
addRequiredParam<std::vector<MeshGeneratorName>>(
"inputs",
"The input MeshGenerators.");
29 "clear_stitched_boundary_ids",
true,
"Whether or not to clear the stitched boundary IDs");
31 "stitch_boundaries_pairs",
32 "Pairs of boundaries to be stitched together between the 1st mesh in inputs and each " 37 "Control the use of binary search for the nodes of the stitched surfaces.");
38 params.
addParam<
bool>(
"prevent_boundary_ids_overlap",
40 "Whether to re-number boundaries in stitched meshes to prevent merging of " 41 "unrelated boundaries");
43 "merge_boundaries_with_same_name",
45 "If the input meshes have boundaries with the same name (but different IDs), merge them");
47 "verbose_stitching",
false,
"Whether mesh stitching should have verbose output.");
49 "Allows multiple mesh files to be stitched together to form a single mesh.");
56 _mesh_ptrs(getMeshes(
"inputs")),
57 _input_names(getParam<
std::vector<MeshGeneratorName>>(
"inputs")),
58 _clear_stitched_boundary_ids(getParam<bool>(
"clear_stitched_boundary_ids")),
59 _stitch_boundaries_pairs(
60 getParam<
std::vector<
std::vector<
std::string>>>(
"stitch_boundaries_pairs")),
62 _prevent_boundary_ids_overlap(getParam<bool>(
"prevent_boundary_ids_overlap")),
63 _merge_boundaries_with_same_name(getParam<bool>(
"merge_boundaries_with_same_name"))
67 std::unique_ptr<MeshBase>
73 mooseError(
"StitchedMeshGenerator is only implemented for unstructured meshes");
76 std::vector<std::unique_ptr<UnstructuredMesh>> meshes(
_mesh_ptrs.size() - 1);
80 meshes[i - 1] = dynamic_pointer_cast<UnstructuredMesh>(*
_mesh_ptrs[i]);
83 for (MooseIndex(meshes) i = 0; i < meshes.size(); i++)
91 first = MooseUtils::convert<boundary_id_type>(boundary_pair[0],
true);
95 first =
mesh->get_boundary_info().get_id_by_name(boundary_pair[0]);
97 if (first == BoundaryInfo::invalid_id)
99 std::stringstream error;
101 error <<
"Boundary " << boundary_pair[0] <<
" doesn't exist on mesh '" <<
_input_names[0]
102 <<
"' in generator " <<
name() <<
"\n";
103 error <<
"Boundary (sideset) names that do exist: \n";
104 error <<
" ID : Name\n";
106 auto & sideset_id_name_map =
mesh->get_boundary_info().get_sideset_name_map();
108 for (
auto & ss_name_map_pair : sideset_id_name_map)
109 error <<
" " << ss_name_map_pair.first <<
" : " << ss_name_map_pair.second <<
"\n";
111 error <<
"\nBoundary (nodeset) names that do exist: \n";
112 error <<
" ID : Name\n";
114 auto & nodeset_id_name_map =
mesh->get_boundary_info().get_nodeset_name_map();
116 for (
auto & ns_name_map_pair : nodeset_id_name_map)
117 error <<
" " << ns_name_map_pair.first <<
" : " << ns_name_map_pair.second <<
"\n";
119 paramError(
"stitch_boundaries_pairs", error.str());
125 second = MooseUtils::convert<boundary_id_type>(boundary_pair[1],
true);
129 second = meshes[i]->get_boundary_info().get_id_by_name(boundary_pair[1]);
131 if (second == BoundaryInfo::invalid_id)
133 meshes[i]->print_info();
135 std::stringstream error;
137 error <<
"Boundary " << boundary_pair[1] <<
" doesn't exist on mesh '" <<
_input_names[i]
138 <<
"' in generator " <<
name() <<
"\n";
139 error <<
"Boundary (sideset) names that do exist: \n";
140 error <<
" ID : Name\n";
142 auto & sideset_id_name_map = meshes[i]->get_boundary_info().get_sideset_name_map();
144 for (
auto & ss_name_map_pair : sideset_id_name_map)
145 error <<
" " << ss_name_map_pair.first <<
" : " << ss_name_map_pair.second <<
"\n";
147 error <<
"\nBoundary (nodeset) names that do exist: \n";
148 error <<
" ID : Name\n";
150 auto & nodeset_id_name_map =
mesh->get_boundary_info().get_nodeset_name_map();
152 for (
auto & ns_name_map_pair : nodeset_id_name_map)
153 error <<
" " << ns_name_map_pair.first <<
" : " << ns_name_map_pair.second <<
"\n";
155 paramError(
"stitch_boundaries_pairs", error.str());
159 const bool use_binary_search = (
_algorithm ==
"BINARY");
162 if (!
mesh->is_prepared())
163 mesh->prepare_for_use();
164 if (!meshes[i]->is_prepared())
165 meshes[i]->prepare_for_use();
172 const auto & base_mesh_bids =
mesh->get_boundary_info().get_global_boundary_ids();
173 const auto stitched_mesh_bids = meshes[i]->get_boundary_info().get_global_boundary_ids();
176 bool overlap_found =
false;
177 for (
const auto & bid : stitched_mesh_bids)
178 if (base_mesh_bids.count(bid))
179 overlap_found =
true;
183 const auto max_boundary_id = *base_mesh_bids.rbegin();
185 for (
const auto bid : stitched_mesh_bids)
187 const auto new_bid = max_boundary_id + (new_index++);
188 meshes[i]->get_boundary_info().renumber_id(bid, new_bid);
200 const auto & base_mesh_bids =
mesh->get_boundary_info().get_global_boundary_ids();
201 const auto & other_mesh_bids = meshes[i]->get_boundary_info().get_global_boundary_ids();
204 std::set<boundary_id_type> bd_id_intersection;
205 std::set_intersection(base_mesh_bids.begin(),
206 base_mesh_bids.end(),
207 other_mesh_bids.begin(),
208 other_mesh_bids.end(),
209 std::inserter(bd_id_intersection, bd_id_intersection.begin()));
211 for (
const auto bid : bd_id_intersection)
213 const auto & sideset_name_on_first_mesh =
mesh->get_boundary_info().get_sideset_name(bid);
214 const auto & sideset_name_on_second_mesh =
215 meshes[i]->get_boundary_info().get_sideset_name(bid);
217 if (sideset_name_on_first_mesh != sideset_name_on_second_mesh)
221 " corresponds to different boundary names on the input meshes! On the first " 222 "mesh it corresponds to `",
223 sideset_name_on_first_mesh,
224 "` while on the second mesh it corresponds to `",
225 sideset_name_on_second_mesh,
226 "`. The final mesh will replace boundary `",
227 sideset_name_on_second_mesh,
229 sideset_name_on_first_mesh,
230 "`. To avoid this situation, use the `prevent_boundary_ids_overlap` parameter!");
234 mesh->stitch_meshes(*meshes[i],
239 getParam<bool>(
"verbose_stitching"),
246 mesh->set_isnt_prepared();
const bool _prevent_boundary_ids_overlap
Whether to renumber all boundaries in stitched meshes to prevent accidental merging of sidesets with ...
static InputParameters validParams()
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
T * get(const std::unique_ptr< T > &u)
The MooseUtils::get() specializations are used to support making forwards-compatible code changes fro...
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.
virtual const std::string & name() const
Get the name of the class.
void mooseWarning(Args &&... args) const
Emits a warning prefixed with object name and type.
std::vector< std::vector< std::string > > _stitch_boundaries_pairs
A transformed version of _stitch_boundaries into a more logical "pairwise" structure.
std::vector< std::unique_ptr< MeshBase > * > _mesh_ptrs
boundary_id_type BoundaryID
StitchedMeshGenerator(const InputParameters ¶meters)
const bool & _clear_stitched_boundary_ids
Whether or not to clear (remove) the stitched boundary IDs.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
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 ...
static InputParameters validParams()
const bool _merge_boundaries_with_same_name
Whether to merge boundaries if they have the same name but different boundary IDs.
const std::vector< MeshGeneratorName > & _input_names
The mesh generator inputs to read.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
void mergeBoundaryIDsWithSameName(MeshBase &mesh)
Merges the boundary IDs of boundaries that have the same names but different IDs. ...
registerMooseObject("MooseApp", StitchedMeshGenerator)
MeshGenerators are objects that can modify or add to an existing mesh.
Allows multiple mesh files to be "stitched" together to form a single mesh.
MooseEnum _algorithm
Type of algorithm used to find matching nodes (binary or exhaustive)