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 "subdomain_remapping",
49 "Treat input subdomain names as primary, preserving them and remapping IDs as needed");
51 "verbose_stitching",
false,
"Whether mesh stitching should have verbose output.");
53 "Allows multiple mesh files to be stitched together to form a single mesh.");
60 _mesh_ptrs(getMeshes(
"inputs")),
61 _input_names(getParam<
std::vector<MeshGeneratorName>>(
"inputs")),
62 _clear_stitched_boundary_ids(getParam<bool>(
"clear_stitched_boundary_ids")),
63 _stitch_boundaries_pairs(
64 getParam<
std::vector<
std::vector<
std::string>>>(
"stitch_boundaries_pairs")),
66 _prevent_boundary_ids_overlap(getParam<bool>(
"prevent_boundary_ids_overlap")),
67 _merge_boundaries_with_same_name(getParam<bool>(
"merge_boundaries_with_same_name"))
71 std::unique_ptr<MeshBase>
77 mooseError(
"StitchedMeshGenerator is only implemented for unstructured meshes");
80 std::vector<std::unique_ptr<UnstructuredMesh>> meshes(
_mesh_ptrs.size() - 1);
84 meshes[i - 1] = dynamic_pointer_cast<UnstructuredMesh>(*
_mesh_ptrs[i]);
87 for (MooseIndex(meshes) i = 0; i < meshes.size(); i++)
95 first = MooseUtils::convert<boundary_id_type>(boundary_pair[0],
true);
99 first =
mesh->get_boundary_info().get_id_by_name(boundary_pair[0]);
101 if (first == BoundaryInfo::invalid_id)
103 std::stringstream error;
105 error <<
"Boundary " << boundary_pair[0] <<
" doesn't exist on mesh '" <<
_input_names[0]
106 <<
"' in generator " <<
name() <<
"\n";
107 error <<
"Boundary (sideset) names that do exist: \n";
108 error <<
" ID : Name\n";
110 auto & sideset_id_name_map =
mesh->get_boundary_info().get_sideset_name_map();
112 for (
auto & ss_name_map_pair : sideset_id_name_map)
113 error <<
" " << ss_name_map_pair.first <<
" : " << ss_name_map_pair.second <<
"\n";
115 error <<
"\nBoundary (nodeset) names that do exist: \n";
116 error <<
" ID : Name\n";
118 auto & nodeset_id_name_map =
mesh->get_boundary_info().get_nodeset_name_map();
120 for (
auto & ns_name_map_pair : nodeset_id_name_map)
121 error <<
" " << ns_name_map_pair.first <<
" : " << ns_name_map_pair.second <<
"\n";
123 paramError(
"stitch_boundaries_pairs", error.str());
129 second = MooseUtils::convert<boundary_id_type>(boundary_pair[1],
true);
133 second = meshes[i]->get_boundary_info().get_id_by_name(boundary_pair[1]);
135 if (second == BoundaryInfo::invalid_id)
137 meshes[i]->print_info();
139 std::stringstream error;
141 error <<
"Boundary " << boundary_pair[1] <<
" doesn't exist on mesh '" <<
_input_names[i]
142 <<
"' in generator " <<
name() <<
"\n";
143 error <<
"Boundary (sideset) names that do exist: \n";
144 error <<
" ID : Name\n";
146 auto & sideset_id_name_map = meshes[i]->get_boundary_info().get_sideset_name_map();
148 for (
auto & ss_name_map_pair : sideset_id_name_map)
149 error <<
" " << ss_name_map_pair.first <<
" : " << ss_name_map_pair.second <<
"\n";
151 error <<
"\nBoundary (nodeset) names that do exist: \n";
152 error <<
" ID : Name\n";
154 auto & nodeset_id_name_map =
mesh->get_boundary_info().get_nodeset_name_map();
156 for (
auto & ns_name_map_pair : nodeset_id_name_map)
157 error <<
" " << ns_name_map_pair.first <<
" : " << ns_name_map_pair.second <<
"\n";
159 paramError(
"stitch_boundaries_pairs", error.str());
163 const bool use_binary_search = (
_algorithm ==
"BINARY");
166 if (!
mesh->is_prepared())
167 mesh->prepare_for_use();
168 if (!meshes[i]->is_prepared())
169 meshes[i]->prepare_for_use();
176 const auto & base_mesh_bids =
mesh->get_boundary_info().get_global_boundary_ids();
177 const auto stitched_mesh_bids = meshes[i]->get_boundary_info().get_global_boundary_ids();
180 bool overlap_found =
false;
181 for (
const auto & bid : stitched_mesh_bids)
182 if (base_mesh_bids.count(bid))
183 overlap_found =
true;
187 const auto max_boundary_id = *base_mesh_bids.rbegin();
189 for (
const auto bid : stitched_mesh_bids)
191 const auto new_bid = max_boundary_id + (new_index++);
192 meshes[i]->get_boundary_info().renumber_id(bid, new_bid);
204 const auto & base_mesh_bids =
mesh->get_boundary_info().get_global_boundary_ids();
205 const auto & other_mesh_bids = meshes[i]->get_boundary_info().get_global_boundary_ids();
208 std::set<boundary_id_type> bd_id_intersection;
209 std::set_intersection(base_mesh_bids.begin(),
210 base_mesh_bids.end(),
211 other_mesh_bids.begin(),
212 other_mesh_bids.end(),
213 std::inserter(bd_id_intersection, bd_id_intersection.begin()));
215 for (
const auto bid : bd_id_intersection)
217 const auto & sideset_name_on_first_mesh =
mesh->get_boundary_info().get_sideset_name(bid);
218 const auto & sideset_name_on_second_mesh =
219 meshes[i]->get_boundary_info().get_sideset_name(bid);
221 if (sideset_name_on_first_mesh != sideset_name_on_second_mesh)
225 " corresponds to different boundary names on the input meshes! On the first " 226 "mesh it corresponds to `",
227 sideset_name_on_first_mesh,
228 "` while on the second mesh it corresponds to `",
229 sideset_name_on_second_mesh,
230 "`. The final mesh will replace boundary `",
231 sideset_name_on_second_mesh,
233 sideset_name_on_first_mesh,
234 "`. To avoid this situation, use the `prevent_boundary_ids_overlap` parameter!");
238 mesh->stitch_meshes(*meshes[i],
243 getParam<bool>(
"verbose_stitching"),
247 getParam<bool>(
"subdomain_remapping"));
253 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)