libMesh
Loading...
Searching...
No Matches
cell_pyramid5.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// Local includes
20#include "libmesh/cell_pyramid5.h"
21#include "libmesh/edge_edge2.h"
22#include "libmesh/face_tri3.h"
23#include "libmesh/face_quad4.h"
24#include "libmesh/enum_io_package.h"
25#include "libmesh/enum_order.h"
26#include "libmesh/cell_hex8.h"
27
28namespace libMesh
29{
30
31
32
33
34// ------------------------------------------------------------
35// Pyramid5 class static member initializations
36const int Pyramid5::num_nodes;
39
40// ------------------------------------------------------------
41// Pyramid5 class member functions
42
43bool Pyramid5::is_vertex(const unsigned int libmesh_dbg_var(n)) const
44{
45 libmesh_assert_not_equal_to (n, invalid_uint);
46 return true;
47}
48
49bool Pyramid5::is_edge(const unsigned int) const
50{
51 return false;
52}
53
54bool Pyramid5::is_face(const unsigned int) const
55{
56 return false;
57}
58
59bool Pyramid5::is_node_on_side(const unsigned int n,
60 const unsigned int s) const
61{
62 libmesh_assert_less (s, n_sides());
63 return std::find(std::begin(side_nodes_map[s]),
64 std::end(side_nodes_map[s]),
65 n) != std::end(side_nodes_map[s]);
66}
67
68std::vector<unsigned>
69Pyramid5::nodes_on_side(const unsigned int s) const
70{
71 libmesh_assert_less(s, n_sides());
72 auto trim = (s == 4) ? 0 : 1;
73 return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
74}
75
76std::vector<unsigned>
77Pyramid5::nodes_on_edge(const unsigned int e) const
78{
79 libmesh_assert_less(e, n_edges());
80 return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
81}
82
83bool Pyramid5::is_node_on_edge(const unsigned int n,
84 const unsigned int e) const
85{
86 libmesh_assert_less (e, n_edges());
87 return std::find(std::begin(edge_nodes_map[e]),
88 std::end(edge_nodes_map[e]),
89 n) != std::end(edge_nodes_map[e]);
90}
91
92
93
95{
96 // Point v = this->point(3) - this->point(0);
97 // return (v.relative_fuzzy_equals(this->point(2) - this->point(1)));
98 return false;
99}
100
101
102
104{
105 return FIRST;
106}
107
108
109
110std::unique_ptr<Elem> Pyramid5::build_side_ptr (const unsigned int i)
111{
112 libmesh_assert_less (i, this->n_sides());
113
114 std::unique_ptr<Elem> face;
115
116 switch (i)
117 {
118 case 0: // triangular face 1
119 case 1: // triangular face 2
120 case 2: // triangular face 3
121 case 3: // triangular face 4
122 {
123 face = std::make_unique<Tri3>();
124 break;
125 }
126 case 4: // the quad face at z=0
127 {
128 face = std::make_unique<Quad4>();
129 break;
130 }
131 default:
132 libmesh_error_msg("Invalid side i = " << i);
133 }
134
135 // Set the nodes
136 for (auto n : face->node_index_range())
137 face->set_node(n, this->node_ptr(Pyramid5::side_nodes_map[i][n]));
138
139 face->set_interior_parent(this);
140 face->inherit_data_from(*this);
141
142 return face;
143}
144
145
146
147void Pyramid5::build_side_ptr (std::unique_ptr<Elem> & side,
148 const unsigned int i)
149{
150 this->side_ptr(side, i);
151 side->set_interior_parent(this);
152 side->inherit_data_from(*this);
153}
154
155
156
157std::unique_ptr<Elem> Pyramid5::build_edge_ptr (const unsigned int i)
158{
159 return this->simple_build_edge_ptr<Edge2,Pyramid5>(i);
160}
161
162
163
164void Pyramid5::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
165{
166 this->simple_build_edge_ptr<Pyramid5>(edge, i, EDGE2);
167}
168
169
170
171void Pyramid5::connectivity(const unsigned int libmesh_dbg_var(sc),
172 const IOPackage iop,
173 std::vector<dof_id_type> & conn) const
174{
176 libmesh_assert_less (sc, this->n_sub_elem());
177 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
178
179 switch (iop)
180 {
181 case TECPLOT:
182 {
183 conn.resize(8);
184 conn[0] = this->node_id(0)+1;
185 conn[1] = this->node_id(1)+1;
186 conn[2] = this->node_id(2)+1;
187 conn[3] = this->node_id(3)+1;
188 conn[4] = this->node_id(4)+1;
189 conn[5] = this->node_id(4)+1;
190 conn[6] = this->node_id(4)+1;
191 conn[7] = this->node_id(4)+1;
192 return;
193 }
194
195 case VTK:
196 {
197 conn.resize(5);
198 conn[0] = this->node_id(3);
199 conn[1] = this->node_id(2);
200 conn[2] = this->node_id(1);
201 conn[3] = this->node_id(0);
202 conn[4] = this->node_id(4);
203 return;
204 }
205
206 default:
207 libmesh_error_msg("Unsupported IO package " << iop);
208 }
209}
210
211
213{
214 // Call Hex8 static helper function, passing 4 copies of the final
215 // vertex point, effectively treating the Pyramid as a degenerate
216 // hexahedron. In my testing, this still seems to give correct
217 // results.
219 point(0), point(1), point(2), point(3),
220 point(4), point(4), point(4), point(4));
221}
222
223
224
226{
227 // This specialization is good for Lagrange mappings only in general
228 if (this->mapping_type() != LAGRANGE_MAP)
229 return this->Elem::volume();
230
231 // The pyramid with a bilinear base has volume given by the
232 // formula in: "Calculation of the Volume of a General Hexahedron
233 // for Flow Predictions", AIAA Journal v.23, no.6, 1984, p.954-
234 Point
235 x0 = point(0), x1 = point(1), x2 = point(2),
236 x3 = point(3), x4 = point(4);
237
238 // Construct various edge and diagonal vectors.
239 Point v40 = x0 - x4;
240 Point v13 = x3 - x1;
241 Point v02 = x2 - x0;
242 Point v03 = x3 - x0;
243 Point v01 = x1 - x0;
244
245 // Finally, ready to return the volume!
246 return
247 triple_product(v40, v13, v02) / 6. +
248 triple_product(v02, v01, v03) / 12.;
249}
250
256
257void Pyramid5::permute(unsigned int perm_num)
258{
259 libmesh_assert_less (perm_num, 4);
260
261 for (unsigned int i = 0; i != perm_num; ++i)
262 {
263 swap4nodes(0,1,2,3);
264 swap4neighbors(0,1,2,3);
265 }
266}
267
268
269void Pyramid5::flip(BoundaryInfo * boundary_info)
270{
271 libmesh_assert(boundary_info);
272
273 swap2nodes(0,1);
274 swap2nodes(2,3);
275 swap2neighbors(1,3);
276 swap2boundarysides(1,3,boundary_info);
277 swap2boundaryedges(1,3,boundary_info);
278 swap2boundaryedges(4,5,boundary_info);
279 swap2boundaryedges(6,7,boundary_info);
280}
281
282
283ElemType Pyramid5::side_type (const unsigned int s) const
284{
285 libmesh_assert_less (s, 5);
286 if (s < 4)
287 return TRI3;
288 return QUAD4;
289}
290
291
292Point
293Pyramid5::side_vertex_average_normal(const unsigned int s) const
294{
295 libmesh_assert_less (s, 5);
296 libmesh_assert_equal_to(this->mapping_type(), LAGRANGE_MAP);
297
298 switch (s)
299 {
300 case 0: // triangular face 1
301 case 1: // triangular face 2
302 case 2: // triangular face 3
303 case 3: // triangular face 4
304 {
305 const Point n1 = this->point(side_nodes_map[s][1]) -
306 this->point(side_nodes_map[s][0]);
307 const Point n2 = this->point(side_nodes_map[s][2]) -
308 this->point(side_nodes_map[s][1]);
309 const Point pointing_out = n1.cross(n2);
310 return pointing_out.unit();
311 }
312 case 4: // the quad face at z=0
313 {
314 // At the side vertex average, things simplify a bit
315 // We get the side "plane" normal at all vertices, then average them
316 Point normal;
317 Point current_edge = this->point(side_nodes_map[s][1]) -
318 this->point(side_nodes_map[s][0]);
319 for (auto i : make_range(4))
320 {
321 const Point next_edge = this->point(side_nodes_map[s][(i + 2) % 4]) -
322 this->point(side_nodes_map[s][(i + 1) % 4]);
323 const Point normal_at_vertex = current_edge.cross(next_edge);
324 normal += normal_at_vertex;
325 current_edge = next_edge;
326 }
327 normal /= 4;
328 return normal.unit();
329 }
330 default:
331 libmesh_error_msg("Invalid side s = " << s);
332 }
333}
334
335
336} // namespace libMesh
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
Defines a Cartesian bounding box by the two corner extremum.
void swap4nodes(unsigned int n1, unsigned int n2, unsigned int n3, unsigned int n4)
Swaps four node_ptrs, "rotating" them.
Definition elem.h:2273
virtual BoundingBox loose_bounding_box() const
Definition elem.C:3901
const Point & point(const unsigned int i) const
Definition elem.h:2583
void swap2nodes(unsigned int n1, unsigned int n2)
Swaps two node_ptrs.
Definition elem.h:2222
Node ** _nodes
Pointers to the nodes we are connected to.
Definition elem.h:2375
void swap2neighbors(unsigned int n1, unsigned int n2)
Swaps two neighbor_ptrs.
Definition elem.h:2232
void swap2boundarysides(unsigned short s1, unsigned short s2, BoundaryInfo *boundary_info) const
Swaps two sides in boundary_info, if it is non-null.
Definition elem.C:3982
ElemMappingType mapping_type() const
Definition elem.h:3258
virtual Real volume() const
Definition elem.C:3865
void swap2boundaryedges(unsigned short e1, unsigned short e2, BoundaryInfo *boundary_info) const
Swaps two edges in boundary_info, if it is non-null.
Definition elem.C:3998
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2605
void swap4neighbors(unsigned int n1, unsigned int n2, unsigned int n3, unsigned int n4)
Swaps four neighbor_ptrs, "rotating" them.
Definition elem.h:2283
static Point centroid_from_points(const Point &x0, const Point &x1, const Point &x2, const Point &x3, const Point &x4, const Point &x5, const Point &x6, const Point &x7)
Class static helper function that computes the centroid of a hexahedral region from a set of input po...
Definition cell_hex8.C:310
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:41
virtual std::vector< unsigned int > nodes_on_edge(const unsigned int e) const override
virtual void flip(BoundaryInfo *) override final
Flips the element (by swapping node and neighbor pointers) to have a mapping Jacobian of opposite sig...
static constexpr unsigned int edge_nodes_map[num_edges][nodes_per_edge]
This maps the node of the edge to element node numbers.
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i) override
Builds a QUAD4 or TRI3 built coincident with face i.
virtual bool is_vertex(const unsigned int i) const override
virtual bool is_edge(const unsigned int i) const override
virtual std::unique_ptr< Elem > build_edge_ptr(const unsigned int i) override
Builds a EDGE2 built coincident with edge i.
virtual Point true_centroid() const override
We compute the centroid of the Pyramid by treating it as a degenerate Hex8 element.
static const int num_nodes
Geometric constants for Pyramid5.
virtual void permute(unsigned int perm_num) override final
Permutes the element (by swapping node and neighbor pointers) according to the specified index.
virtual BoundingBox loose_bounding_box() const override
Builds a bounding box out of the nodal positions.
static const int nodes_per_side
virtual Order default_order() const override
virtual bool is_face(const unsigned int i) const override
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
virtual std::vector< unsigned int > nodes_on_side(const unsigned int s) const override
virtual Real volume() const override
Specialization for computing the volume of a pyramid.
virtual unsigned int n_sub_elem() const override
ElemType side_type(const unsigned int s) const override final
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
virtual Point side_vertex_average_normal(const unsigned int s) const override final
static const int nodes_per_edge
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
static constexpr unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
virtual bool has_affine_map() const override
virtual unsigned int n_sides() const override
virtual unsigned int n_edges() const override
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
LIBMESH_DEVICE_INLINE TypeVector< T > unit() const
The libMesh namespace provides an interface to certain functionality in the library.
IOPackage
libMesh interfaces with several different software packages for the purposes of creating,...
LIBMESH_DEVICE_INLINE T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
ElemType
Defines an enum for geometric element types.
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
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176