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