libMesh
Loading...
Searching...
No Matches
cell_pyramid18.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_pyramid18.h"
21#include "libmesh/edge_edge3.h"
22#include "libmesh/face_tri7.h"
23#include "libmesh/face_quad9.h"
24#include "libmesh/enum_io_package.h"
25#include "libmesh/enum_order.h"
26
27namespace libMesh
28{
29
30
31
32
33// ------------------------------------------------------------
34// Pyramid18 class static member initializations
35const int Pyramid18::num_nodes;
38
40 {
41 {0, 1, 4, 5, 10, 9, 14, 99, 99}, // Side 0 (front)
42 {1, 2, 4, 6, 11, 10, 15, 99, 99}, // Side 1 (right)
43 {2, 3, 4, 7, 12, 11, 16, 99, 99}, // Side 2 (back)
44 {3, 0, 4, 8, 9, 12, 17, 99, 99}, // Side 3 (left)
45 {0, 3, 2, 1, 8, 7, 6, 5, 13} // Side 4 (base)
46 };
47
49 {
50 {0, 1, 5}, // Edge 0
51 {1, 2, 6}, // Edge 1
52 {2, 3, 7}, // Edge 2
53 {0, 3, 8}, // Edge 3
54 {0, 4, 9}, // Edge 4
55 {1, 4, 10}, // Edge 5
56 {2, 4, 11}, // Edge 6
57 {3, 4, 12} // Edge 7
58 };
59
60// ------------------------------------------------------------
61// Pyramid18 class member functions
62
63bool Pyramid18::is_vertex(const unsigned int i) const
64{
65 if (i < 5)
66 return true;
67 return false;
68}
69
70
71
72bool Pyramid18::is_edge(const unsigned int i) const
73{
74 if (i < 5)
75 return false;
76 if (i > 12)
77 return false;
78 return true;
79}
80
81
82
83bool Pyramid18::is_face(const unsigned int i) const
84{
85 if (i > 12)
86 return true;
87 return false;
88}
89
90
91
92bool Pyramid18::is_node_on_side(const unsigned int n,
93 const unsigned int s) const
94{
95 libmesh_assert_less (s, n_sides());
96 return std::find(std::begin(side_nodes_map[s]),
97 std::end(side_nodes_map[s]),
98 n) != std::end(side_nodes_map[s]);
99}
100
101std::vector<unsigned>
102Pyramid18::nodes_on_side(const unsigned int s) const
103{
104 libmesh_assert_less(s, n_sides());
105 auto trim = (s == 4) ? 0 : 2;
106 return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
107}
108
109std::vector<unsigned>
110Pyramid18::nodes_on_edge(const unsigned int e) const
111{
112 libmesh_assert_less(e, n_edges());
113 return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
114}
115
116bool Pyramid18::is_node_on_edge(const unsigned int n,
117 const unsigned int e) const
118{
119 libmesh_assert_less (e, n_edges());
120 return std::find(std::begin(edge_nodes_map[e]),
121 std::end(edge_nodes_map[e]),
122 n) != std::end(edge_nodes_map[e]);
123}
124
125
126
128{
129 // TODO: If the base is a parallelogram and all the triangular faces are planar,
130 // the map should be linear, but I need to test this theory...
131 return false;
132}
133
134
135
137{
138 return THIRD;
139}
140
141
142
143dof_id_type Pyramid18::key (const unsigned int s) const
144{
145 libmesh_assert_less (s, this->n_sides());
146
147 switch (s)
148 {
149 case 0: // triangular face 1
150 case 1: // triangular face 2
151 case 2: // triangular face 3
152 case 3: // triangular face 4
153 return this->compute_key (this->node_id(s+14));
154
155 case 4: // the quad face at z=0
156 return this->compute_key (this->node_id(13));
157
158 default:
159 libmesh_error_msg("Invalid side s = " << s);
160 }
161}
162
163
164
165unsigned int Pyramid18::local_side_node(unsigned int side,
166 unsigned int side_node) const
167{
168 libmesh_assert_less (side, this->n_sides());
169
170 // Never more than 9 nodes per side.
171 libmesh_assert_less(side_node, Pyramid18::nodes_per_side);
172
173 // Some sides have 7 nodes.
174 libmesh_assert(side == 4 || side_node < 7);
175
176 return Pyramid18::side_nodes_map[side][side_node];
177}
178
179
180
181unsigned int Pyramid18::local_edge_node(unsigned int edge,
182 unsigned int edge_node) const
183{
184 libmesh_assert_less(edge, this->n_edges());
185 libmesh_assert_less(edge_node, Pyramid18::nodes_per_edge);
186
187 return Pyramid18::edge_nodes_map[edge][edge_node];
188}
189
190
191
192std::unique_ptr<Elem> Pyramid18::build_side_ptr (const unsigned int i)
193{
194 libmesh_assert_less (i, this->n_sides());
195
196 std::unique_ptr<Elem> face;
197
198 switch (i)
199 {
200 case 0: // triangular face 1
201 case 1: // triangular face 2
202 case 2: // triangular face 3
203 case 3: // triangular face 4
204 {
205 face = std::make_unique<Tri7>();
206 break;
207 }
208 case 4: // the quad face at z=0
209 {
210 face = std::make_unique<Quad9>();
211 break;
212 }
213 default:
214 libmesh_error_msg("Invalid side i = " << i);
215 }
216
217 // Set the nodes
218 for (auto n : face->node_index_range())
219 face->set_node(n, this->node_ptr(Pyramid18::side_nodes_map[i][n]));
220
221 face->set_interior_parent(this);
222 face->inherit_data_from(*this);
223
224 return face;
225}
226
227
228
229void Pyramid18::build_side_ptr (std::unique_ptr<Elem> & side,
230 const unsigned int i)
231{
232 libmesh_assert_less (i, this->n_sides());
233
234 switch (i)
235 {
236 case 0: // triangular face 1
237 case 1: // triangular face 2
238 case 2: // triangular face 3
239 case 3: // triangular face 4
240 {
241 if (!side.get() || side->type() != TRI7)
242 {
243 side = this->build_side_ptr(i);
244 return;
245 }
246 break;
247 }
248 case 4: // the quad face at z=0
249 {
250 if (!side.get() || side->type() != QUAD9)
251 {
252 side = this->build_side_ptr(i);
253 return;
254 }
255 break;
256 }
257 default:
258 libmesh_error_msg("Invalid side i = " << i);
259 }
260
261 side->inherit_data_from(*this);
262
263 // Set the nodes
264 for (auto n : side->node_index_range())
265 side->set_node(n, this->node_ptr(Pyramid18::side_nodes_map[i][n]));
266}
267
268
269
270std::unique_ptr<Elem> Pyramid18::build_edge_ptr (const unsigned int i)
271{
272 return this->simple_build_edge_ptr<Edge3,Pyramid18>(i);
273}
274
275
276
277void Pyramid18::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
278{
279 this->simple_build_edge_ptr<Pyramid18>(edge, i, EDGE3);
280}
281
282
283
284void Pyramid18::connectivity(const unsigned int libmesh_dbg_var(sc),
285 const IOPackage iop,
286 std::vector<dof_id_type> & /*conn*/) const
287{
289 libmesh_assert_less (sc, this->n_sub_elem());
290 libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
291
292 switch (iop)
293 {
294 case TECPLOT:
295 {
296 // TODO
297 libmesh_not_implemented();
298 }
299
300 case VTK:
301 {
302 // TODO
303 libmesh_not_implemented();
304 }
305
306 default:
307 libmesh_error_msg("Unsupported IO package " << iop);
308 }
309}
310
311
312
313unsigned int Pyramid18::n_second_order_adjacent_vertices (const unsigned int n) const
314{
315 switch (n)
316 {
317 case 5:
318 case 6:
319 case 7:
320 case 8:
321 case 9:
322 case 10:
323 case 11:
324 case 12:
325 return 2;
326
327 case 13:
328 return 4;
329
330 case 14:
331 case 15:
332 case 16:
333 case 17:
334 return 3;
335
336 default:
337 libmesh_error_msg("Invalid node n = " << n);
338 }
339}
340
341
342unsigned short int Pyramid18::second_order_adjacent_vertex (const unsigned int n,
343 const unsigned int v) const
344{
345 libmesh_assert_greater_equal (n, this->n_vertices());
346 libmesh_assert_less (n, this->n_nodes());
347
348 switch (n)
349 {
350 case 5:
351 case 6:
352 case 7:
353 case 8:
354 case 9:
355 case 10:
356 case 11:
357 case 12:
358 {
359 libmesh_assert_less (v, 2);
360
361 // This is the analog of the static, const arrays
362 // {Hex,Prism,Tet10}::_second_order_adjacent_vertices
363 // defined in the respective source files... possibly treat
364 // this similarly once the Pyramid13 has been added?
365 constexpr unsigned short node_list[8][2] =
366 {
367 {0,1},
368 {1,2},
369 {2,3},
370 {0,3},
371 {0,4},
372 {1,4},
373 {2,4},
374 {3,4}
375 };
376
377 return node_list[n-5][v];
378 }
379
380 // mid-face node on bottom
381 case 13:
382 {
383 libmesh_assert_less (v, 4);
384
385 // The vertex nodes surrounding node 13 are 0, 1, 2, and 3.
386 // Thus, the v'th node is simply = v.
387 return cast_int<unsigned short>(v);
388 }
389
390 // mid-face nodes on triangles
391 case 14:
392 case 15:
393 case 16:
394 case 17:
395 {
396 libmesh_assert_less (v, 3);
397
398 constexpr unsigned short node_list[4][3] =
399 {
400 {0,1,4},
401 {1,2,4},
402 {2,3,4},
403 {0,3,4}
404 };
405
406 return node_list[n-14][v];
407 }
408
409 default:
410 libmesh_error_msg("Invalid n = " << n);
411
412 }
413}
414
415
416
417void Pyramid18::permute(unsigned int perm_num)
418{
419 libmesh_assert_less (perm_num, 4);
420
421 for (unsigned int i = 0; i != perm_num; ++i)
422 {
423 swap4nodes(0,1,2,3);
424 swap4nodes(5,6,7,8);
425 swap4nodes(9,10,11,12);
426 swap4nodes(14,15,16,17);
427 swap4neighbors(0,1,2,3);
428 }
429}
430
431
432void Pyramid18::flip(BoundaryInfo * boundary_info)
433{
434 libmesh_assert(boundary_info);
435
436 swap2nodes(0,1);
437 swap2nodes(2,3);
438 swap2nodes(6,8);
439 swap2nodes(9,10);
440 swap2nodes(11,12);
441 swap2nodes(15,17);
442 swap2neighbors(1,3);
443 swap2boundarysides(1,3,boundary_info);
444 swap2boundaryedges(1,3,boundary_info);
445 swap2boundaryedges(4,5,boundary_info);
446 swap2boundaryedges(6,7,boundary_info);
447}
448
449
450unsigned int Pyramid18::center_node_on_side(const unsigned short side) const
451{
452 libmesh_assert_less (side, Pyramid18::num_sides);
453 return side == 4 ? 13 : side+14;
454}
455
456
457ElemType Pyramid18::side_type (const unsigned int s) const
458{
459 libmesh_assert_less (s, 5);
460 if (s < 4)
461 return TRI7;
462 return QUAD9;
463}
464
465
466} // namespace libMesh
The BoundaryInfo class contains information relevant to boundary conditions including storing faces,...
void swap4nodes(unsigned int n1, unsigned int n2, unsigned int n3, unsigned int n4)
Swaps four node_ptrs, "rotating" them.
Definition elem.h:2152
void swap2nodes(unsigned int n1, unsigned int n2)
Swaps two node_ptrs.
Definition elem.h:2101
Node ** _nodes
Pointers to the nodes we are connected to.
Definition elem.h:2254
void swap2neighbors(unsigned int n1, unsigned int n2)
Swaps two neighbor_ptrs.
Definition elem.h:2111
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:3579
static dof_id_type compute_key(dof_id_type n0)
Definition elem.h:3311
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:3595
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2484
void swap4neighbors(unsigned int n1, unsigned int n2, unsigned int n3, unsigned int n4)
Swaps four neighbor_ptrs, "rotating" them.
Definition elem.h:2162
virtual void connectivity(const unsigned int sc, const IOPackage iop, std::vector< dof_id_type > &conn) const override
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const override
static const int nodes_per_edge
virtual void permute(unsigned int perm_num) override final
Permutes the element (by swapping node and neighbor pointers) according to the specified index.
virtual void flip(BoundaryInfo *) override final
Flips the element (by swapping node and neighbor pointers) to have a mapping Jacobian of opposite sig...
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i) override
Builds a QUAD9 or TRI7 coincident with face i.
virtual unsigned int n_second_order_adjacent_vertices(const unsigned int n) const override
virtual unsigned short int second_order_adjacent_vertex(const unsigned int n, const unsigned int v) const override
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const override
virtual std::vector< unsigned int > nodes_on_side(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_nodes() const override
virtual bool has_affine_map() const override
static const int nodes_per_side
virtual bool is_edge(const unsigned int i) const override
virtual dof_id_type key() const
Don't hide Pyramid::key() defined in the base class.
Definition elem.C:738
virtual unsigned int n_sub_elem() const override
FIXME: we don't yet have a refinement pattern for pyramids...
virtual bool is_face(const unsigned int i) const override
virtual bool is_node_on_edge(const unsigned int n, const unsigned int e) const override
virtual bool is_vertex(const unsigned int i) const override
static const int num_nodes
Geometric constants for Pyramid18.
static const 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_edge_ptr(const unsigned int i) override
Builds a EDGE3 coincident with edge i.
static const unsigned int side_nodes_map[num_sides][nodes_per_side]
This maps the node of the side to element node numbers.
virtual std::vector< unsigned int > nodes_on_edge(const unsigned int e) const override
virtual Order default_order() const override
ElemType side_type(const unsigned int s) const override final
unsigned int center_node_on_side(const unsigned short side) const override final
virtual unsigned int n_sides() const override
virtual unsigned int n_edges() const override
static const int num_edges
static const int num_sides
Geometric constants for all Pyramids.
virtual unsigned int n_vertices() const override
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,...
ElemType
Defines an enum for geometric element types.
libmesh_assert(ctx)
uint8_t dof_id_type
Definition id_types.h:67