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