libMesh
Loading...
Searching...
No Matches
cell_prism.C
Go to the documentation of this file.
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// C++ includes
20
21// Local includes
22#include "libmesh/cell_prism.h"
23#include "libmesh/cell_prism6.h"
24#include "libmesh/enum_elem_quality.h"
25#include "libmesh/face_quad4.h"
26#include "libmesh/face_tri3.h"
27
28namespace libMesh
29{
30
31
32// ------------------------------------------------------------
33// Prism class static member initializations
34const int Prism::num_sides;
35const int Prism::num_edges;
36const int Prism::num_children;
37
38const Real Prism::_master_points[21][3] =
39 {
40 {0, 0, -1},
41 {1, 0, -1},
42 {0, 1, -1},
43 {0, 0, 1},
44 {1, 0, 1},
45 {0, 1, 1},
46 {0.5, 0, -1},
47 {0.5, 0.5, -1},
48 {0, 0.5, -1},
49 {0, 0, 0},
50 {1, 0, 0},
51 {0, 1, 0},
52 {0.5, 0, 1},
53 {0.5, 0.5, 1},
54 {0, 0.5, 1},
55 {0.5, 0, 0},
56 {0.5, 0.5, 0},
57 {0, 0.5, 0},
58 {Real(1)/3, Real(1)/3, -1},
59 {Real(1)/3, Real(1)/3, 1},
60 {Real(1)/3, Real(1)/3, 0}
61 };
62
63const unsigned int Prism::edge_sides_map[9][2] =
64 {
65 {0, 1}, // Edge 0
66 {0, 2}, // Edge 1
67 {0, 3}, // Edge 2
68 {1, 3}, // Edge 3
69 {1, 2}, // Edge 4
70 {2, 3}, // Edge 5
71 {1, 4}, // Edge 6
72 {2, 4}, // Edge 7
73 {3, 4} // Edge 8
74 };
75
76const unsigned int Prism::adjacent_edges_map[/*num_vertices*/6][/*n_adjacent_edges*/3] =
77 {
78 {0, 2, 3}, // Edges adjacent to node 0
79 {0, 1, 4}, // Edges adjacent to node 1
80 {1, 2, 5}, // Edges adjacent to node 2
81 {3, 6, 8}, // Edges adjacent to node 3
82 {4, 6, 7}, // Edges adjacent to node 4
83 {5, 7, 8}, // Edges adjacent to node 5
84 };
85
86
87// ------------------------------------------------------------
88// Prism class member functions
89dof_id_type Prism::key (const unsigned int s) const
90{
91 libmesh_assert_less (s, this->n_sides());
92
93 switch (s)
94 {
95 case 0: // the triangular face at z=0
96 case 4: // the triangular face at z=1
97 return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
99 this->node_id(Prism6::side_nodes_map[s][2]));
100
101 case 1: // the quad face at y=0
102 case 2: // the other quad face
103 case 3: // the quad face at x=0
104 return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
105 this->node_id(Prism6::side_nodes_map[s][1]),
106 this->node_id(Prism6::side_nodes_map[s][2]),
107 this->node_id(Prism6::side_nodes_map[s][3]));
108
109 default:
110 libmesh_error_msg("Invalid side " << s);
111 }
112}
113
114
115
116dof_id_type Prism::low_order_key (const unsigned int s) const
117{
118 libmesh_assert_less (s, this->n_sides());
119
120 switch (s)
121 {
122 case 0: // the triangular face at z=0
123 case 4: // the triangular face at z=1
124 return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
125 this->node_id(Prism6::side_nodes_map[s][1]),
126 this->node_id(Prism6::side_nodes_map[s][2]));
127
128 case 1: // the quad face at y=0
129 case 2: // the other quad face
130 case 3: // the quad face at x=0
131 return this->compute_key (this->node_id(Prism6::side_nodes_map[s][0]),
132 this->node_id(Prism6::side_nodes_map[s][1]),
133 this->node_id(Prism6::side_nodes_map[s][2]),
134 this->node_id(Prism6::side_nodes_map[s][3]));
135
136 default:
137 libmesh_error_msg("Invalid side " << s);
138 }
139}
140
141
142
143unsigned int Prism::local_side_node(unsigned int side,
144 unsigned int side_node) const
145{
146 libmesh_assert_less (side, this->n_sides());
147
148 // Never more than 4 nodes per side.
149 libmesh_assert_less(side_node, Prism6::nodes_per_side);
150
151 // Some sides have 3 nodes.
152 libmesh_assert(!(side==0 || side==4) || side_node < 3);
153
154 return Prism6::side_nodes_map[side][side_node];
155}
156
157
158
159unsigned int Prism::local_edge_node(unsigned int edge,
160 unsigned int edge_node) const
161{
162 libmesh_assert_less(edge, this->n_edges());
163 libmesh_assert_less(edge_node, Prism6::nodes_per_edge);
164
165 return Prism6::edge_nodes_map[edge][edge_node];
166}
167
168
169
170std::unique_ptr<Elem> Prism::side_ptr (const unsigned int i)
171{
172 libmesh_assert_less (i, this->n_sides());
173
174 std::unique_ptr<Elem> face;
175
176 // Set up the type of element
177 switch (i)
178 {
179 case 0: // the triangular face at z=0
180 case 4: // the triangular face at z=1
181 {
182 face = std::make_unique<Tri3>();
183 break;
184 }
185 case 1: // the quad face at y=0
186 case 2: // the other quad face
187 case 3: // the quad face at x=0
188 {
189 face = std::make_unique<Quad4>();
190 break;
191 }
192 default:
193 libmesh_error_msg("Invalid side i = " << i);
194 }
195
196 // Set the nodes
197 for (auto n : face->node_index_range())
198 face->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
199
200 return face;
201}
202
203
204
205void Prism::side_ptr (std::unique_ptr<Elem> & side,
206 const unsigned int i)
207{
208 libmesh_assert_less (i, this->n_sides());
209
210 switch (i)
211 {
212 // the base face
213 case 0: // the triangular face at z=0
214 case 4: // the triangular face at z=1
215 {
216 if (!side.get() || side->type() != TRI3)
217 {
218 side = this->side_ptr(i);
219 return;
220 }
221 break;
222 }
223
224 case 1: // the quad face at y=0
225 case 2: // the other quad face
226 case 3: // the quad face at x=0
227 {
228 if (!side.get() || side->type() != QUAD4)
229 {
230 side = this->side_ptr(i);
231 return;
232 }
233 break;
234 }
235
236 default:
237 libmesh_error_msg("Invalid side i = " << i);
238 }
239
240 side->subdomain_id() = this->subdomain_id();
241
242 // Set the nodes
243 for (auto n : side->node_index_range())
244 side->set_node(n, this->node_ptr(Prism6::side_nodes_map[i][n]));
245}
246
247
248
249bool Prism::is_child_on_side(const unsigned int c,
250 const unsigned int s) const
251{
252 libmesh_assert_less (c, this->n_children());
253 libmesh_assert_less (s, this->n_sides());
254
255 for (unsigned int i = 0; i != 4; ++i)
256 if (Prism6::side_elems_map[s][i] == c)
257 return true;
258 return false;
259}
260
261
262
263bool Prism::is_edge_on_side(const unsigned int e,
264 const unsigned int s) const
265{
266 libmesh_assert_less (e, this->n_edges());
267 libmesh_assert_less (s, this->n_sides());
268
269 return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
270}
271
272
273
274std::vector<unsigned int> Prism::sides_on_edge(const unsigned int e) const
275{
276 libmesh_assert_less(e, this->n_edges());
277
278 return {edge_sides_map[e][0], edge_sides_map[e][1]};
279}
280
281
282
283unsigned int Prism::opposite_side(const unsigned int side_in) const
284{
285 libmesh_assert_less (side_in, 5);
286 static const unsigned int prism_opposites[5] =
288 return prism_opposites[side_in];
289}
290
291
292
293bool
295{
296 return (triple_product(this->point(1)-this->point(0),
297 this->point(2)-this->point(0),
298 this->point(3)-this->point(0)) < 0);
299}
300
301
302std::vector<unsigned int>
303Prism::edges_adjacent_to_node(const unsigned int n) const
304{
305 libmesh_assert_less(n, this->n_nodes());
306
307 // For vertices, we use the Prism::adjacent_sides_map, otherwise each
308 // of the mid-edge nodes is adjacent only to the edge it is on, and
309 // face/internal nodes are not adjacent to any edge.
310 if (this->is_vertex(n))
311 return {std::begin(adjacent_edges_map[n]), std::end(adjacent_edges_map[n])};
312 else if (this->is_edge(n))
313 return {n - this->n_vertices()};
314
315 libmesh_assert(this->is_face(n) || this->is_internal(n));
316 return {};
317}
318
319
320
322 const Real eps) const
323{
324 const Real & xi = p(0);
325 const Real & eta = p(1);
326 const Real & zeta = p(2);
327
328 // inside the reference triangle with zeta in [-1,1]
329 return ((xi >= 0.-eps) &&
330 (eta >= 0.-eps) &&
331 (zeta >= -1.-eps) &&
332 (zeta <= 1.+eps) &&
333 ((xi + eta) <= 1.+eps));
334}
335
336
337
338std::pair<Real, Real> Prism::qual_bounds (const ElemQuality) const
339{
340 // No suggested ranges have yet been established for any of the
341 // metrics Quality::valid() lists for prisms, so we always return
342 // the (-1, -1) sentinel.
343 libmesh_warning("Invalid quality measure chosen.");
344 return std::make_pair(Real(-1), Real(-1));
345}
346
347
348
349const unsigned short int Prism::_second_order_vertex_child_number[18] =
350 {
351 99,99,99,99,99,99, // Vertices
352 0,1,0,0,1,2,3,4,3, // Edges
353 0,1,0 // Faces
354 };
355
356
357
358const unsigned short int Prism::_second_order_vertex_child_index[18] =
359 {
360 99,99,99,99,99,99, // Vertices
361 1,2,2,3,4,5,4,5,5, // Edges
362 4,5,5 // Faces
363 };
364
365
366const unsigned short int Prism::_second_order_adjacent_vertices[9][2] =
367 {
368 { 0, 1}, // vertices adjacent to node 6
369 { 1, 2}, // vertices adjacent to node 7
370 { 0, 2}, // vertices adjacent to node 8
371
372 { 0, 3}, // vertices adjacent to node 9
373 { 1, 4}, // vertices adjacent to node 10
374 { 2, 5}, // vertices adjacent to node 11
375
376 { 3, 4}, // vertices adjacent to node 12
377 { 4, 5}, // vertices adjacent to node 13
378 { 3, 5} // vertices adjacent to node 14
379 };
380
381} // namespace libMesh
const Point & point(const unsigned int i) const
Definition elem.h:2583
virtual bool is_face(const unsigned int i) const =0
subdomain_id_type subdomain_id() const
Definition elem.h:2712
virtual bool is_edge(const unsigned int i) const =0
static dof_id_type compute_key(dof_id_type n0)
Definition elem.h:3432
bool is_internal(const unsigned int i) const
Definition elem.C:4014
virtual bool is_vertex(const unsigned int i) const =0
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2605
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:41
static constexpr unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
static const unsigned int side_elems_map[num_sides][nodes_per_side]
This maps the child elements with the associated side of the parent element.
static const int nodes_per_edge
static const int nodes_per_side
static constexpr unsigned int edge_nodes_map[num_edges][nodes_per_edge]
This maps the node of the edge to element node numbers.
virtual unsigned int n_vertices() const override final
Definition cell_prism.h:91
static const unsigned int adjacent_edges_map[6][3]
This maps the Prism vertex to the (in this case) 3 edge ids adjacent to the node.
Definition cell_prism.h:232
virtual std::vector< unsigned int > edges_adjacent_to_node(const unsigned int n) const override
Definition cell_prism.C:303
virtual bool is_flipped() const override final
Definition cell_prism.C:294
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const override final
Definition cell_prism.C:321
virtual unsigned int n_edges() const override final
Definition cell_prism.h:96
static const int num_children
Definition cell_prism.h:75
virtual unsigned int n_sides() const override final
Definition cell_prism.h:86
static const unsigned short int _second_order_vertex_child_number[18]
Vector that names a child sharing each second order node.
Definition cell_prism.h:213
static const unsigned int edge_sides_map[9][2]
This maps each edge to the sides that contain said edge.
Definition cell_prism.h:181
virtual dof_id_type key() const
Don't hide Elem::key() defined in the base class.
Definition elem.C:678
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const override
Definition cell_prism.C:143
virtual unsigned int n_children() const override final
Definition cell_prism.h:106
static const Real _master_points[21][3]
Master element node locations.
Definition cell_prism.h:223
static const int num_edges
Definition cell_prism.h:74
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const override final
Definition cell_prism.C:263
virtual unsigned int n_nodes() const override
Definition cell_prism.h:81
virtual std::vector< unsigned int > sides_on_edge(const unsigned int e) const override final
Definition cell_prism.C:274
static const int num_sides
Geometric constants for all Prisms.
Definition cell_prism.h:73
virtual std::pair< Real, Real > qual_bounds(const ElemQuality q) const override
Definition cell_prism.C:338
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
Definition cell_prism.C:170
virtual dof_id_type low_order_key(const unsigned int s) const override
Definition cell_prism.C:116
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const override final
Definition cell_prism.C:249
static const unsigned short int _second_order_adjacent_vertices[9][2]
Matrix that tells which vertices define the location of mid-side (or second-order) nodes.
Definition cell_prism.h:208
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const override
Definition cell_prism.C:159
static const unsigned short int _second_order_vertex_child_index[18]
Vector that names the child vertex index for each second order node.
Definition cell_prism.h:218
virtual unsigned int opposite_side(const unsigned int s) const override final
Definition cell_prism.C:283
The libMesh namespace provides an interface to certain functionality in the library.
LIBMESH_DEVICE_INLINE T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
libmesh_assert(ctx)
const unsigned int invalid_uint
A number which is used quite often to represent an invalid or uninitialized value for an unsigned int...
Definition libmesh.h:303
ElemQuality
Defines an enum for element quality metrics.
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real