Skip to content

Commit

Permalink
Avoid merging blocks and boundaries with the combiner generator
Browse files Browse the repository at this point in the history
  • Loading branch information
GiudGiud committed May 23, 2024
1 parent d76ac1a commit 801bb26
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 17 deletions.
5 changes: 5 additions & 0 deletions framework/include/meshgenerators/CombinerGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,9 @@ class CombinerGenerator : public MeshGenerator

/// The (offsets) positions for each mesh
std::vector<Point> _positions;

/// Boolean to control whether to prevent merging subdomains
const bool _avoid_merging_subdomains;
/// Boolean to control whether to prevent merging boundaries
const bool _avoid_merging_boundaries;
};
84 changes: 67 additions & 17 deletions framework/src/meshgenerators/CombinerGenerator.C
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,26 @@ CombinerGenerator::validParams()
params.addParam<std::vector<FileName>>(
"positions_file", "Alternative way to provide the position of each given mesh.");

params.addParam<bool>("avoid_merging_subdomains",
false,
"Whether to prevent merging subdomains by offsetting ids. The first mesh "
"in the input will conserve the same subdomains ids, the others will have "
"offsets. All subdomain names will remain valid");
params.addParam<bool>("avoid_merging_boundaries",
false,
"Whether to prevent merging sidesets by offsetting ids. The first mesh "
"in the input will conserve the same sideset ids, the others will have "
"offsets. All sideset names will remain valid");

return params;
}

CombinerGenerator::CombinerGenerator(const InputParameters & parameters)
: MeshGenerator(parameters),
_meshes(getMeshes("inputs")),
_input_names(getParam<std::vector<MeshGeneratorName>>("inputs"))
_input_names(getParam<std::vector<MeshGeneratorName>>("inputs")),
_avoid_merging_subdomains(getParam<bool>("avoid_merging_subdomains")),
_avoid_merging_boundaries(getParam<bool>("avoid_merging_boundaries"))
{
if (_input_names.empty())
paramError("input_names", "You need to specify at least one MeshGenerator as an input.");
Expand Down Expand Up @@ -225,44 +238,81 @@ CombinerGenerator::copyIntoMesh(UnstructuredMesh & destination, const Unstructur
0;
#endif

// Prevent overlaps by offsetting the subdomains in
std::unordered_map<subdomain_id_type, subdomain_id_type> id_remapping;
unsigned int block_offset = 0;
if (_avoid_merging_subdomains)
{
// Note: if performance becomes an issue, this is overkill for just getting the max node id
std::set<subdomain_id_type> source_ids;
std::set<subdomain_id_type> dest_ids;
source.subdomain_ids(source_ids, false);
destination.subdomain_ids(dest_ids, false);
unsigned int max_dest_bid = *dest_ids.rbegin();
unsigned int min_source_bid = *source_ids.begin();
_communicator.max(max_dest_bid);
_communicator.min(min_source_bid);
block_offset = 1 + max_dest_bid - min_source_bid;
for (const auto bid : source_ids)
id_remapping[bid] = block_offset + bid;
}

// Copy mesh data over from the other mesh
destination.copy_nodes_and_elements(source,
// Skipping this should cause the neighors
// Skipping this should cause the neighbors
// to simply be copied from the other mesh
// (which makes sense and is way faster)
/*skip_find_neighbors = */ true,
elem_delta,
node_delta,
unique_delta);
unique_delta,
_avoid_merging_subdomains ? &id_remapping : nullptr);

// Get an offset to prevent overlaps / wild merging between boundaries
BoundaryInfo & boundary = destination.get_boundary_info();
const BoundaryInfo & other_boundary = source.get_boundary_info();

unsigned int bid_offset = 0;
if (_avoid_merging_boundaries)
{
unsigned int max_dest_bid = *boundary.get_boundary_ids().rbegin();
unsigned int min_source_bid = *other_boundary.get_boundary_ids().begin();
_communicator.max(max_dest_bid);
_communicator.min(min_source_bid);
bid_offset = 1 + max_dest_bid - min_source_bid;
}

// Note: the code below originally came from ReplicatedMesh::stitch_mesh_helper()
// in libMesh replicated_mesh.C around line 1203

// Copy BoundaryInfo from other_mesh too. We do this via the
// list APIs rather than element-by-element for speed.
BoundaryInfo & boundary = destination.get_boundary_info();
const BoundaryInfo & other_boundary = source.get_boundary_info();
for (const auto & t : other_boundary.build_node_list())
boundary.add_node(std::get<0>(t) + node_delta, std::get<1>(t));
boundary.add_node(std::get<0>(t) + node_delta, bid_offset + std::get<1>(t));

for (const auto & t : other_boundary.build_side_list())
boundary.add_side(std::get<0>(t) + elem_delta, std::get<1>(t), std::get<2>(t));
boundary.add_side(std::get<0>(t) + elem_delta, std::get<1>(t), bid_offset + std::get<2>(t));

for (const auto & t : other_boundary.build_edge_list())
boundary.add_edge(std::get<0>(t) + elem_delta, std::get<1>(t), std::get<2>(t));
boundary.add_edge(std::get<0>(t) + elem_delta, std::get<1>(t), bid_offset + std::get<2>(t));

for (const auto & t : other_boundary.build_shellface_list())
boundary.add_shellface(std::get<0>(t) + elem_delta, std::get<1>(t), std::get<2>(t));
boundary.add_shellface(
std::get<0>(t) + elem_delta, std::get<1>(t), bid_offset + std::get<2>(t));

for (auto block_name_id_pair : source.get_subdomain_name_map())
destination.set_subdomain_name_map().insert(block_name_id_pair);
for (const auto & [block_id, block_name] : source.get_subdomain_name_map())
destination.set_subdomain_name_map().insert(
std::make_pair<SubdomainID, SubdomainName>(block_id + block_offset, block_name));

for (auto nodeset_name_id_pair : other_boundary.get_nodeset_name_map())
boundary.set_nodeset_name_map().insert(nodeset_name_id_pair);
for (const auto & [nodeset_id, nodeset_name] : other_boundary.get_nodeset_name_map())
boundary.set_nodeset_name_map().insert(
std::make_pair<BoundaryID, BoundaryName>(nodeset_id + bid_offset, nodeset_name));

for (auto sideset_name_id_pair : other_boundary.get_sideset_name_map())
boundary.set_sideset_name_map().insert(sideset_name_id_pair);
for (const auto & [sideset_id, sideset_name] : other_boundary.get_sideset_name_map())
boundary.set_sideset_name_map().insert(
std::make_pair<BoundaryID, BoundaryName>(sideset_id + bid_offset, sideset_name));

for (auto edgeset_name_id_pair : other_boundary.get_edgeset_name_map())
boundary.set_edgeset_name_map().insert(edgeset_name_id_pair);
for (const auto & [edgeset_id, edgeset_name] : other_boundary.get_edgeset_name_map())
boundary.set_edgeset_name_map().insert(
std::make_pair<BoundaryID, BoundaryName>(edgeset_id + bid_offset, edgeset_name));
}

0 comments on commit 801bb26

Please sign in to comment.