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 : #ifndef LIBMESH_SIDES_TO_ELEM_MAP_H 19 : #define LIBMESH_SIDES_TO_ELEM_MAP_H 20 : 21 : // libMesh includes 22 : #include "libmesh/id_types.h" // dof_id_type 23 : #include "libmesh/hashword.h" // Utility::hashword() 24 : 25 : // C++ includes 26 : #include <unordered_map> 27 : #include <vector> 28 : 29 : namespace libMesh 30 : { 31 : 32 : // Forward declarations 33 : class MeshBase; 34 : class Elem; 35 : 36 : namespace MeshTools 37 : { 38 : 39 : /** 40 : * This class implements a generalization of the 41 : * MeshTools::build_nodes_to_elem_map() function, but rather than 42 : * being a standalone function taking a std::unordered_map argument, 43 : * we define a class with APIs for both building the underlying 44 : * map data structure and querying its contents. This way, we avoid 45 : * issues with hash collisions resulting from the Elem::low_order_key() 46 : * function (which could occur with as few as 100k sides when using a 47 : * 32-bit dof_id_type) in addition to being able to control exactly 48 : * how the user will interact with the class. 49 : * 50 : * \author John W. Peterson 51 : * \date 2024 52 : */ 53 120 : class SidesToElemMap 54 : { 55 : public: 56 : /** 57 : * Default constructor/destructor 58 : */ 59 : SidesToElemMap(); 60 : ~SidesToElemMap(); 61 : 62 : /** 63 : * Static build function. Most users will simply call this 64 : * function to construct the SidesToElemMap object for their 65 : * Mesh. 66 : */ 67 : static SidesToElemMap build(const MeshBase & mesh); 68 : 69 : /** 70 : * Typedef for the iterator type returned by the 71 : * SidesToeElemMap::get_connected_elems() function. 72 : */ 73 : typedef std::vector<const Elem *>::const_iterator ElemIter; 74 : 75 : /** 76 : * Return an iterator pair defining the range of Elems connected to "side" 77 : * of "elem". The returned list of Elems will also include "elem" 78 : * itself. Throws an error if the requested (elem, side) combination 79 : * is not found in the map (this should not happen because every 80 : * side in the map should be attached to at least one Elem). 81 : */ 82 : std::pair<ElemIter, ElemIter> 83 : get_connected_elems(const Elem * elem, unsigned int side) const; 84 : 85 : private: 86 : 87 : /** 88 : * Convenient typedefs for working with std::unordered_map 89 : */ 90 : typedef std::vector<dof_id_type> Key; 91 : typedef std::vector<const Elem *> Value; 92 : 93 : struct HashFunction 94 : { 95 : public: 96 : /** 97 : * The "Hash" template argument. We just use the same 98 : * Utility::hashword() function that is used by the various 99 : * Elem::compute_key() implementations, although here we can 100 : * assume the sorting has already been done for us. This will be a 101 : * 32-bit hash when dof_id_type is 32-bits and a 64-bit hash when 102 : * dof_id_type is 64 bits. 103 : */ 104 : inline 105 2352 : std::size_t operator()(const Key & vertex_ids) const 106 : { 107 3228 : return cast_int<std::size_t>(Utility::hashword(vertex_ids)); 108 : } 109 : 110 : /** 111 : * The "KeyEqual" template argument. Calls std::vector::operator==() 112 : */ 113 : inline 114 1224 : bool operator()(const Key & lhs, const Key & rhs) const 115 : { 116 29116 : return lhs == rhs; 117 : } 118 : }; 119 : 120 : /** 121 : * Map from (sorted list of side vertex ids) -> (Elems touching that side) 122 : * A "side" is uniquely defined by the sorted list of its vertex ids, so this 123 : * is a good choice to use as a key. 124 : */ 125 : std::unordered_map<Key, Value, /*Hash*/HashFunction, /*KeyEqual*/HashFunction> _sides_to_elem_map; 126 : 127 : /** 128 : * Construct a sorted list of vertex ids for the input (elem, side) 129 : * pair. This is needed in a couple different places, so it makes 130 : * sense to factor it out. The output array is passed as a reference 131 : * to facilitate reuse over reallocation. 132 : */ 133 : void get_sorted_vertex_ids( 134 : const Elem * elem, 135 : unsigned int side, 136 : std::vector<dof_id_type> & sorted_vertex_ids) const; 137 : }; 138 : 139 : } // namespace MeshTools 140 : 141 : } // namespace libMesh 142 : 143 : #endif // LIBMESH_SIDES_TO_ELEM_MAP_H