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