From f222dd9a720cfd47f3a9d748f0fd01690fc0c435 Mon Sep 17 00:00:00 2001 From: Daniel Yankura Date: Thu, 27 Mar 2025 16:26:34 -0600 Subject: [PATCH 1/5] Fix for overwriting nodesets - When creating sidesets from nodesets if the sideset shares an id with a nodeset they are combined - This checks first that the two are actually the same (same id and same nodes) - If they are not the same the instead of overwriting a new id is assigned to the new nodeset refs idaholab/moose#30085 --- include/mesh/boundary_info.h | 16 +++++++ src/mesh/boundary_info.C | 86 +++++++++++++++++++++++++++++++----- 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/include/mesh/boundary_info.h b/include/mesh/boundary_info.h index 26cccc74840..dab3ce29609 100644 --- a/include/mesh/boundary_info.h +++ b/include/mesh/boundary_info.h @@ -386,6 +386,17 @@ class BoundaryInfo : public ParallelObject */ void renumber_id (boundary_id_type old_id, boundary_id_type new_id); + /** + * Returns nodeset id to be used when converting a sideset to a nodeset + */ + boundary_id_type check_renumber_nodeset (boundary_id_type bc_id); + + /** + * Checks for existing nodeset that matches with this sideset + */ + + bool has_equivalent_nodeset(const Elem * side, boundary_id_type bc_id); + /** * \returns The number of user-specified boundary ids on the * semilocal part of the mesh. @@ -1044,6 +1055,11 @@ class BoundaryInfo : public ParallelObject */ std::set _node_boundary_ids; + /** + * Map from sideset id to nodeset id for when a sideset is converted to a nodeset + */ + std::map _sideset_to_nodeset_conversion; + /** * Set of user-specified boundary IDs for shellfaces *only*. * This is only relevant for shell elements. diff --git a/src/mesh/boundary_info.C b/src/mesh/boundary_info.C index b704e41f37e..7c677aa78be 100644 --- a/src/mesh/boundary_info.C +++ b/src/mesh/boundary_info.C @@ -141,6 +141,7 @@ BoundaryInfo & BoundaryInfo::operator=(const BoundaryInfo & other_boundary_info) _global_boundary_ids = other_boundary_info._global_boundary_ids; _side_boundary_ids = other_boundary_info._side_boundary_ids; _node_boundary_ids = other_boundary_info._node_boundary_ids; + _sideset_to_nodeset_conversion = other_boundary_info._sideset_to_nodeset_conversion; _edge_boundary_ids = other_boundary_info._edge_boundary_ids; _shellface_boundary_ids = other_boundary_info._shellface_boundary_ids; @@ -348,6 +349,7 @@ void BoundaryInfo::clear() _boundary_ids.clear(); _side_boundary_ids.clear(); _node_boundary_ids.clear(); + _sideset_to_nodeset_conversion.clear(); _edge_boundary_ids.clear(); _shellface_boundary_ids.clear(); _ss_id_to_name.clear(); @@ -1188,6 +1190,12 @@ void BoundaryInfo::add_side(const Elem * elem, _boundary_side_id.emplace(elem, std::make_pair(side, id)); _boundary_ids.insert(id); _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs + + // create temp side and check if sideset has a matching nodeset + ElemSideBuilder side_builder; + const Elem * new_side = &side_builder(*elem, side); + if (has_equivalent_nodeset(new_side, id)) + _sideset_to_nodeset_conversion.emplace(id, id); } @@ -1258,6 +1266,12 @@ void BoundaryInfo::add_side(const Elem * elem, _boundary_side_id.emplace(elem, std::make_pair(side, id)); _boundary_ids.insert(id); _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs + + // create temp side and check if sideset has a matching nodeset + ElemSideBuilder side_builder; + const Elem * new_side = &side_builder(*elem, side); + if (has_equivalent_nodeset(new_side, id)) + _sideset_to_nodeset_conversion.emplace(id, id); } } @@ -1902,7 +1916,51 @@ void BoundaryInfo::renumber_id (boundary_id_type old_id, this->libmesh_assert_valid_multimaps(); } +boundary_id_type BoundaryInfo::check_renumber_nodeset(boundary_id_type bc_id) +{ + if (_sideset_to_nodeset_conversion.find(bc_id) != _sideset_to_nodeset_conversion.end()) + // A new bc ID has already been created for this nodeset. Return that + return _sideset_to_nodeset_conversion[bc_id]; + else + { + // Find a suitable id and add to map + boundary_id_type new_id = _node_boundary_ids.size() + 1; + while (_node_boundary_ids.find(new_id) != _node_boundary_ids.end()) + new_id++; + _sideset_to_nodeset_conversion.emplace(bc_id, new_id); + return new_id; + } +} +bool BoundaryInfo::has_equivalent_nodeset(const Elem * side, boundary_id_type bc_id) +{ + bool equivalent_nodeset = false; + if (_sideset_to_nodeset_conversion.find(bc_id) != _sideset_to_nodeset_conversion.end()) + // The appropriate sideset->nodeset conversion has already been found and we can skip this check + return equivalent_nodeset; + const auto * n_list = side->get_nodes(); + for (unsigned int i = 0; i < side->n_nodes(); i++) + { + const auto node = n_list[i]; + //auto bc_ids = _boundary_node_id.equal_range(node); + for (const auto & itr : as_range(_boundary_node_id.equal_range(node))) + { + if (itr.second == bc_id) + { + equivalent_nodeset = true; + break; + } + else + equivalent_nodeset = false; + // no equivalent nodeset exists + //equivalent_nodeset = false; + //break; + } + if (!equivalent_nodeset) + break; + } + return equivalent_nodeset; +} unsigned int BoundaryInfo::side_with_boundary_id(const Elem * const elem, const boundary_id_type boundary_id_in) const @@ -2358,20 +2416,28 @@ BoundaryInfo::build_node_list_from_side_list() for (const auto & cur_elem : family) { side = &side_builder(*cur_elem, id_pair.first); - + // Check for equivalent nodeset here. If it has one the next portion can be skipped // Add each node node on the side with the side's boundary id + //if (has_equivalent_nodeset(side, id_pair.second)) + //_sideset_to_nodeset_conversion.emplace(id_pair.second, id_pair.second); for (auto i : side->node_index_range()) + { + const boundary_id_type bcid = id_pair.second; + auto bcid_renum = bcid; + // Check that bcid is not the same as a sideset id + if (_node_boundary_ids.find(bcid) != _node_boundary_ids.end()) + // Check that the nodeset and sideset don't cover the same area + bcid_renum = check_renumber_nodeset(bcid_renum); + this->add_node(side->node_ptr(i), bcid_renum); + _sideset_to_nodeset_conversion.emplace(bcid, bcid_renum); + if (!mesh_is_serial) { - const boundary_id_type bcid = id_pair.second; - this->add_node(side->node_ptr(i), bcid); - if (!mesh_is_serial) - { - const processor_id_type proc_id = - side->node_ptr(i)->processor_id(); - if (proc_id != my_proc_id) - nodes_to_push[proc_id].emplace(side->node_id(i), bcid); - } + const processor_id_type proc_id = + side->node_ptr(i)->processor_id(); + if (proc_id != my_proc_id) + nodes_to_push[proc_id].emplace(side->node_id(i), bcid); } + } } } From f595806977bad104b7cc54d4d0f22faba61e967b Mon Sep 17 00:00:00 2001 From: Daniel Yankura Date: Thu, 3 Apr 2025 17:42:40 -0600 Subject: [PATCH 2/5] Now throws an error instead of attempting to renumber nodesets - May need minor adjustments to work for when users manually rename sideset IDs --- src/mesh/boundary_info.C | 44 ++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/mesh/boundary_info.C b/src/mesh/boundary_info.C index 7c677aa78be..b1ee12613f0 100644 --- a/src/mesh/boundary_info.C +++ b/src/mesh/boundary_info.C @@ -1919,25 +1919,42 @@ void BoundaryInfo::renumber_id (boundary_id_type old_id, boundary_id_type BoundaryInfo::check_renumber_nodeset(boundary_id_type bc_id) { if (_sideset_to_nodeset_conversion.find(bc_id) != _sideset_to_nodeset_conversion.end()) - // A new bc ID has already been created for this nodeset. Return that + // The appropriate sideset->nodeset conversion has already been found and we can skip this check return _sideset_to_nodeset_conversion[bc_id]; - else + // Else search for a nodeset name that matches this sideset's name + std::string sideset_name = _ss_id_to_name[bc_id]; + for (const auto & ns_id : _node_boundary_ids) + { + if (_ns_id_to_name[ns_id] == sideset_name) { - // Find a suitable id and add to map - boundary_id_type new_id = _node_boundary_ids.size() + 1; - while (_node_boundary_ids.find(new_id) != _node_boundary_ids.end()) - new_id++; - _sideset_to_nodeset_conversion.emplace(bc_id, new_id); - return new_id; + // This sideset and nodeset should be treated the same + _sideset_to_nodeset_conversion.emplace(bc_id, ns_id); + return ns_id; } + } + // Find a suitable id and add to map + boundary_id_type new_id = _node_boundary_ids.size() + 1; + while (_node_boundary_ids.find(new_id) != _node_boundary_ids.end()) + new_id++; + _sideset_to_nodeset_conversion.emplace(bc_id, new_id); + return new_id; } bool BoundaryInfo::has_equivalent_nodeset(const Elem * side, boundary_id_type bc_id) { bool equivalent_nodeset = false; if (_sideset_to_nodeset_conversion.find(bc_id) != _sideset_to_nodeset_conversion.end()) + { // The appropriate sideset->nodeset conversion has already been found and we can skip this check + equivalent_nodeset = true; return equivalent_nodeset; + } + // If there is no nodeset with the same ID then we don't have to worry about overwriting + if (_node_boundary_ids.find(bc_id) == _node_boundary_ids.end()) + { + equivalent_nodeset = true; + return equivalent_nodeset; + } const auto * n_list = side->get_nodes(); for (unsigned int i = 0; i < side->n_nodes(); i++) { @@ -2424,12 +2441,13 @@ BoundaryInfo::build_node_list_from_side_list() { const boundary_id_type bcid = id_pair.second; auto bcid_renum = bcid; - // Check that bcid is not the same as a sideset id - if (_node_boundary_ids.find(bcid) != _node_boundary_ids.end()) - // Check that the nodeset and sideset don't cover the same area - bcid_renum = check_renumber_nodeset(bcid_renum); + // If grouping by name check if nodeset id needs to be renumbered + if (_node_boundary_ids.find(bcid) != _node_boundary_ids.end() && !has_equivalent_nodeset(side, bcid)) + // This sideset overlaps with a nodeset. Throw an error + libmesh_error_msg("Sideset " << bcid << " has the same ID as a preexisting nodeset. Rename one in order to build a nodeset from this sideset"); this->add_node(side->node_ptr(i), bcid_renum); - _sideset_to_nodeset_conversion.emplace(bcid, bcid_renum); + _sideset_to_nodeset_conversion.emplace(bcid, bcid); + // _sideset_to_nodeset_conversion.emplace(bcid, bcid_renum); if (!mesh_is_serial) { const processor_id_type proc_id = From 80d4e3260760840fcf9ccacdde983e5ada77b0c7 Mon Sep 17 00:00:00 2001 From: Daniel Yankura Date: Wed, 9 Apr 2025 16:53:13 -0600 Subject: [PATCH 3/5] Minor changes - Removed commented out code - Changed Map from nodeset to sideset id to a set of boundary IDs - Added function that allows MOOSE to add an id to this set --- include/mesh/boundary_info.h | 11 ++++------- src/mesh/boundary_info.C | 37 +++--------------------------------- 2 files changed, 7 insertions(+), 41 deletions(-) diff --git a/include/mesh/boundary_info.h b/include/mesh/boundary_info.h index dab3ce29609..316ba3dd08e 100644 --- a/include/mesh/boundary_info.h +++ b/include/mesh/boundary_info.h @@ -386,17 +386,14 @@ class BoundaryInfo : public ParallelObject */ void renumber_id (boundary_id_type old_id, boundary_id_type new_id); - /** - * Returns nodeset id to be used when converting a sideset to a nodeset - */ - boundary_id_type check_renumber_nodeset (boundary_id_type bc_id); - /** * Checks for existing nodeset that matches with this sideset */ bool has_equivalent_nodeset(const Elem * side, boundary_id_type bc_id); + void add_equivalent_sideset(boundary_id_type bc_id) {_sideset_to_nodeset_conversion.insert(bc_id); } + /** * \returns The number of user-specified boundary ids on the * semilocal part of the mesh. @@ -1056,9 +1053,9 @@ class BoundaryInfo : public ParallelObject std::set _node_boundary_ids; /** - * Map from sideset id to nodeset id for when a sideset is converted to a nodeset + * Set of sideset that are equivalent to their corresponding nodeset */ - std::map _sideset_to_nodeset_conversion; + std::set _sideset_to_nodeset_conversion; /** * Set of user-specified boundary IDs for shellfaces *only*. diff --git a/src/mesh/boundary_info.C b/src/mesh/boundary_info.C index b1ee12613f0..0ac9f9e58b9 100644 --- a/src/mesh/boundary_info.C +++ b/src/mesh/boundary_info.C @@ -1195,7 +1195,7 @@ void BoundaryInfo::add_side(const Elem * elem, ElemSideBuilder side_builder; const Elem * new_side = &side_builder(*elem, side); if (has_equivalent_nodeset(new_side, id)) - _sideset_to_nodeset_conversion.emplace(id, id); + _sideset_to_nodeset_conversion.insert(id); } @@ -1271,7 +1271,7 @@ void BoundaryInfo::add_side(const Elem * elem, ElemSideBuilder side_builder; const Elem * new_side = &side_builder(*elem, side); if (has_equivalent_nodeset(new_side, id)) - _sideset_to_nodeset_conversion.emplace(id, id); + _sideset_to_nodeset_conversion.insert(id); } } @@ -1916,30 +1916,6 @@ void BoundaryInfo::renumber_id (boundary_id_type old_id, this->libmesh_assert_valid_multimaps(); } -boundary_id_type BoundaryInfo::check_renumber_nodeset(boundary_id_type bc_id) -{ - if (_sideset_to_nodeset_conversion.find(bc_id) != _sideset_to_nodeset_conversion.end()) - // The appropriate sideset->nodeset conversion has already been found and we can skip this check - return _sideset_to_nodeset_conversion[bc_id]; - // Else search for a nodeset name that matches this sideset's name - std::string sideset_name = _ss_id_to_name[bc_id]; - for (const auto & ns_id : _node_boundary_ids) - { - if (_ns_id_to_name[ns_id] == sideset_name) - { - // This sideset and nodeset should be treated the same - _sideset_to_nodeset_conversion.emplace(bc_id, ns_id); - return ns_id; - } - } - // Find a suitable id and add to map - boundary_id_type new_id = _node_boundary_ids.size() + 1; - while (_node_boundary_ids.find(new_id) != _node_boundary_ids.end()) - new_id++; - _sideset_to_nodeset_conversion.emplace(bc_id, new_id); - return new_id; -} - bool BoundaryInfo::has_equivalent_nodeset(const Elem * side, boundary_id_type bc_id) { bool equivalent_nodeset = false; @@ -1959,7 +1935,6 @@ bool BoundaryInfo::has_equivalent_nodeset(const Elem * side, boundary_id_type bc for (unsigned int i = 0; i < side->n_nodes(); i++) { const auto node = n_list[i]; - //auto bc_ids = _boundary_node_id.equal_range(node); for (const auto & itr : as_range(_boundary_node_id.equal_range(node))) { if (itr.second == bc_id) @@ -1969,9 +1944,6 @@ bool BoundaryInfo::has_equivalent_nodeset(const Elem * side, boundary_id_type bc } else equivalent_nodeset = false; - // no equivalent nodeset exists - //equivalent_nodeset = false; - //break; } if (!equivalent_nodeset) break; @@ -2435,8 +2407,6 @@ BoundaryInfo::build_node_list_from_side_list() side = &side_builder(*cur_elem, id_pair.first); // Check for equivalent nodeset here. If it has one the next portion can be skipped // Add each node node on the side with the side's boundary id - //if (has_equivalent_nodeset(side, id_pair.second)) - //_sideset_to_nodeset_conversion.emplace(id_pair.second, id_pair.second); for (auto i : side->node_index_range()) { const boundary_id_type bcid = id_pair.second; @@ -2446,8 +2416,7 @@ BoundaryInfo::build_node_list_from_side_list() // This sideset overlaps with a nodeset. Throw an error libmesh_error_msg("Sideset " << bcid << " has the same ID as a preexisting nodeset. Rename one in order to build a nodeset from this sideset"); this->add_node(side->node_ptr(i), bcid_renum); - _sideset_to_nodeset_conversion.emplace(bcid, bcid); - // _sideset_to_nodeset_conversion.emplace(bcid, bcid_renum); + _sideset_to_nodeset_conversion.insert(bcid); if (!mesh_is_serial) { const processor_id_type proc_id = From 4ee955cbf2b3ebdfc9342517d2ae3e18e18d25dd Mon Sep 17 00:00:00 2001 From: Daniel Yankura Date: Thu, 10 Apr 2025 08:45:11 -0600 Subject: [PATCH 4/5] Deleted trailing whitespace --- src/mesh/boundary_info.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/boundary_info.C b/src/mesh/boundary_info.C index 0ac9f9e58b9..d350f0eb4e1 100644 --- a/src/mesh/boundary_info.C +++ b/src/mesh/boundary_info.C @@ -1946,7 +1946,7 @@ bool BoundaryInfo::has_equivalent_nodeset(const Elem * side, boundary_id_type bc equivalent_nodeset = false; } if (!equivalent_nodeset) - break; + break; } return equivalent_nodeset; } From ca63b3e53af284c74f25a7c2ae3e6b82323568e1 Mon Sep 17 00:00:00 2001 From: Daniel Yankura Date: Thu, 10 Apr 2025 09:15:17 -0600 Subject: [PATCH 5/5] removed more trailing whitespace --- src/mesh/boundary_info.C | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesh/boundary_info.C b/src/mesh/boundary_info.C index d350f0eb4e1..a1a547eb05f 100644 --- a/src/mesh/boundary_info.C +++ b/src/mesh/boundary_info.C @@ -1266,7 +1266,7 @@ void BoundaryInfo::add_side(const Elem * elem, _boundary_side_id.emplace(elem, std::make_pair(side, id)); _boundary_ids.insert(id); _side_boundary_ids.insert(id); // Also add this ID to the set of side boundary IDs - + // create temp side and check if sideset has a matching nodeset ElemSideBuilder side_builder; const Elem * new_side = &side_builder(*elem, side);