Line data Source code
1 : // The libMesh Finite Element Library. 2 : // Copyright (C) 2002-2026 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_PRISM18_H 21 : #define LIBMESH_CELL_PRISM18_H 22 : 23 : // Local includes 24 : #include "libmesh/cell_prism.h" 25 : #include "libmesh/cell_prism6.h" 26 : #include "libmesh/fe_reference_element_traits.h" 27 : 28 : namespace libMesh 29 : { 30 : 31 : /** 32 : * The \p Prism18 is an element in 3D composed of 18 nodes. 33 : * It is numbered like this: 34 : * 35 : * \verbatim 36 : * PRISM18: 37 : * 5 38 : * o 39 : * /:\ 40 : * / : \ 41 : * / : \ 42 : * / : \ 43 : * 14 o : o 13 44 : * / : \ 45 : * / : \ 46 : * / o 11 \ 47 : * 3 / : \4 48 : * o---------o---------o 49 : * | :12 | 50 : * | : | 51 : * | o : o | zeta 52 : * | 17 o 16 | ^ eta (into page) 53 : * | .2. | | / 54 : * | . . | |/ 55 : * 9 o . o . o 10 o---> xi 56 : * | . 15 . | 57 : * | 8 o o 7 | 58 : * | . . | 59 : * | . . | 60 : * | . . | 61 : * |. .| 62 : * o---------o---------o 63 : * 0 6 1 64 : * \endverbatim 65 : * 66 : * (xi, eta, zeta): { 0 <= xi <= 1 67 : * { 0 <= eta <= 1 68 : * { -1 <= zeta <= 1 69 : * { xi + eta <= 1 70 : * are the reference element coordinates associated with the given 71 : * numbering. 72 : * 73 : * \author Benjamin S. Kirk 74 : * \date 2003 75 : * \brief A 3D prismatic element with 18 nodes. 76 : */ 77 : class Prism18 final : public Prism 78 : { 79 : public: 80 : 81 : /** 82 : * Constructor. By default this element has no parent. 83 : */ 84 : explicit 85 598741 : Prism18 (Elem * p=nullptr) : 86 598741 : Prism(num_nodes, p, _nodelinks_data) 87 598741 : {} 88 : 89 : Prism18 (Prism18 &&) = delete; 90 : Prism18 (const Prism18 &) = delete; 91 : Prism18 & operator= (const Prism18 &) = delete; 92 : Prism18 & operator= (Prism18 &&) = delete; 93 623006 : virtual ~Prism18() = default; 94 : 95 : /** 96 : * \returns \p PRISM18. 97 : */ 98 599110772 : virtual ElemType type () const override { return PRISM18; } 99 : 100 : /** 101 : * \returns 18. 102 : */ 103 167364299 : virtual unsigned int n_nodes() const override { return num_nodes; } 104 : 105 : /** 106 : * \returns 8. 107 : */ 108 0 : virtual unsigned int n_sub_elem() const override { return 8; } 109 : 110 : /** 111 : * \returns \p true if the specified (local) node number is a vertex. 112 : */ 113 : virtual bool is_vertex(const unsigned int i) const override; 114 : 115 : /** 116 : * \returns \p true if the specified (local) node number is an edge. 117 : */ 118 : virtual bool is_edge(const unsigned int i) const override; 119 : 120 : /** 121 : * \returns \p true if the specified (local) node number is a face. 122 : */ 123 : virtual bool is_face(const unsigned int i) const override; 124 : 125 : /** 126 : * \returns \p true if the specified (local) node number is on the 127 : * specified side. 128 : */ 129 : virtual bool is_node_on_side(const unsigned int n, 130 : const unsigned int s) const override; 131 : 132 : virtual std::vector<unsigned int> nodes_on_side(const unsigned int s) const override; 133 : 134 : virtual std::vector<unsigned int> nodes_on_edge(const unsigned int e) const override; 135 : 136 : /** 137 : * \returns \p true if the specified (local) node number is on the 138 : * specified edge. 139 : */ 140 : virtual bool is_node_on_edge(const unsigned int n, 141 : const unsigned int e) const override; 142 : 143 : /** 144 : * \returns \p true if the element map is definitely affine within 145 : * numerical tolerances. 146 : */ 147 : virtual bool has_affine_map () const override; 148 : 149 : /** 150 : * \returns SECOND. 151 : */ 152 : virtual Order default_order() const override; 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 : * We reimplement this method here for the \p Prism18 since we can 164 : * use the center node of each quad face to provide a perfect (unique) 165 : * key. 166 : */ 167 : virtual dof_id_type key (const unsigned int s) const override; 168 : 169 : /** 170 : * \returns \p Prism18::side_nodes_map[side][side_node] after doing some range checking. 171 : */ 172 : virtual unsigned int local_side_node(unsigned int side, 173 : unsigned int side_node) const override; 174 : 175 : /** 176 : * \returns \p Prism18::edge_nodes_map[edge][edge_node] after doing some range checking. 177 : */ 178 : virtual unsigned int local_edge_node(unsigned int edge, 179 : unsigned int edge_node) const override; 180 : 181 : /** 182 : * Builds a \p QUAD9 or \p TRI6 built coincident with face i. 183 : * The \p std::unique_ptr<Elem> handles the memory aspect. 184 : */ 185 : virtual std::unique_ptr<Elem> build_side_ptr (const unsigned int i) override; 186 : 187 : /** 188 : * Rebuilds a \p QUAD9 or \p TRI6 built coincident with face i. 189 : */ 190 : virtual void build_side_ptr (std::unique_ptr<Elem> & elem, 191 : const unsigned int i) override; 192 : 193 : // Avoid hiding deprecated version with different signature 194 : using Elem::build_side_ptr; 195 : 196 : /** 197 : * Builds a \p EDGE3 or \p INFEDGE2 built coincident with edge i. 198 : * The \p std::unique_ptr<Elem> handles the memory aspect. 199 : */ 200 : virtual std::unique_ptr<Elem> build_edge_ptr (const unsigned int i) override; 201 : 202 : /** 203 : * Rebuilds a \p EDGE3 built coincident with edges 0 to 2, or \p 204 : * INFEDGE2 built coincident with edges 3 to 5. 205 : */ 206 : virtual void build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i) override; 207 : 208 : virtual void connectivity(const unsigned int sc, 209 : const IOPackage iop, 210 : std::vector<dof_id_type> & conn) const override; 211 : 212 : /** 213 : * \returns 2 for all edge nodes and 4 for face nodes. 214 : */ 215 : virtual unsigned int n_second_order_adjacent_vertices (const unsigned int) const override; 216 : 217 : /** 218 : * \returns The element-local number of the \f$ v^{th} \f$ vertex 219 : * that defines the \f$ n^{th} \f$ second-order node. 220 : * 221 : * \note \p n is counted as depicted above, \f$ 6 \le n < 18 \f$. 222 : */ 223 : virtual unsigned short int second_order_adjacent_vertex (const unsigned int n, 224 : const unsigned int v) const override; 225 : 226 : /** 227 : * \returns The child number \p c and element-local index \p v of the 228 : * \f$ n^{th} \f$ second-order node on the parent element. See 229 : * elem.h for further details. 230 : */ 231 : virtual std::pair<unsigned short int, unsigned short int> 232 : second_order_child_vertex (const unsigned int n) const override; 233 : 234 : /** 235 : * Geometric constants for Prism18. 236 : */ 237 : static const int num_nodes = 18; 238 : static const int nodes_per_side = 9; 239 : static const int nodes_per_edge = 3; 240 : 241 : /** 242 : * These map the \f$ j^{th} \f$ node of the \f$ i^{th} \f$ edge or 243 : * side to element node numbers. They are derived from the 244 : * first-order Prism6 tables; see fe_reference_element_traits.h. 245 : */ 246 : static constexpr NodeMapTable<num_edges, nodes_per_edge> 247 : _edge_nodes = derived_edge_nodes<Prism6, num_edges>(); 248 : static constexpr const unsigned int (&edge_nodes_map)[num_edges][nodes_per_edge] = _edge_nodes.values; 249 : 250 : static constexpr NodeMapTable<num_sides, nodes_per_side> 251 : _side_nodes = derived_side_nodes<Prism6, num_sides, nodes_per_side> 252 : (_edge_nodes.values, [](unsigned int s) { return (s >= 1 && s <= 3) ? 14 + s : invalid_uint; }); 253 : static constexpr const unsigned int (&side_nodes_map)[num_sides][nodes_per_side] = _side_nodes.values; 254 : 255 : /** 256 : * A specialization for computing the volume of a Prism18. 257 : */ 258 : virtual Real volume () const override; 259 : 260 : virtual void permute(unsigned int perm_num) override final; 261 : 262 : virtual void flip(BoundaryInfo *) override final; 263 : 264 : unsigned int center_node_on_side(const unsigned short side) const override final; 265 : 266 : ElemType side_type (const unsigned int s) const override final; 267 : 268 : protected: 269 : 270 : /** 271 : * Data for links to nodes. 272 : */ 273 : Node * _nodelinks_data[num_nodes]; 274 : 275 : 276 : 277 : #ifdef LIBMESH_ENABLE_AMR 278 : 279 : /** 280 : * Matrix used to create the elements children. 281 : */ 282 7171479 : virtual Real embedding_matrix (const unsigned int i, 283 : const unsigned int j, 284 : const unsigned int k) const override 285 7171479 : { return _embedding_matrix[i][j][k]; } 286 : 287 : /** 288 : * Matrix that computes new nodal locations/solution values 289 : * from current nodes/solution. 290 : */ 291 : static const Real _embedding_matrix[num_children][num_nodes][num_nodes]; 292 : 293 58826180 : LIBMESH_ENABLE_TOPOLOGY_CACHES; 294 : 295 : #endif // LIBMESH_ENABLE_AMR 296 : 297 : /** 298 : * Matrix that tells which vertices define the location 299 : * of mid-side (or second-order) nodes. This matrix 300 : * handles only the second-order nodes that are unique 301 : * to \p Prism18. All other second-order nodes are identical 302 : * with \p Prism15, and are therefore handled through a 303 : * matrix contained in \p cell_prism.C 304 : */ 305 : static const unsigned short int _remaining_second_order_adjacent_vertices[3][4]; 306 : }; 307 : 308 : } // namespace libMesh 309 : 310 : #endif // LIBMESH_CELL_PRISM18_H