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