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 : 19 : 20 : #ifndef LIBMESH_CELL_INF_HEX_H 21 : #define LIBMESH_CELL_INF_HEX_H 22 : 23 : #include "libmesh/libmesh_config.h" 24 : 25 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 26 : 27 : // Local includes 28 : #include "libmesh/cell_inf.h" 29 : 30 : namespace libMesh 31 : { 32 : 33 : /** 34 : * The \p InfHex is an element in 3D with 5 sides. 35 : * The \f$ 6^{th} \f$ side is theoretically located at infinity, 36 : * and therefore not accounted for. 37 : * However, one could say that the \f$ 6^{th} \f$ side actually 38 : * does exist in the mesh, since the outer nodes are located 39 : * at a specific distance from the mesh origin (and therefore 40 : * define a side). Still, this face is not to be used! 41 : * 42 : * \author Daniel Dreyer 43 : * \date 2003 44 : * \brief The base class for all 3D infinite hexahedral element types. 45 : */ 46 : class InfHex : public InfCell 47 : { 48 : public: 49 : 50 : /** 51 : * Default infinite brick element, takes number of nodes and 52 : * parent. Derived classes implement 'true' elements. 53 : */ 54 2077 : InfHex(const unsigned int nn, Elem * p, Node ** nodelinkdata) : 55 2077 : InfCell(nn, num_sides, p, _elemlinks_data, nodelinkdata) 56 : { 57 : // Make sure the interior parent isn't undefined 58 : if (LIBMESH_DIM > 3) 59 : this->set_interior_parent(nullptr); 60 1080 : } 61 : 62 : InfHex (InfHex &&) = delete; 63 : InfHex (const InfHex &) = delete; 64 : InfHex & operator= (const InfHex &) = delete; 65 : InfHex & operator= (InfHex &&) = delete; 66 1080 : virtual ~InfHex() = default; 67 : 68 : /** 69 : * \returns The \p Point associated with local \p Node \p i, 70 : * in master element rather than physical coordinates. 71 : */ 72 40660 : virtual Point master_point (const unsigned int i) const override final 73 : { 74 16264 : libmesh_assert_less(i, this->n_nodes()); 75 40660 : return Point(_master_points[i][0], 76 40660 : _master_points[i][1], 77 56924 : _master_points[i][2]); 78 : } 79 : 80 : /** 81 : * Geometric constants for all InfHexes. 82 : */ 83 : static const int num_sides = 5; 84 : static const int num_edges = 8; 85 : static const int num_children = 4; 86 : 87 : /** 88 : * \returns 5. Infinite elements have one side less 89 : * than their conventional counterparts, since one 90 : * side is supposed to be located at infinity. 91 : */ 92 851340 : virtual unsigned int n_sides() const override final { return 5; } 93 : 94 : /** 95 : * \returns 8. All infinite hexahedra (in our 96 : * setting) have 8 "vertices"; we're counting the infinite edge's 97 : * nodes too. 98 : */ 99 273860 : virtual unsigned int n_vertices() const override final { return 8; } 100 : 101 : /** 102 : * \returns \p true if the specified (local) node number is a 103 : * "mid-edge" node on an infinite element edge. 104 : */ 105 200 : virtual bool is_mid_infinite_edge_node(const unsigned int i) const 106 200 : override final { return (i > 3 && i < 8); } 107 : 108 : /** 109 : * \returns 8. All infinite hexahedra have 8 edges, 110 : * 4 lying in the base, and 4 perpendicular to the base. 111 : */ 112 261231 : virtual unsigned int n_edges() const override final { return 8; } 113 : 114 : /** 115 : * \returns 5. All infinite hexahedra have 5 faces. 116 : */ 117 0 : virtual unsigned int n_faces() const override final { return 5; } 118 : 119 : /** 120 : * \returns 4. 121 : */ 122 192382 : virtual unsigned int n_children() const override final { return 4; } 123 : 124 : /** 125 : * We number vertices first. 126 : */ 127 83117 : virtual bool is_vertex(const unsigned int i) const override final { return (i < 8); } 128 : 129 : /** 130 : * We number edges next. 131 : */ 132 293 : virtual bool is_edge(const unsigned int i) const override final { return (i >= 8 && i < 12); } 133 : 134 : /** 135 : * We number faces last. 136 : */ 137 33439 : virtual bool is_face(const unsigned int i) const override final { return (i >= 12 && i < 17); } 138 : 139 : /** 140 : * \returns \p true if the specified child is on the 141 : * specified side. 142 : */ 143 : virtual bool is_child_on_side(const unsigned int c, 144 : const unsigned int s) const override final; 145 : 146 : /** 147 : * \returns \p true if the specified edge is on the specified side. 148 : */ 149 : virtual bool is_edge_on_side(const unsigned int e, 150 : const unsigned int s) const override final; 151 : 152 : virtual std::vector<unsigned int> sides_on_edge(const unsigned int e) const override final; 153 : 154 : /** 155 : * Don't hide Elem::key() defined in the base class. 156 : */ 157 : using Elem::key; 158 : 159 : /** 160 : * \returns An id associated with the \p s side of this element. 161 : * The id is not necessarily unique, but should be close. 162 : */ 163 : virtual dof_id_type key (const unsigned int s) const override; 164 : 165 : /** 166 : * \returns An id associated with the \p s side of this element, as 167 : * defined solely by element vertices. The id is not necessarily 168 : * unique, but should be close. This is particularly useful in the 169 : * \p MeshBase::find_neighbors() routine. 170 : */ 171 : virtual dof_id_type low_order_key (const unsigned int s) const override; 172 : 173 : /** 174 : * \returns \p InfHex8::side_nodes_map[side][side_node] after doing some range checking. 175 : */ 176 : virtual unsigned int local_side_node(unsigned int side, 177 : unsigned int side_node) const override; 178 : 179 : /** 180 : * \returns \p InfHex8::edge_nodes_map[edge][edge_node] after doing some range checking. 181 : */ 182 : virtual unsigned int local_edge_node(unsigned int edge, 183 : unsigned int edge_node) const override; 184 : 185 : /** 186 : * \returns A primitive (4-noded) quad or infquad for face i. 187 : */ 188 : virtual std::unique_ptr<Elem> side_ptr (const unsigned int i) override final; 189 : 190 : /** 191 : * Rebuilds a primitive (4-noded) quad or infquad for face i. 192 : */ 193 : virtual void side_ptr (std::unique_ptr<Elem> & side, const unsigned int i) override final; 194 : 195 : /** 196 : * \returns A quantitative assessment of element quality based on 197 : * the metric \p q specified by the user. 198 : */ 199 : virtual Real quality (const ElemQuality q) const override; 200 : 201 : /** 202 : * \returns The suggested quality bounds for the hex based on 203 : * quality measure \p q. These are the values suggested by the 204 : * CUBIT User's Manual. 205 : */ 206 : virtual std::pair<Real, Real> qual_bounds (const ElemQuality q) const override; 207 : 208 : /** 209 : * \returns \p true when this element contains the point 210 : * \p p. Customized for infinite elements, since knowledge 211 : * about the envelope can be helpful. 212 : */ 213 : virtual bool contains_point (const Point & p, Real tol=TOLERANCE) const override; 214 : 215 : /** 216 : * One non-infinite side, four orientations. 217 : */ 218 0 : virtual unsigned int n_permutations() const override final { return 4; } 219 : 220 : virtual bool is_flipped() const override final; 221 : 222 : virtual std::vector<unsigned int> edges_adjacent_to_node(const unsigned int n) const override; 223 : 224 : /** 225 : * This maps each edge to the sides that contain said edge. 226 : */ 227 : static const unsigned int edge_sides_map[8][2]; 228 : 229 : virtual bool on_reference_element(const Point & p, 230 : const Real eps = TOLERANCE) const override final; 231 : 232 : protected: 233 : 234 : /** 235 : * Data for links to parent/neighbor/interior_parent elements. 236 : */ 237 : Elem * _elemlinks_data[6+(LIBMESH_DIM>3)]; 238 : 239 : 240 : 241 : /** 242 : * For higher-order elements, namely \p InfHex16 and 243 : * \p InfHex18, the matrices for adjacent vertices 244 : * of second order nodes are quite similar (apart from 245 : * the face nodes, which are directly handled by \p InfHex18). 246 : * Therefore hold this matrix here, so that both can re-use 247 : * this. Matrix that tells which vertices define the location 248 : * of mid-side (or second-order) nodes. 249 : */ 250 : static const unsigned short int _second_order_adjacent_vertices[8][2]; 251 : 252 : /** 253 : * Vector that names a child sharing each second order node. 254 : */ 255 : static const unsigned short int _second_order_vertex_child_number[18]; 256 : 257 : /** 258 : * Vector that names the child vertex index for each second order node. 259 : */ 260 : static const unsigned short int _second_order_vertex_child_index[18]; 261 : 262 : /** 263 : * Master element node locations 264 : */ 265 : static const Real _master_points[18][3]; 266 : 267 : /** 268 : * This maps the \f$ j^{th} \f$ node to the 3 (or fewer) edge ids 269 : * adjacent to the node. The edge numbering matches the one used in 270 : * the derived classes' edge_nodes_map. An edge index of 99 is used 271 : * to indicate that there is no adjacent edge. This data structure 272 : * is used in the InfHex::edges_adjacent_to_node() override and is 273 : * shared by all the derived InfHex types. 274 : */ 275 : static const unsigned int adjacent_edges_map[/*num_vertices*/8][/*max_adjacent_edges*/3]; 276 : }; 277 : 278 : 279 : } // namespace libMesh 280 : 281 : #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS 282 : 283 : #endif // LIBMESH_CELL_INF_HEX_H