libMesh
Loading...
Searching...
No Matches
cell_pyramid.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_pyramid.h"
23#include "libmesh/cell_pyramid5.h"
24#include "libmesh/enum_elem_quality.h"
25#include "libmesh/face_tri3.h"
26#include "libmesh/face_quad4.h"
27
28namespace libMesh
29{
30
31// ------------------------------------------------------------
32// Pyramid class static member initializations
33const int Pyramid::num_sides;
34const int Pyramid::num_edges;
35const int Pyramid::num_children;
36
37const Real Pyramid::_master_points[18][3] =
38 {
39 {-1, -1, 0},
40 {1, -1, 0},
41 {1, 1, 0},
42 {-1, 1, 0},
43 {0, 0, 1},
44 {0, -1, 0},
45 {1, 0, 0},
46 {0, 1, 0},
47 {-1, 0, 0},
48 {-0.5, -0.5, 0.5},
49 {0.5, -0.5, 0.5},
50 {0.5, 0.5, 0.5},
51 {-0.5, 0.5, 0.5},
52 {0, 0, 0},
53 {0, -Real(2)/3, Real(1)/3},
54 { Real(2)/3, 0, Real(1)/3},
55 {0, Real(2)/3, Real(1)/3},
56 {-Real(2)/3, 0, Real(1)/3}
57 };
58
59const unsigned int Pyramid::edge_sides_map[8][2] =
60 {
61 {0, 4}, // Edge 0
62 {1, 4}, // Edge 1
63 {2, 4}, // Edge 2
64 {3, 4}, // Edge 3
65 {0, 3}, // Edge 4
66 {0, 1}, // Edge 5
67 {1, 2}, // Edge 6
68 {2, 3} // Edge 7
69 };
70
71const unsigned int Pyramid::adjacent_edges_map[/*num_vertices*/5][/*max_adjacent_edges*/4] =
72 {
73 {0, 3, 4, 99}, // Edges adjacent to node 0
74 {0, 1, 5, 99}, // Edges adjacent to node 1
75 {1, 2, 6, 99}, // Edges adjacent to node 2
76 {2, 3, 7, 99}, // Edges adjacent to node 3
77 {4, 5, 6, 7} // Edges adjacent to node 4
78 };
79
80// ------------------------------------------------------------
81// Pyramid class member functions
82dof_id_type Pyramid::key (const unsigned int s) const
83{
84 libmesh_assert_less (s, this->n_sides());
85
86 switch (s)
87 {
88 case 0: // triangular face 1
89 case 1: // triangular face 2
90 case 2: // triangular face 3
91 case 3: // triangular face 4
92 return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
95
96 case 4: // the quad face at z=0
97 return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
100 this->node_id(Pyramid5::side_nodes_map[s][3]));
101
102 default:
103 libmesh_error_msg("Invalid side s = " << s);
104 }
105}
106
107
108
109dof_id_type Pyramid::low_order_key (const unsigned int s) const
110{
111 libmesh_assert_less (s, this->n_sides());
112
113 switch (s)
114 {
115 case 0: // triangular face 1
116 case 1: // triangular face 2
117 case 2: // triangular face 3
118 case 3: // triangular face 4
119 return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
121 this->node_id(Pyramid5::side_nodes_map[s][2]));
122
123 case 4: // the quad face at z=0
124 return this->compute_key (this->node_id(Pyramid5::side_nodes_map[s][0]),
127 this->node_id(Pyramid5::side_nodes_map[s][3]));
128
129 default:
130 libmesh_error_msg("Invalid side s = " << s);
131 }
132}
133
135
136unsigned int Pyramid::local_side_node(unsigned int side,
137 unsigned int side_node) const
138{
139 libmesh_assert_less (side, this->n_sides());
140
141 // Never more than 4 nodes per side.
142 libmesh_assert_less(side_node, Pyramid5::nodes_per_side);
143
144 // Some sides have 3 nodes.
145 libmesh_assert(side == 4 || side_node < 3);
146
147 return Pyramid5::side_nodes_map[side][side_node];
148}
149
150
151
152unsigned int Pyramid::local_edge_node(unsigned int edge,
153 unsigned int edge_node) const
154{
155 libmesh_assert_less(edge, this->n_edges());
156 libmesh_assert_less(edge_node, Pyramid5::nodes_per_edge);
157
158 return Pyramid5::edge_nodes_map[edge][edge_node];
159}
160
161
162
163std::unique_ptr<Elem> Pyramid::side_ptr (const unsigned int i)
164{
165 libmesh_assert_less (i, this->n_sides());
166
167 // Return value
168 std::unique_ptr<Elem> face;
169
170 // Set up the type of element
171 switch (i)
172 {
173 case 0: // triangular face 1
174 case 1: // triangular face 2
175 case 2: // triangular face 3
176 case 3: // triangular face 4
177 {
178 face = std::make_unique<Tri3>();
179 break;
180 }
181 case 4: // the quad face at z=0
182 {
183 face = std::make_unique<Quad4>();
184 break;
185 }
186 default:
187 libmesh_error_msg("Invalid side i = " << i);
188 }
189
190 // Set the nodes
191 for (auto n : face->node_index_range())
192 face->set_node(n, this->node_ptr(Pyramid5::side_nodes_map[i][n]));
193
194 return face;
195}
196
197
198
199void Pyramid::side_ptr (std::unique_ptr<Elem> & side,
200 const unsigned int i)
201{
202 libmesh_assert_less (i, this->n_sides());
203
204 switch (i)
205 {
206 case 0: // triangular face 1
207 case 1: // triangular face 2
208 case 2: // triangular face 3
209 case 3: // triangular face 4
210 {
211 if (!side.get() || side->type() != TRI3)
212 {
213 side = this->side_ptr(i);
214 return;
215 }
216 break;
217 }
218
219 case 4: // the quad face at z=0
220 {
221 if (!side.get() || side->type() != QUAD4)
222 {
223 side = this->side_ptr(i);
224 return;
225 }
226 break;
227 }
228
229 default:
230 libmesh_error_msg("Invalid side i = " << i);
231 }
232
233 side->subdomain_id() = this->subdomain_id();
234
235 // Set the nodes
236 for (auto n : side->node_index_range())
237 side->set_node(n, this->node_ptr(Pyramid5::side_nodes_map[i][n]));
238}
239
240
241
242bool Pyramid::is_child_on_side(const unsigned int c,
243 const unsigned int s) const
244{
245 libmesh_assert_less (c, this->n_children());
246 libmesh_assert_less (s, this->n_sides());
247
248 for (unsigned int i = 0; i != 4; ++i)
249 if (Pyramid5::side_nodes_map[s][i] == c)
250 return true;
251 return false;
252}
253
254
255
256bool Pyramid::is_edge_on_side(const unsigned int e,
257 const unsigned int s) const
258{
259 libmesh_assert_less (e, this->n_edges());
260 libmesh_assert_less (s, this->n_sides());
261
262 return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
263}
264
265
266
267std::vector<unsigned int> Pyramid::sides_on_edge(const unsigned int e) const
268{
269 libmesh_assert_less (e, this->n_edges());
270 return {edge_sides_map[e][0], edge_sides_map[e][1]};
271}
272
273
274bool
276{
277 return (triple_product(this->point(1)-this->point(0),
278 this->point(3)-this->point(0),
279 this->point(4)-this->point(0)) < 0);
280}
281
282std::vector<unsigned int>
283Pyramid::edges_adjacent_to_node(const unsigned int n) const
284{
285 libmesh_assert_less(n, this->n_nodes());
286 if (this->is_vertex(n))
287 {
288 auto trim = (n < 4) ? 1 : 0;
289 return {std::begin(adjacent_edges_map[n]), std::end(adjacent_edges_map[n]) - trim};
290 }
291 else if (this->is_edge(n))
292 return {n - this->n_vertices()};
293
294 // Not a vertex or edge node, so must be one of the face nodes.
295 libmesh_assert(this->is_face(n));
296 return {};
297}
298
299unsigned int Pyramid::local_singular_node(const Point & p, const Real tol) const
300{
301 return this->node_ref(4).absolute_fuzzy_equals(p, tol) ? 4 : invalid_uint;
302}
303
304
306 const Real eps) const
307{
308 const Real & xi = p(0);
309 const Real & eta = p(1);
310 const Real & zeta = p(2);
311
312 // Check that the point is on the same side of all the faces
313 // by testing whether:
314 //
315 // n_i.(x - x_i) <= 0
316 //
317 // for each i, where:
318 // n_i is the outward normal of face i,
319 // x_i is a point on face i.
320 return ((-eta - 1. + zeta <= 0.+eps) &&
321 ( xi - 1. + zeta <= 0.+eps) &&
322 ( eta - 1. + zeta <= 0.+eps) &&
323 ( -xi - 1. + zeta <= 0.+eps) &&
324 ( zeta >= 0.-eps));
325}
326
327
328
329std::pair<Real, Real> Pyramid::qual_bounds (const ElemQuality) const
330{
331 // No suggested ranges have yet been established for any of the
332 // metrics Quality::valid() lists for pyramids, so we always return
333 // the (-1, -1) sentinel.
334 libmesh_warning("Invalid quality measure chosen.");
335 return std::make_pair(Real(-1), Real(-1));
336}
337
338
339} // namespace libMesh
const Point & point(const unsigned int i) const
Definition elem.h:2583
const Node & node_ref(const unsigned int i) const
Definition elem.h:2659
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
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 edge_nodes_map[num_edges][nodes_per_edge]
This maps the node of the edge to element node numbers.
static const int nodes_per_side
static const int nodes_per_edge
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 edge_sides_map[8][2]
This maps each edge to the sides that contain said edge.
virtual unsigned int n_nodes() const override
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const override
virtual unsigned int n_children() const override
virtual std::vector< unsigned int > sides_on_edge(const unsigned int e) const override final
virtual unsigned int n_sides() const override
virtual dof_id_type low_order_key(const unsigned int s) const override
virtual unsigned int n_edges() const override
virtual bool is_flipped() const override final
unsigned int local_singular_node(const Point &p, const Real tol=TOLERANCE *TOLERANCE) const override final
virtual std::vector< unsigned int > edges_adjacent_to_node(const unsigned int n) const override
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
virtual std::pair< Real, Real > qual_bounds(const ElemQuality q) const override
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override
static const unsigned int adjacent_edges_map[5][4]
This maps the node to the 3 or 4 edge ids adjacent to the node.
static const Real _master_points[18][3]
Master element node locations.
static const int num_edges
static const int num_sides
Geometric constants for all Pyramids.
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const override
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const override
virtual unsigned int n_vertices() const override
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const override final
static const int num_children
bool absolute_fuzzy_equals(const TypeVector< T > &rhs, Real tol=TOLERANCE) const
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