Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 3 : 4 : // This library is free software; you can redistribute it and/or 5 : // modify it under the terms of the GNU Lesser General Public 6 : // License as published by the Free Software Foundation; either 7 : // version 2.1 of the License, or (at your option) any later version. 8 : 9 : // This library is distributed in the hope that it will be useful, 10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 : // Lesser General Public License for more details. 13 : 14 : // You should have received a copy of the GNU Lesser General Public 15 : // License along with this library; if not, write to the Free Software 16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 : 18 : // libMesh includes 19 : #include "libmesh/sides_to_elem_map.h" 20 : #include "libmesh/elem.h" 21 : #include "libmesh/libmesh_logging.h" // LOG_SCOPE 22 : #include "libmesh/mesh_base.h" 23 : #include "libmesh/utility.h" // libmesh_map_find() 24 : 25 : namespace libMesh 26 : { 27 : 28 : namespace MeshTools 29 : { 30 : 31 796 : SidesToElemMap::SidesToElemMap() = default; 32 796 : SidesToElemMap::~SidesToElemMap() = default; 33 : 34 : /** 35 : * Static build function 36 : */ 37 844 : SidesToElemMap SidesToElemMap::build(const MeshBase & mesh) 38 : { 39 48 : LOG_SCOPE("build()", "SidesToElemMap"); 40 : 41 : // Eventual return value 42 844 : SidesToElemMap ret; 43 : 44 : // Temporary storage of sorted list of vertex ids on side "s" of 45 : // "elem". We use only vertices since that is sufficient to 46 : // uniquely identify an Elem side. We only create this once and then 47 : // reuse it for each Side in the mesh to avoid repeated small memory 48 : // allocations. 49 48 : std::vector<dof_id_type> sorted_vertex_ids; 50 : 51 : // Flag which is used to check for hanging Nodes, a case not 52 : // currently handled by the SidesToElemMap object. 53 24 : unsigned int active_level_seen = libMesh::invalid_uint; 54 : 55 31184 : for (const auto & elem : mesh.element_ptr_range()) 56 : { 57 : // We currently don't handle meshes with hanging nodes. That is, 58 : // if there is a refined element with a coarser neighbor, the 59 : // SidesToElemMap won't contain any neighbor information (in 60 : // either direction) about this. For now, we throw an error 61 : // in this scenario. 62 15192 : if (elem->active()) 63 : { 64 15192 : if (active_level_seen == libMesh::invalid_uint) 65 844 : active_level_seen = elem->level(); 66 : else 67 14348 : libmesh_error_msg_if( 68 : active_level_seen != elem->level(), 69 : "SidesToElemMap does not currently support hanging nodes."); 70 : } 71 : 72 76392 : for (auto s : elem->side_index_range()) 73 : { 74 60768 : ret.get_sorted_vertex_ids(elem, s, sorted_vertex_ids); 75 : 76 : // Get reference to (or create) the vector of Elem pointers 77 : // associated with this list of vertex ids, and store "elem" in it. 78 60768 : ret._sides_to_elem_map[sorted_vertex_ids].push_back(elem); 79 : } 80 796 : } 81 : 82 868 : return ret; 83 0 : } 84 : 85 : std::pair<SidesToElemMap::ElemIter, SidesToElemMap::ElemIter> 86 8016 : SidesToElemMap::get_connected_elems(const Elem * elem, unsigned int side) const 87 : { 88 624 : std::vector<dof_id_type> sorted_vertex_ids; 89 8016 : this->get_sorted_vertex_ids(elem, side, sorted_vertex_ids); 90 : 91 8016 : const auto & elem_vec = libmesh_map_find(_sides_to_elem_map, sorted_vertex_ids); 92 9264 : return std::make_pair(elem_vec.begin(), elem_vec.end()); 93 : } 94 : 95 : void 96 68784 : SidesToElemMap::get_sorted_vertex_ids( 97 : const Elem * elem, 98 : unsigned int side, 99 : std::vector<dof_id_type> & sorted_vertex_ids) const 100 : { 101 : // Clear any prior data 102 2352 : sorted_vertex_ids.clear(); 103 : 104 : // Get all vertices for this side. Note: we can stop once we reach 105 : // the first non-vertex node, since all vertices are numbered first. 106 208704 : for (const auto & n : elem->nodes_on_side(side)) 107 : { 108 137568 : if (elem->is_vertex(n)) 109 142272 : sorted_vertex_ids.push_back(elem->node_id(n)); 110 : else 111 0 : break; 112 : } 113 : 114 : // Sort the vertex ids. The hash functions depend on the ordering 115 : // of the ids, so we want to be sure they are the same for every 116 : // Elem that touches this Side. 117 68784 : std::sort(sorted_vertex_ids.begin(), sorted_vertex_ids.end()); 118 68784 : } 119 : 120 : } // namespace MeshTools 121 : 122 : } // namespace libMesh 123 :