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