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_PRISM21_H
21 : #define LIBMESH_CELL_PRISM21_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 Prism21 is an element in 3D composed of 21 nodes.
33 : * It is numbered like this:
34 : *
35 : * \verbatim
36 : * PRISM21:
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 : * And it also includes two face nodes:
67 : * Node 18, centroid on side 0, arithmetic mean of 0/1/2 or 6/7/8
68 : * Node 19, centroid on side 4, arithmetic mean of 3/4/5 or 12/13/14
69 : *
70 : * And one midpoint node:
71 : * Node 20, on the interior, arithmetic mean of 9/10/11 or 15/16/17
72 : *
73 : * (xi, eta, zeta): { 0 <= xi <= 1
74 : * { 0 <= eta <= 1
75 : * { -1 <= zeta <= 1
76 : * { xi + eta <= 1
77 : * are the reference element coordinates associated with the given
78 : * numbering.
79 : *
80 : * \author Roy H. Stogner
81 : * \date 2022
82 : * \brief A 3D prismatic element with 21 nodes.
83 : */
84 : class Prism21 final : public Prism
85 : {
86 : public:
87 :
88 : /**
89 : * Constructor. By default this element has no parent.
90 : */
91 : explicit
92 265570 : Prism21 (Elem * p=nullptr) :
93 265570 : Prism(num_nodes, p, _nodelinks_data)
94 265570 : {}
95 :
96 : Prism21 (Prism21 &&) = delete;
97 : Prism21 (const Prism21 &) = delete;
98 : Prism21 & operator= (const Prism21 &) = delete;
99 : Prism21 & operator= (Prism21 &&) = delete;
100 275407 : virtual ~Prism21() = default;
101 :
102 : /**
103 : * \returns \p PRISM21.
104 : */
105 2195066660 : virtual ElemType type () const override { return PRISM21; }
106 :
107 : /**
108 : * \returns 21.
109 : */
110 481764582 : virtual unsigned int n_nodes() const override { return num_nodes; }
111 :
112 : /**
113 : * \returns 8.
114 : */
115 0 : virtual unsigned int n_sub_elem() const override { return 8; }
116 :
117 : /**
118 : * \returns \p true if the specified (local) node number is a vertex.
119 : */
120 : virtual bool is_vertex(const unsigned int i) const override;
121 :
122 : /**
123 : * \returns \p true if the specified (local) node number is an edge.
124 : */
125 : virtual bool is_edge(const unsigned int i) const override;
126 :
127 : /**
128 : * \returns \p true if the specified (local) node number is a face.
129 : */
130 : virtual bool is_face(const unsigned int i) const override;
131 :
132 : /**
133 : * \returns \p true if the specified (local) node number is on the
134 : * specified side.
135 : */
136 : virtual bool is_node_on_side(const unsigned int n,
137 : const unsigned int s) const override;
138 :
139 : virtual std::vector<unsigned int> nodes_on_side(const unsigned int s) const override;
140 :
141 : virtual std::vector<unsigned int> nodes_on_edge(const unsigned int e) const override;
142 :
143 : /**
144 : * \returns \p true if the specified (local) node number is on the
145 : * specified edge.
146 : */
147 : virtual bool is_node_on_edge(const unsigned int n,
148 : const unsigned int e) const override;
149 :
150 : /**
151 : * \returns \p true if the element map is definitely affine within
152 : * numerical tolerances.
153 : */
154 : virtual bool has_affine_map () const override;
155 :
156 : /**
157 : * \returns SECOND.
158 : */
159 : virtual Order default_order() const override;
160 :
161 : /**
162 : * Don't hide Elem::key() defined in the base class.
163 : */
164 : using Elem::key;
165 :
166 : /**
167 : * \returns An id associated with the \p s side of this element.
168 : * The id is not necessarily unique, but should be close.
169 : *
170 : * We reimplement this method here for the \p Prism21 since we can
171 : * use the center node of each quad face to provide a perfect (unique)
172 : * key.
173 : */
174 : virtual dof_id_type key (const unsigned int s) const override;
175 :
176 : /**
177 : * \returns \p Prism21::side_nodes_map[side][side_node] after doing some range checking.
178 : */
179 : virtual unsigned int local_side_node(unsigned int side,
180 : unsigned int side_node) const override;
181 :
182 : /**
183 : * \returns \p Prism21::edge_nodes_map[edge][edge_node] after doing some range checking.
184 : */
185 : virtual unsigned int local_edge_node(unsigned int edge,
186 : unsigned int edge_node) const override;
187 :
188 : /**
189 : * Builds a \p QUAD9 or \p TRI6 built coincident with face i.
190 : * The \p std::unique_ptr<Elem> handles the memory aspect.
191 : */
192 : virtual std::unique_ptr<Elem> build_side_ptr (const unsigned int i) override;
193 :
194 : /**
195 : * Rebuilds a \p QUAD9 or \p TRI6 built coincident with face i.
196 : */
197 : virtual void build_side_ptr (std::unique_ptr<Elem> & elem,
198 : const unsigned int i) override;
199 :
200 : // Avoid hiding deprecated version with different signature
201 : using Elem::build_side_ptr;
202 :
203 : /**
204 : * Builds a \p EDGE3 or \p INFEDGE2 built coincident with edge i.
205 : * The \p std::unique_ptr<Elem> handles the memory aspect.
206 : */
207 : virtual std::unique_ptr<Elem> build_edge_ptr (const unsigned int i) override;
208 :
209 : /**
210 : * Rebuilds a \p EDGE3 built coincident with edges 0 to 2, or \p
211 : * INFEDGE2 built coincident with edges 3 to 5.
212 : */
213 : virtual void build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i) override;
214 :
215 : virtual void connectivity(const unsigned int sc,
216 : const IOPackage iop,
217 : std::vector<dof_id_type> & conn) const override;
218 :
219 : /**
220 : * \returns 2 for all edge nodes, 4 for quad face nodes, 3 for tri
221 : * face nodes, 6 for the interior node.
222 : */
223 : virtual unsigned int n_second_order_adjacent_vertices (const unsigned int) const override;
224 :
225 : /**
226 : * \returns The element-local number of the \f$ v^{th} \f$ vertex
227 : * that defines the \f$ n^{th} \f$ second-order node.
228 : *
229 : * \note \p n is counted as depicted above, \f$ 6 \le n < 21 \f$.
230 : */
231 : virtual unsigned short int second_order_adjacent_vertex (const unsigned int n,
232 : const unsigned int v) const override;
233 :
234 : /**
235 : * \returns The child number \p c and element-local index \p v of the
236 : * \f$ n^{th} \f$ second-order node on the parent element. See
237 : * elem.h for further details.
238 : */
239 : virtual std::pair<unsigned short int, unsigned short int>
240 : second_order_child_vertex (const unsigned int n) const override;
241 :
242 : /**
243 : * Geometric constants for Prism21.
244 : */
245 : static const int num_nodes = 21;
246 : static const int nodes_per_side = 9;
247 : static const int nodes_per_edge = 3;
248 :
249 : /**
250 : * These map the \f$ j^{th} \f$ node of the \f$ i^{th} \f$ edge or
251 : * side to element node numbers. They are derived from the
252 : * first-order Prism6 tables; see fe_reference_element_traits.h.
253 : */
254 : static constexpr NodeMapTable<num_edges, nodes_per_edge>
255 : _edge_nodes = derived_edge_nodes<Prism6, num_edges>();
256 : static constexpr const unsigned int (&edge_nodes_map)[num_edges][nodes_per_edge] = _edge_nodes.values;
257 :
258 : static constexpr NodeMapTable<num_sides, nodes_per_side>
259 : _side_nodes = derived_side_nodes<Prism6, num_sides, nodes_per_side>
260 : (_edge_nodes.values, [](unsigned int s) { return s == 0 ? 18u : s == 4 ? 19u : 14 + s; });
261 : static constexpr const unsigned int (&side_nodes_map)[num_sides][nodes_per_side] = _side_nodes.values;
262 :
263 : virtual void permute(unsigned int perm_num) override final;
264 :
265 : virtual void flip(BoundaryInfo *) override final;
266 :
267 : #ifdef LIBMESH_ENABLE_AMR
268 : virtual
269 : const std::vector<std::pair<unsigned char, unsigned char>> &
270 1875446 : parent_bracketing_nodes(unsigned int c,
271 : unsigned int n) const override
272 1875446 : { return _parent_bracketing_nodes[c][n]; }
273 : #endif
274 :
275 : unsigned int center_node_on_side(const unsigned short side) const override final;
276 :
277 : ElemType side_type (const unsigned int s) const override final;
278 :
279 : protected:
280 :
281 : /**
282 : * Data for links to nodes.
283 : */
284 : Node * _nodelinks_data[num_nodes];
285 :
286 :
287 :
288 : #ifdef LIBMESH_ENABLE_AMR
289 :
290 : /**
291 : * Matrix used to create the elements children.
292 : */
293 12167427 : virtual Real embedding_matrix (const unsigned int i,
294 : const unsigned int j,
295 : const unsigned int k) const override
296 12167427 : { return _embedding_matrix[i][j][k]; }
297 :
298 : /**
299 : * Matrix that computes new nodal locations/solution values
300 : * from current nodes/solution.
301 : */
302 : static const Real _embedding_matrix[num_children][num_nodes][num_nodes];
303 :
304 : /**
305 : * Pairs of nodes that bracket child nodes when doing mesh
306 : * refinement.
307 : */
308 : static const std::vector<std::pair<unsigned char, unsigned char>>
309 : _parent_bracketing_nodes[num_children][num_nodes];
310 :
311 2499588 : LIBMESH_ENABLE_TOPOLOGY_CACHES;
312 :
313 : #endif // LIBMESH_ENABLE_AMR
314 :
315 : /**
316 : * Matrix that tells which vertices define the location
317 : * of mid-side (or second-order) nodes. This matrix
318 : * handles only the second-order nodes that are unique
319 : * to \p Prism20. Earlier second-order nodes are identical
320 : * with \p Prism15, and are therefore handled through a
321 : * matrix contained in \p cell_prism.C; the final second-order node
322 : * is just a simple identity map.
323 : */
324 : static const unsigned short int _remaining_second_order_adjacent_vertices[5][4];
325 : };
326 :
327 : } // namespace libMesh
328 :
329 : #endif // LIBMESH_CELL_PRISM21_H
|