From 8ed1e4adb32bc8ca2eb3b20df55c4bc9deab3029 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Thu, 2 May 2024 16:01:06 -0500 Subject: [PATCH 1/3] Do not erase sides out of map after neighbors are found We used to do this for efficiency when we were using a std::multimap with O(N lg N) lookup complexity, but now that we are using a std::unordered_multimap, not constantly shrinking the map lets us handle the 1D case where more than two Edge elements meet at a single Node. --- src/mesh/unstructured_mesh.C | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mesh/unstructured_mesh.C b/src/mesh/unstructured_mesh.C index d98c7f99d4b..45d538d3cb2 100644 --- a/src/mesh/unstructured_mesh.C +++ b/src/mesh/unstructured_mesh.C @@ -963,7 +963,6 @@ void UnstructuredMesh::find_neighbors (const bool reset_remote_elements, { neighbor->set_neighbor(ns,element); } - side_to_elem_map.erase (bounds.first); // get out of this nested crap goto next_side; From a1267e80b121c7e14920f93aad6c7e865a53ce20 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Thu, 2 May 2024 16:06:04 -0500 Subject: [PATCH 2/3] Fix old comment --- src/mesh/unstructured_mesh.C | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mesh/unstructured_mesh.C b/src/mesh/unstructured_mesh.C index 45d538d3cb2..f92ffa3eea9 100644 --- a/src/mesh/unstructured_mesh.C +++ b/src/mesh/unstructured_mesh.C @@ -882,7 +882,9 @@ void UnstructuredMesh::find_neighbors (const bool reset_remote_elements, // with identical side keys and then check to see if they // are neighbors { - // data structures -- Use the hash_multimap if available + // map from side_key -> (Elem, side_index) + // We use a multimap since side keys are not guaranteed to be + // unique, then we verify sides actually match using Elem::operator==() typedef dof_id_type key_type; typedef std::pair val_type; typedef std::unordered_multimap map_type; From 6a537459f23ace112a176ee92b6dd53c8068b6f2 Mon Sep 17 00:00:00 2001 From: John Peterson Date: Thu, 2 May 2024 17:24:21 -0500 Subject: [PATCH 3/3] Relax checks in Elem::libmesh_assert_valid_neighbors() for 1D elements --- src/geom/elem.C | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/geom/elem.C b/src/geom/elem.C index 750ab00fdd5..9d86317954b 100644 --- a/src/geom/elem.C +++ b/src/geom/elem.C @@ -1219,26 +1219,37 @@ void Elem::libmesh_assert_valid_neighbors() const else { unsigned int rev = neigh->which_neighbor_am_i(elem); - libmesh_assert_less (rev, neigh->n_neighbors()); - if (this->subactive() && !neigh->subactive()) + // We relax the valid neighbor requirements for 1D elements + // since multiple 1D elements may be connected to the same + // node, and in this case, they do not satisfy the + // "A is a neighbor of B" -> "B is a neighbor of A" + // assumption. + libmesh_assert (rev < neigh->n_neighbors() || + this->dim() == 1); + + if (rev < neigh->n_neighbors()) { - while (neigh->neighbor_ptr(rev) != elem) + if (this->subactive() && !neigh->subactive()) { - libmesh_assert(elem->parent()); - elem = elem->parent(); + while (neigh->neighbor_ptr(rev) != elem) + { + libmesh_assert(elem->parent()); + elem = elem->parent(); + } } - } - else - { - const Elem * nn = neigh->neighbor_ptr(rev); - libmesh_assert(nn); + else + { + const Elem * nn = neigh->neighbor_ptr(rev); + libmesh_assert(nn); - for (; elem != nn; elem = elem->parent()) - libmesh_assert(elem); + for (; elem != nn; elem = elem->parent()) + libmesh_assert(elem); + } } } } + // If we don't have a neighbor and we're not subactive, our // ancestors shouldn't have any neighbors in this same // direction.