-
Notifications
You must be signed in to change notification settings - Fork 292
/
Copy pathcell_pyramid5.C
354 lines (286 loc) · 8.57 KB
/
cell_pyramid5.C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
// The libMesh Finite Element Library.
// Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Local includes
#include "libmesh/side.h"
#include "libmesh/cell_pyramid5.h"
#include "libmesh/edge_edge2.h"
#include "libmesh/face_tri3.h"
#include "libmesh/face_quad4.h"
#include "libmesh/enum_io_package.h"
#include "libmesh/enum_order.h"
#include "libmesh/cell_hex8.h"
namespace libMesh
{
// ------------------------------------------------------------
// Pyramid5 class static member initializations
const int Pyramid5::num_nodes;
const int Pyramid5::nodes_per_side;
const int Pyramid5::nodes_per_edge;
const unsigned int Pyramid5::side_nodes_map[Pyramid5::num_sides][Pyramid5::nodes_per_side] =
{
{0, 1, 4, 99}, // Side 0
{1, 2, 4, 99}, // Side 1
{2, 3, 4, 99}, // Side 2
{3, 0, 4, 99}, // Side 3
{0, 3, 2, 1} // Side 4
};
const unsigned int Pyramid5::edge_nodes_map[Pyramid5::num_edges][Pyramid5::nodes_per_edge] =
{
{0, 1}, // Edge 0
{1, 2}, // Edge 1
{2, 3}, // Edge 2
{0, 3}, // Edge 3
{0, 4}, // Edge 4
{1, 4}, // Edge 5
{2, 4}, // Edge 6
{3, 4} // Edge 7
};
// ------------------------------------------------------------
// Pyramid5 class member functions
bool Pyramid5::is_vertex(const unsigned int libmesh_dbg_var(n)) const
{
libmesh_assert_not_equal_to (n, invalid_uint);
return true;
}
bool Pyramid5::is_edge(const unsigned int) const
{
return false;
}
bool Pyramid5::is_face(const unsigned int) const
{
return false;
}
bool Pyramid5::is_node_on_side(const unsigned int n,
const unsigned int s) const
{
libmesh_assert_less (s, n_sides());
return std::find(std::begin(side_nodes_map[s]),
std::end(side_nodes_map[s]),
n) != std::end(side_nodes_map[s]);
}
std::vector<unsigned>
Pyramid5::nodes_on_side(const unsigned int s) const
{
libmesh_assert_less(s, n_sides());
auto trim = (s == 4) ? 0 : 1;
return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
}
std::vector<unsigned>
Pyramid5::nodes_on_edge(const unsigned int e) const
{
libmesh_assert_less(e, n_edges());
return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
}
bool Pyramid5::is_node_on_edge(const unsigned int n,
const unsigned int e) const
{
libmesh_assert_less (e, n_edges());
return std::find(std::begin(edge_nodes_map[e]),
std::end(edge_nodes_map[e]),
n) != std::end(edge_nodes_map[e]);
}
bool Pyramid5::has_affine_map() const
{
// Point v = this->point(3) - this->point(0);
// return (v.relative_fuzzy_equals(this->point(2) - this->point(1)));
return false;
}
Order Pyramid5::default_order() const
{
return FIRST;
}
std::unique_ptr<Elem> Pyramid5::build_side_ptr (const unsigned int i,
bool proxy)
{
libmesh_assert_less (i, this->n_sides());
std::unique_ptr<Elem> face;
if (proxy)
{
#ifdef LIBMESH_ENABLE_DEPRECATED
libmesh_deprecated();
switch (i)
{
case 0:
case 1:
case 2:
case 3:
{
face = std::make_unique<Side<Tri3,Pyramid5>>(this,i);
break;
}
case 4:
{
face = std::make_unique<Side<Quad4,Pyramid5>>(this,i);
break;
}
default:
libmesh_error_msg("Invalid side i = " << i);
}
#else
libmesh_error();
#endif // LIBMESH_ENABLE_DEPRECATED
}
else
{
switch (i)
{
case 0: // triangular face 1
case 1: // triangular face 2
case 2: // triangular face 3
case 3: // triangular face 4
{
face = std::make_unique<Tri3>();
break;
}
case 4: // the quad face at z=0
{
face = std::make_unique<Quad4>();
break;
}
default:
libmesh_error_msg("Invalid side i = " << i);
}
// Set the nodes
for (auto n : face->node_index_range())
face->set_node(n) = this->node_ptr(Pyramid5::side_nodes_map[i][n]);
}
#ifdef LIBMESH_ENABLE_DEPRECATED
if (!proxy) // proxy sides used to leave parent() set
#endif
face->set_parent(nullptr);
face->set_interior_parent(this);
face->subdomain_id() = this->subdomain_id();
face->set_mapping_type(this->mapping_type());
#ifdef LIBMESH_ENABLE_AMR
face->set_p_level(this->p_level());
#endif
return face;
}
void Pyramid5::build_side_ptr (std::unique_ptr<Elem> & side,
const unsigned int i)
{
this->side_ptr(side, i);
side->set_interior_parent(this);
side->subdomain_id() = this->subdomain_id();
side->set_mapping_type(this->mapping_type());
#ifdef LIBMESH_ENABLE_AMR
side->set_p_level(this->p_level());
#endif
}
std::unique_ptr<Elem> Pyramid5::build_edge_ptr (const unsigned int i)
{
return this->simple_build_edge_ptr<Edge2,Pyramid5>(i);
}
void Pyramid5::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
{
this->simple_build_edge_ptr<Pyramid5>(edge, i, EDGE2);
}
void Pyramid5::connectivity(const unsigned int libmesh_dbg_var(sc),
const IOPackage iop,
std::vector<dof_id_type> & conn) const
{
libmesh_assert(_nodes);
libmesh_assert_less (sc, this->n_sub_elem());
libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
switch (iop)
{
case TECPLOT:
{
conn.resize(8);
conn[0] = this->node_id(0)+1;
conn[1] = this->node_id(1)+1;
conn[2] = this->node_id(2)+1;
conn[3] = this->node_id(3)+1;
conn[4] = this->node_id(4)+1;
conn[5] = this->node_id(4)+1;
conn[6] = this->node_id(4)+1;
conn[7] = this->node_id(4)+1;
return;
}
case VTK:
{
conn.resize(5);
conn[0] = this->node_id(3);
conn[1] = this->node_id(2);
conn[2] = this->node_id(1);
conn[3] = this->node_id(0);
conn[4] = this->node_id(4);
return;
}
default:
libmesh_error_msg("Unsupported IO package " << iop);
}
}
Point Pyramid5::true_centroid () const
{
// Call Hex8 static helper function, passing 4 copies of the final
// vertex point, effectively treating the Pyramid as a degenerate
// hexahedron. In my testing, this still seems to give correct
// results.
return Hex8::centroid_from_points(
point(0), point(1), point(2), point(3),
point(4), point(4), point(4), point(4));
}
Real Pyramid5::volume () const
{
// The pyramid with a bilinear base has volume given by the
// formula in: "Calculation of the Volume of a General Hexahedron
// for Flow Predictions", AIAA Journal v.23, no.6, 1984, p.954-
Point
x0 = point(0), x1 = point(1), x2 = point(2),
x3 = point(3), x4 = point(4);
// Construct various edge and diagonal vectors.
Point v40 = x0 - x4;
Point v13 = x3 - x1;
Point v02 = x2 - x0;
Point v03 = x3 - x0;
Point v01 = x1 - x0;
// Finally, ready to return the volume!
return
triple_product(v40, v13, v02) / 6. +
triple_product(v02, v01, v03) / 12.;
}
BoundingBox
Pyramid5::loose_bounding_box () const
{
return Elem::loose_bounding_box();
}
void Pyramid5::permute(unsigned int perm_num)
{
libmesh_assert_less (perm_num, 4);
for (unsigned int i = 0; i != perm_num; ++i)
{
swap4nodes(0,1,2,3);
swap4neighbors(0,1,2,3);
}
}
void Pyramid5::flip(BoundaryInfo * boundary_info)
{
libmesh_assert(boundary_info);
swap2nodes(0,1);
swap2nodes(2,3);
swap2neighbors(1,3);
swap2boundarysides(1,3,boundary_info);
swap2boundaryedges(1,3,boundary_info);
swap2boundaryedges(4,5,boundary_info);
swap2boundaryedges(6,7,boundary_info);
}
ElemType Pyramid5::side_type (const unsigned int s) const
{
libmesh_assert_less (s, 5);
if (s < 4)
return TRI3;
return QUAD4;
}
} // namespace libMesh