diff --git a/framework/include/meshgenerators/PatternedMeshGenerator.h b/framework/include/meshgenerators/PatternedMeshGenerator.h index 89540f206741..0faeca041ee6 100644 --- a/framework/include/meshgenerators/PatternedMeshGenerator.h +++ b/framework/include/meshgenerators/PatternedMeshGenerator.h @@ -41,12 +41,6 @@ class PatternedMeshGenerator : public MeshGenerator /// The pattern, starting with the upper left corner const std::vector> & _pattern; - /// Holds the pointers to the input generated meshes - std::vector> _meshes; - - /// Holds a mesh for each row, these will be stitched together in the end - std::vector> _row_meshes; - /** * Merges the subdomain name maps between two meshes, throws an error * if input maps contain shared subdomain name with conflicting subdomain ids diff --git a/framework/src/meshgenerators/PatternedMeshGenerator.C b/framework/src/meshgenerators/PatternedMeshGenerator.C index fcece416fd7c..95de258e30ab 100644 --- a/framework/src/meshgenerators/PatternedMeshGenerator.C +++ b/framework/src/meshgenerators/PatternedMeshGenerator.C @@ -74,10 +74,23 @@ std::unique_ptr PatternedMeshGenerator::generate() { // Reserve spaces for all the meshes - _meshes.reserve(_input_names.size()); + std::vector> meshes(_input_names.size()); + + // Getting the boundaries provided by the user + std::vector boundary_names = {getParam("left_boundary"), + getParam("right_boundary"), + getParam("top_boundary"), + getParam("bottom_boundary")}; + + boundary_id_type left_id, right_id, top_id, bottom_id; + std::vector left_ids(_input_names.size()), right_ids(_input_names.size()), + top_ids(_input_names.size()), bottom_ids(_input_names.size()); + bool have_common_ids = true; + + std::set used_boundary_ids; // Read in all of the meshes - for (MooseIndex(_input_names) i = 0; i < _input_names.size(); ++i) + for (const auto i : index_range(_input_names)) { std::unique_ptr mesh = dynamic_pointer_cast(*_mesh_ptrs[i]); if (!mesh) @@ -88,39 +101,39 @@ PatternedMeshGenerator::generate() type(), " only works with inputs that are replicated.\n\n", "Try running without distributed mesh."); - _meshes.push_back(std::move(mesh)); + meshes[i] = dynamic_pointer_cast(mesh->clone()); + + std::vector ids = + MooseMeshUtils::getBoundaryIDs(*meshes[i], boundary_names, true); + mooseAssert(ids.size() == boundary_names.size(), + "Unexpected number of ids returned for MooseMeshUtils::getBoundaryIDs"); + + // Keep track of used IDs so we can find IDs that are unused across all meshes + used_boundary_ids.insert(ids.begin(), ids.end()); + + left_id = ids[0], right_id = ids[1], top_id = ids[2], bottom_id = ids[3]; + + // Check if all the boundaries have been initialized + if (left_id == -123) + mooseError("The left boundary has not been initialized properly."); + if (right_id == -123) + mooseError("The right boundary has not been initialized properly."); + if (top_id == -123) + mooseError("The top boundary has not been initialized properly."); + if (bottom_id == -123) + mooseError("The bottom boundary has not been initialized properly."); + + left_ids[i] = left_id, right_ids[i] = right_id, top_ids[i] = top_id, bottom_ids[i] = bottom_id; + + // Check if boundary ids are same accross all meshes + if (i > 0 && (left_id != left_ids[i - 1] || right_id != right_ids[i - 1] || + top_id != top_ids[i - 1] || bottom_id != bottom_ids[i - 1])) + have_common_ids = false; } - // Data structure that holds each row - _row_meshes.resize(_pattern.size()); - - // Getting the boundaries provided by the user - std::vector boundary_names = {getParam("left_boundary"), - getParam("right_boundary"), - getParam("top_boundary"), - getParam("bottom_boundary")}; - - std::vector ids = - MooseMeshUtils::getBoundaryIDs(*_meshes[0], boundary_names, true); - - mooseAssert(ids.size() == boundary_names.size(), - "Unexpected number of ids returned for MooseMeshUtils::getBoundaryIDs"); - - boundary_id_type left = ids[0], right = ids[1], top = ids[2], bottom = ids[3]; - - // Check if all the boundaries have been initialized - if (left == -123) - mooseError("The left boundary has not been initialized properly."); - if (right == -123) - mooseError("The right boundary has not been initialized properly."); - if (top == -123) - mooseError("The top boundary has not been initialized properly."); - if (bottom == -123) - mooseError("The bottom boundary has not been initialized properly."); - // Check if the user has provided the x, y and z widths. // If not (their value is 0 by default), compute them - auto bbox = MeshTools::create_bounding_box(*_meshes[0]); + auto bbox = MeshTools::create_bounding_box(*meshes[0]); if (_x_width == 0) _x_width = bbox.max()(0) - bbox.min()(0); if (_y_width == 0) @@ -128,6 +141,29 @@ PatternedMeshGenerator::generate() if (_z_width == 0) _z_width = bbox.max()(2) - bbox.min()(2); + // Make boundary ids same accross all meshes + if (!have_common_ids) + { + // Generate some unused_boundary ids to use as common ids accross meshes + std::vector ids; + ids.reserve(4); + for (boundary_id_type id = 0; id != Moose::INVALID_BOUNDARY_ID; ++id) + if (!used_boundary_ids.count(id)) + ids.push_back(id); + + left_id = ids[0], right_id = ids[1], top_id = ids[2], bottom_id = ids[3]; + for (const auto i : index_range(meshes)) + { + MeshTools::Modification::change_boundary_id(*meshes[i], left_ids[i], left_id); + MeshTools::Modification::change_boundary_id(*meshes[i], right_ids[i], right_id); + MeshTools::Modification::change_boundary_id(*meshes[i], top_ids[i], top_id); + MeshTools::Modification::change_boundary_id(*meshes[i], bottom_ids[i], bottom_id); + } + } + + // Data structure that holds each row + std::vector> row_meshes(_pattern.size()); + // Build each row mesh for (MooseIndex(_pattern) i = 0; i < _pattern.size(); ++i) for (MooseIndex(_pattern[i]) j = 0; j < _pattern[i].size(); ++j) @@ -137,31 +173,31 @@ PatternedMeshGenerator::generate() // If this is the first cell of the row initialize the row mesh if (j == 0) { - auto clone = _meshes[_pattern[i][j]]->clone(); - _row_meshes[i] = dynamic_pointer_cast(clone); + auto clone = meshes[_pattern[i][j]]->clone(); + row_meshes[i] = dynamic_pointer_cast(clone); - MeshTools::Modification::translate(*_row_meshes[i], deltax, -deltay, 0); + MeshTools::Modification::translate(*row_meshes[i], deltax, -deltay, 0); continue; } - ReplicatedMesh & cell_mesh = *_meshes[_pattern[i][j]]; + ReplicatedMesh & cell_mesh = *meshes[_pattern[i][j]]; // Move the mesh into the right spot. -i because we are starting at the top MeshTools::Modification::translate(cell_mesh, deltax, -deltay, 0); // Subdomain map is aggregated on each row first. This retrieves a writable reference - auto & main_subdomain_map = _row_meshes[i]->set_subdomain_name_map(); + auto & main_subdomain_map = row_meshes[i]->set_subdomain_name_map(); // Retrieve subdomain name map from the mesh to be stitched and merge into the row's // subdomain map const auto & increment_subdomain_map = cell_mesh.get_subdomain_name_map(); mergeSubdomainNameMaps(main_subdomain_map, increment_subdomain_map); - _row_meshes[i]->stitch_meshes(cell_mesh, - right, - left, - TOLERANCE, - /*clear_stitched_boundary_ids=*/true); + row_meshes[i]->stitch_meshes(cell_mesh, + right_id, + left_id, + TOLERANCE, + /*clear_stitched_boundary_ids=*/true); // Undo the translation MeshTools::Modification::translate(cell_mesh, -deltax, deltay, 0); @@ -173,17 +209,26 @@ PatternedMeshGenerator::generate() { // Get a writeable reference subdomain-name map for the main mesh to which the other rows are // stitched - auto & main_subdomain_map = _row_meshes[0]->set_subdomain_name_map(); + auto & main_subdomain_map = row_meshes[0]->set_subdomain_name_map(); // Retrieve subdomain name map from the mesh to be stitched and merge into the main // subdomain map - const auto & increment_subdomain_map = _row_meshes[i]->get_subdomain_name_map(); + const auto & increment_subdomain_map = row_meshes[i]->get_subdomain_name_map(); mergeSubdomainNameMaps(main_subdomain_map, increment_subdomain_map); - _row_meshes[0]->stitch_meshes( - *_row_meshes[i], bottom, top, TOLERANCE, /*clear_stitched_boundary_ids=*/true); + row_meshes[0]->stitch_meshes( + *row_meshes[i], bottom_id, top_id, TOLERANCE, /*clear_stitched_boundary_ids=*/true); + } + + // Change boundary ids back to those of meshes[0] to not surprise user + if (!have_common_ids) + { + MeshTools::Modification::change_boundary_id(*row_meshes[0], left_id, left_ids[0]); + MeshTools::Modification::change_boundary_id(*row_meshes[0], right_id, right_ids[0]); + MeshTools::Modification::change_boundary_id(*row_meshes[0], top_id, top_ids[0]); + MeshTools::Modification::change_boundary_id(*row_meshes[0], bottom_id, bottom_ids[0]); } - return dynamic_pointer_cast(_row_meshes[0]); + return dynamic_pointer_cast(row_meshes[0]); } void