libMesh
cell_prism.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_prism.h"
23 #include "libmesh/cell_prism6.h"
24 #include "libmesh/face_quad4.h"
25 #include "libmesh/face_tri3.h"
26 
27 namespace libMesh
28 {
29 
30 
31 // ------------------------------------------------------------
32 // Prism class static member initializations
33 const int Prism::num_sides;
34 const int Prism::num_edges;
35 const int Prism::num_children;
36 
37 const 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 
59 const 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 
72 const 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
85 dof_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]),
94  this->node_id(Prism6::side_nodes_map[s][1]),
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 
112 dof_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 
139 unsigned 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 
155 unsigned 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 
166 std::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 
201 void 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 
245 bool 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 
259 bool 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 
270 std::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 
279 unsigned 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 
289 bool
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 
298 std::vector<unsigned int>
299 Prism::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 
334 const 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 
343 const 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 
351 const 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
static const unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
Definition: cell_prism6.h:172
static const int num_edges
Definition: cell_prism.h:74
virtual dof_id_type low_order_key(const unsigned int s) const override
Definition: cell_prism.C:112
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
virtual unsigned int n_nodes() const override
Definition: cell_prism.h:81
virtual bool is_face(const unsigned int i) const =0
virtual dof_id_type key() const
Definition: elem.C:753
virtual unsigned int n_sides() const override final
Definition: cell_prism.h:86
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
Definition: cell_prism.C:166
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const override
Definition: cell_prism.C:139
The libMesh namespace provides an interface to certain functionality in the library.
static const int num_children
Definition: cell_prism.h:75
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 n_children() const override final
Definition: cell_prism.h:106
virtual bool is_flipped() const override final
Definition: cell_prism.C:290
T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
Definition: type_vector.h:1029
static const Real _master_points[18][3]
Master element node locations.
Definition: cell_prism.h:214
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 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
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 std::vector< unsigned int > sides_on_edge(const unsigned int e) const override final
Definition: cell_prism.C:270
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const override
Definition: cell_prism.C:155
libmesh_assert(ctx)
virtual unsigned int n_vertices() const override final
Definition: cell_prism.h:91
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const override final
Definition: cell_prism.C:259
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 int nodes_per_side
Definition: cell_prism6.h:165
virtual unsigned int opposite_side(const unsigned int s) const override final
Definition: cell_prism.C:279
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 final
Definition: cell_prism.h:96
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 bool is_vertex(const unsigned int i) const =0
static const int num_sides
Geometric constants for all Prisms.
Definition: cell_prism.h:73
static const int nodes_per_edge
Definition: cell_prism6.h:166
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const override final
Definition: cell_prism.C:317
static const unsigned int edge_nodes_map[num_edges][nodes_per_edge]
This maps the node of the edge to element node numbers.
Definition: cell_prism6.h:183
static dof_id_type compute_key(dof_id_type n0)
Definition: elem.h:3294
virtual std::vector< unsigned int > edges_adjacent_to_node(const unsigned int n) const override
Definition: cell_prism.C:299
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.
Definition: cell_prism6.h:177
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
uint8_t dof_id_type
Definition: id_types.h:67
bool is_internal(const unsigned int i) const
Definition: elem.C:3566