libMesh
Loading...
Searching...
No Matches
cell_hex.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// C++ includes
20#include <algorithm> // for std::min, std::max
21
22// Local includes
23#include "libmesh/cell_hex.h"
24#include "libmesh/cell_hex8.h"
25#include "libmesh/face_quad4.h"
26#include "libmesh/enum_elem_quality.h"
27#include "libmesh/tensor_value.h"
28
29#include <array>
30
31namespace libMesh
32{
33
34
35
36// ------------------------------------------------------------
37// Hex class static member initializations
38const int Hex::num_sides;
39const int Hex::num_edges;
40const int Hex::num_children;
41
42const Real Hex::_master_points[27][3] =
43 {
44 {-1, -1, -1},
45 {1, -1, -1},
46 {1, 1, -1},
47 {-1, 1, -1},
48 {-1, -1, 1},
49 {1, -1, 1},
50 {1, 1, 1},
51 {-1, 1, 1},
52 {0, -1, -1},
53 {1, 0, -1},
54 {0, 1, -1},
55 {-1, 0, -1},
56 {-1, -1, 0},
57 {1, -1, 0},
58 {1, 1, 0},
59 {-1, 1, 0},
60 {0, -1, 1},
61 {1, 0, 1},
62 {0, 1, 1},
63 {-1, 0, 1},
64 {0, 0, -1},
65 {0, -1, 0},
66 {1, 0, 0},
67 {0, 1, 0},
68 {-1, 0, 0},
69 {0, 0, 1}
70 };
71
72const unsigned int Hex::edge_sides_map[12][2] =
73 {
74 {0, 1}, // Edge 0
75 {0, 2}, // Edge 1
76 {0, 3}, // Edge 2
77 {0, 4}, // Edge 3
78 {1, 4}, // Edge 4
79 {1, 2}, // Edge 5
80 {2, 3}, // Edge 6
81 {3, 4}, // Edge 7
82 {1, 5}, // Edge 8
83 {2, 5}, // Edge 9
84 {3, 5}, // Edge 10
85 {4, 5} // Edge 11
86 };
87
88const unsigned int Hex::adjacent_edges_map[/*num_vertices*/8][/*n_adjacent_edges*/3] =
89 {
90 {0, 3, 4}, // Edges adjacent to node 0
91 {0, 1, 5}, // Edges adjacent to node 1
92 {1, 2, 6}, // Edges adjacent to node 2
93 {2, 3, 7}, // Edges adjacent to node 3
94 {4, 8, 11}, // Edges adjacent to node 4
95 {5, 8, 9}, // Edges adjacent to node 5
96 {6, 9, 10}, // Edges adjacent to node 6
97 {7, 10, 11} // Edges adjacent to node 7
98 };
99
100// ------------------------------------------------------------
101// Hex class member functions
102dof_id_type Hex::key (const unsigned int s) const
103{
104 libmesh_assert_less (s, this->n_sides());
105
106 return this->compute_key(this->node_id(Hex8::side_nodes_map[s][0]),
107 this->node_id(Hex8::side_nodes_map[s][1]),
108 this->node_id(Hex8::side_nodes_map[s][2]),
109 this->node_id(Hex8::side_nodes_map[s][3]));
110}
111
112
113
114dof_id_type Hex::low_order_key (const unsigned int s) const
115{
116 libmesh_assert_less (s, this->n_sides());
117
118 return this->compute_key(this->node_id(Hex8::side_nodes_map[s][0]),
119 this->node_id(Hex8::side_nodes_map[s][1]),
120 this->node_id(Hex8::side_nodes_map[s][2]),
121 this->node_id(Hex8::side_nodes_map[s][3]));
122}
123
124
125
126unsigned int Hex::local_side_node(unsigned int side,
127 unsigned int side_node) const
128{
129 libmesh_assert_less (side, this->n_sides());
130 libmesh_assert_less (side_node, Hex8::nodes_per_side);
131
132 return Hex8::side_nodes_map[side][side_node];
133}
134
135
136
137unsigned int Hex::local_edge_node(unsigned int edge,
138 unsigned int edge_node) const
139{
140 libmesh_assert_less (edge, this->n_edges());
141 libmesh_assert_less (edge_node, Hex8::nodes_per_edge);
142
143 return Hex8::edge_nodes_map[edge][edge_node];
144}
145
146
147
148std::unique_ptr<Elem> Hex::side_ptr (const unsigned int i)
149{
150 libmesh_assert_less (i, this->n_sides());
151
152 std::unique_ptr<Elem> face = std::make_unique<Quad4>();
153
154 for (auto n : face->node_index_range())
155 face->set_node(n, this->node_ptr(Hex8::side_nodes_map[i][n]));
156
157 return face;
158}
159
160
161
162void Hex::side_ptr (std::unique_ptr<Elem> & side,
163 const unsigned int i)
164{
165 this->simple_side_ptr<Hex,Hex8>(side, i, QUAD4);
166}
167
168
169
170bool Hex::is_child_on_side(const unsigned int c,
171 const unsigned int s) const
172{
173 libmesh_assert_less (c, this->n_children());
174 libmesh_assert_less (s, this->n_sides());
175
176 // This array maps the Hex8 node numbering to the Hex8 child
177 // numbering. I.e.
178 // node 6 touches child 7, and
179 // node 7 touches child 6, etc.
180 const unsigned int node_child_map[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
181
182 for (unsigned int i = 0; i != 4; ++i)
183 if (node_child_map[Hex8::side_nodes_map[s][i]] == c)
184 return true;
185
186 return false;
187}
188
189
190
191bool Hex::is_edge_on_side(const unsigned int e,
192 const unsigned int s) const
193{
194 libmesh_assert_less (e, this->n_edges());
195 libmesh_assert_less (s, this->n_sides());
196
197 return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
198}
199
200
201
202std::vector<unsigned int> Hex::sides_on_edge(const unsigned int e) const
203{
204 libmesh_assert_less(e, this->n_edges());
205
206 return {edge_sides_map[e][0], edge_sides_map[e][1]};
207}
208
209
210
211unsigned int Hex::opposite_side(const unsigned int side_in) const
212{
213 libmesh_assert_less (side_in, 6);
214 static const unsigned char hex_opposites[6] = {5, 3, 4, 1, 2, 0};
215 return hex_opposites[side_in];
216}
217
218
219
220unsigned int Hex::opposite_node(const unsigned int node_in,
221 const unsigned int side_in) const
222{
223 libmesh_assert_less (node_in, 26);
224 libmesh_assert_less (node_in, this->n_nodes());
225 libmesh_assert_less (side_in, this->n_sides());
226 libmesh_assert(this->is_node_on_side(node_in, side_in));
227
228 static const unsigned char side05_nodes_map[] =
229 {4, 5, 6, 7, 0, 1, 2, 3, 16, 17, 18, 19, 255, 255, 255, 255, 8, 9, 10, 11, 25, 255, 255, 255, 255, 20};
230 static const unsigned char side13_nodes_map[] =
231 {3, 2, 1, 0, 7, 6, 5, 4, 10, 255, 8, 255, 15, 14, 13, 12, 18, 255, 16, 255, 255, 23, 255, 21, 255, 255};
232 static const unsigned char side24_nodes_map[] =
233 {1, 0, 3, 2, 5, 4, 7, 6, 255, 11, 255, 9, 13, 12, 15, 14, 255, 19, 255, 17, 255, 255, 24, 255, 22, 255};
234
235 switch (side_in)
236 {
237 case 0:
238 case 5:
239 return side05_nodes_map[node_in];
240 case 1:
241 case 3:
242 return side13_nodes_map[node_in];
243 case 2:
244 case 4:
245 return side24_nodes_map[node_in];
246 default:
247 libmesh_error_msg("Unsupported side_in = " << side_in);
248 }
249}
250
251
252
253bool
255{
256 return (triple_product(this->point(1)-this->point(0),
257 this->point(3)-this->point(0),
258 this->point(4)-this->point(0)) < 0);
259}
260
261
262std::vector<unsigned int>
263Hex::edges_adjacent_to_node(const unsigned int n) const
264{
265 libmesh_assert_less(n, this->n_nodes());
266
267 // For vertices, we use the Hex::adjacent_edges_map, otherwise each
268 // of the mid-edge nodes is adjacent only to the edge it is on, and
269 // face/internal nodes are not adjacent to any edge.
270 if (this->is_vertex(n))
271 return {std::begin(adjacent_edges_map[n]), std::end(adjacent_edges_map[n])};
272 else if (this->is_edge(n))
273 return {n - this->n_vertices()};
274
275 libmesh_assert(this->is_face(n) || this->is_internal(n));
276 return {};
277}
278
279
281{
282 switch (q)
283 {
284
285#if LIBMESH_DIM >= 3
290 case DIAGONAL:
291 {
292 // Diagonal between node 0 and node 6
293 const Real d06 = this->length(0,6);
294
295 // Diagonal between node 3 and node 5
296 const Real d35 = this->length(3,5);
297
298 // Diagonal between node 1 and node 7
299 const Real d17 = this->length(1,7);
300
301 // Diagonal between node 2 and node 4
302 const Real d24 = this->length(2,4);
303
304 // Find the biggest and smallest diagonals
305 const Real min = std::min(d06, std::min(d35, std::min(d17, d24)));
306 const Real max = std::max(d06, std::max(d35, std::max(d17, d24)));
307
308 libmesh_assert_not_equal_to (max, 0.0);
309
310 return min / max;
311
312 break;
313 }
314
319 case TAPER:
320 {
321
325 const Real d01 = this->length(0,1);
326 const Real d12 = this->length(1,2);
327 const Real d23 = this->length(2,3);
328 const Real d03 = this->length(0,3);
329 const Real d45 = this->length(4,5);
330 const Real d56 = this->length(5,6);
331 const Real d67 = this->length(6,7);
332 const Real d47 = this->length(4,7);
333 const Real d04 = this->length(0,4);
334 const Real d15 = this->length(1,5);
335 const Real d37 = this->length(3,7);
336 const Real d26 = this->length(2,6);
337
338 std::vector<Real> edge_ratios(12);
339 // Front
340 edge_ratios[0] = std::min(d01, d45) / std::max(d01, d45);
341 edge_ratios[1] = std::min(d04, d15) / std::max(d04, d15);
342
343 // Right
344 edge_ratios[2] = std::min(d15, d26) / std::max(d15, d26);
345 edge_ratios[3] = std::min(d12, d56) / std::max(d12, d56);
346
347 // Back
348 edge_ratios[4] = std::min(d67, d23) / std::max(d67, d23);
349 edge_ratios[5] = std::min(d26, d37) / std::max(d26, d37);
350
351 // Left
352 edge_ratios[6] = std::min(d04, d37) / std::max(d04, d37);
353 edge_ratios[7] = std::min(d03, d47) / std::max(d03, d47);
354
355 // Bottom
356 edge_ratios[8] = std::min(d01, d23) / std::max(d01, d23);
357 edge_ratios[9] = std::min(d03, d12) / std::max(d03, d12);
358
359 // Top
360 edge_ratios[10] = std::min(d45, d67) / std::max(d45, d67);
361 edge_ratios[11] = std::min(d56, d47) / std::max(d56, d47);
362
363 return *(std::min_element(edge_ratios.begin(), edge_ratios.end())) ;
364
365 break;
366 }
367
368
373 case STRETCH:
374 {
375 const Real sqrt3 = 1.73205080756888;
376
380 const Real d06 = this->length(0,6);
381 const Real d17 = this->length(1,7);
382 const Real d35 = this->length(3,5);
383 const Real d24 = this->length(2,4);
384 const Real max_diag = std::max(d06, std::max(d17, std::max(d35, d24)));
385
386 libmesh_assert_not_equal_to ( max_diag, 0.0 );
387
391 std::vector<Real> edges(12);
392 edges[0] = this->length(0,1);
393 edges[1] = this->length(1,2);
394 edges[2] = this->length(2,3);
395 edges[3] = this->length(0,3);
396 edges[4] = this->length(4,5);
397 edges[5] = this->length(5,6);
398 edges[6] = this->length(6,7);
399 edges[7] = this->length(4,7);
400 edges[8] = this->length(0,4);
401 edges[9] = this->length(1,5);
402 edges[10] = this->length(2,6);
403 edges[11] = this->length(3,7);
404
405 const Real min_edge = *(std::min_element(edges.begin(), edges.end()));
406 return sqrt3 * min_edge / max_diag ;
407 }
408
409
410 case SHAPE:
411 case SKEW:
412 {
413 // From: P. Knupp, "Algebraic mesh quality metrics for
414 // unstructured initial meshes," Finite Elements in Analysis
415 // and Design 39, 2003, p. 217-241, Sections 6.2 and 6.3.
416
417 // Make local copies of points, we will access these several
418 // times below.
419 const Point
420 x0 = point(0), x1 = point(1), x2 = point(2), x3 = point(3),
421 x4 = point(4), x5 = point(5), x6 = point(6), x7 = point(7);
422
423 // The columns of the Jacobian matrices are:
424 // \vec{x}_{\xi} = \vec{a1}*eta*zeta + \vec{b1}*eta + \vec{c1}*zeta + \vec{d1}
425 // \vec{x}_{\eta} = \vec{a2}*xi*zeta + \vec{b2}*xi + \vec{c2}*zeta + \vec{d2}
426 // \vec{x}_{\zeta} = \vec{a3}*xi*eta + \vec{b3}*xi + \vec{c3}*eta + \vec{d3}
427 // where the ai, bi, ci, and di are constants defined below.
428 const Point a1 = -x0 + x1 - x2 + x3 + x4 - x5 + x6 - x7;
429 const Point b1 = x0 - x1 + x2 - x3 + x4 - x5 + x6 - x7;
430 const Point c1 = x0 - x1 - x2 + x3 - x4 + x5 + x6 - x7;
431 const Point d1 = -x0 + x1 + x2 - x3 - x4 + x5 + x6 - x7;
432
433 const Point a2 = a1;
434 const Point b2 = b1;
435 const Point c2 = x0 + x1 - x2 - x3 - x4 - x5 + x6 + x7;
436 const Point d2 = -x0 - x1 + x2 + x3 - x4 - x5 + x6 + x7;
437
438 const Point a3 = a1;
439 const Point b3 = c1;
440 const Point c3 = c2;
441 const Point d3 = -x0 - x1 - x2 - x3 + x4 + x5 + x6 + x7;
442
443 // Form the nodal Jacobians. These were computed using a
444 // Python script and the formulas above. Note that we are
445 // actually computing the Jacobian _columns_ and passing them
446 // to the RealTensor constructor which expects _rows_, but
447 // it's OK because we are only interested in determinants and
448 // products which are not affected by taking the transpose.
449 std::array<RealTensor, 8> A =
450 {{
451 RealTensor(d1, d2, d3),
452 RealTensor(d1, b2 + d2, b3 + d3),
453 RealTensor(b1 + d1, b2 + d2, a3 + b3 + c3 + d3),
454 RealTensor(b1 + d1, d2, c3 + d3),
455 RealTensor(c1 + d1, c2 + d2, d3),
456 RealTensor(c1 + d1, a2 + b2 + c2 + d2, b3 + d3),
457 RealTensor(a1 + b1 + c1 + d1, a2 + b2 + c2 + d2, a3 + b3 + c3 + d3),
458 RealTensor(a1 + b1 + c1 + d1, c2 + d2, c3 + d3)
459 }};
460
461 // Compute Nodal areas, alpha_k = det(A_k).
462 // If any of these are zero or negative, we return zero
463 // (lowest possible value) for the quality, since the formulas
464 // below require positive nodal areas.
465 std::array<Real, 8> alpha;
466 for (unsigned int k=0; k<alpha.size(); ++k)
467 {
468 alpha[k] = A[k].det();
469 if (alpha[k] <= 0.)
470 return 0.;
471 }
472
473 // Compute metric tensors, T_k = A_k^T * A_k.
474 std::array<RealTensor, 8> T;
475 for (unsigned int k=0; k<T.size(); ++k)
476 T[k] = A[k] * A[k].transpose();
477
478 // Compute and return the shape metric. These only use the
479 // diagonal entries of the T_k.
480 Real den = 0.;
481 if (q == SHAPE)
482 {
483 for (unsigned int k=0; k<T.size(); ++k)
484 den += T[k].tr() / std::pow(alpha[k], 2./3.);
485 return (den == 0.) ? 0 : (24. / den);
486 }
487 else
488 {
489 for (unsigned int k=0; k<T.size(); ++k)
490 den += std::pow(std::sqrt(T[k](0,0) * T[k](1,1) * T[k](2,2)) / alpha[k], 2./3.);
491 return (den == 0.) ? 0 : (8. / den);
492 }
493 }
494#endif // LIBMESH_DIM >= 3
495
500 default:
501 return Elem::quality(q);
502 }
503}
504
505
506
507std::pair<Real, Real> Hex::qual_bounds (const ElemQuality q) const
508{
509 std::pair<Real, Real> bounds;
510
511 switch (q)
512 {
513
514 case ASPECT_RATIO:
515 bounds.first = 1.;
516 bounds.second = 4.;
517 break;
518
519 case SKEW:
520 bounds.first = 0.;
521 bounds.second = 0.5;
522 break;
523
524 case SHEAR:
525 case SHAPE:
526 bounds.first = 0.3;
527 bounds.second = 1.;
528 break;
529
530 case CONDITION:
531 bounds.first = 1.;
532 bounds.second = 8.;
533 break;
534
535 case SCALED_JACOBIAN:
536 case JACOBIAN:
537 bounds.first = 0.5;
538 bounds.second = 1.;
539 break;
540
541 case DISTORTION:
542 bounds.first = 0.6;
543 bounds.second = 1.;
544 break;
545
546 case TAPER:
547 bounds.first = 0.;
548 bounds.second = 0.4;
549 break;
550
551 case STRETCH:
552 bounds.first = 0.25;
553 bounds.second = 1.;
554 break;
555
556 case DIAGONAL:
557 bounds.first = 0.65;
558 bounds.second = 1.;
559 break;
560
561 case SIZE:
562 bounds.first = 0.5;
563 bounds.second = 1.;
564 break;
565
566 default:
567 libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
568 bounds.first = -1;
569 bounds.second = -1;
570 }
571
572 return bounds;
573}
574
575
576
578 const Real eps) const
579{
580 const Real & xi = p(0);
581 const Real & eta = p(1);
582 const Real & zeta = p(2);
583
584 // The reference hexahedral element is [-1,1]^3.
585 return ((xi >= -1.-eps) &&
586 (xi <= 1.+eps) &&
587 (eta >= -1.-eps) &&
588 (eta <= 1.+eps) &&
589 (zeta >= -1.-eps) &&
590 (zeta <= 1.+eps));
591}
592
593
594
595const unsigned short int Hex::_second_order_vertex_child_number[27] =
596 {
597 99,99,99,99,99,99,99,99, // Vertices
598 0,1,2,0,0,1,2,3,4,5,6,5, // Edges
599 0,0,1,2,0,4, // Faces
600 0 // Interior
601 };
602
603
604
605const unsigned short int Hex::_second_order_vertex_child_index[27] =
606 {
607 99,99,99,99,99,99,99,99, // Vertices
608 1,2,3,3,4,5,6,7,5,6,7,7, // Edges
609 2,5,6,7,7,6, // Faces
610 6 // Interior
611 };
612
613
614const unsigned short int Hex::_second_order_adjacent_vertices[12][2] =
615 {
616 { 0, 1}, // vertices adjacent to node 8
617 { 1, 2}, // vertices adjacent to node 9
618 { 2, 3}, // vertices adjacent to node 10
619 { 0, 3}, // vertices adjacent to node 11
620
621 { 0, 4}, // vertices adjacent to node 12
622 { 1, 5}, // vertices adjacent to node 13
623 { 2, 6}, // vertices adjacent to node 14
624 { 3, 7}, // vertices adjacent to node 15
625
626 { 4, 5}, // vertices adjacent to node 16
627 { 5, 6}, // vertices adjacent to node 17
628 { 6, 7}, // vertices adjacent to node 18
629 { 4, 7} // vertices adjacent to node 19
630 };
631
632
633#ifdef LIBMESH_ENABLE_AMR
634
635// We number 125 "possible node locations" for a 2x2x2 refinement of
636// hexes with up to 3x3x3 nodes each
637const int Hex::_child_node_lookup[8][27] =
638 {
639 // node lookup for child 0 (near node 0)
640 { 0, 2, 12, 10, 50, 52, 62, 60, 1, 7, 11, 5, 25, 27, 37, 35,
641 51, 57, 61, 55, 6, 26, 32, 36, 30, 56, 31},
642
643 // node lookup for child 1 (near node 1)
644 { 2, 4, 14, 12, 52, 54, 64, 62, 3, 9, 13, 7, 27, 29, 39, 37,
645 53, 59, 63, 57, 8, 28, 34, 38, 32, 58, 33},
646
647 // node lookup for child 2 (near node 3)
648 { 10, 12, 22, 20, 60, 62, 72, 70, 11, 17, 21, 15, 35, 37, 47, 45,
649 61, 67, 71, 65, 16, 36, 42, 46, 40, 66, 41},
650
651 // node lookup for child 3 (near node 2)
652 { 12, 14, 24, 22, 62, 64, 74, 72, 13, 19, 23, 17, 37, 39, 49, 47,
653 63, 69, 73, 67, 18, 38, 44, 48, 42, 68, 43},
654
655 // node lookup for child 4 (near node 4)
656 { 50, 52, 62, 60, 100, 102, 112, 110, 51, 57, 61, 55, 75, 77, 87, 85,
657 101, 107, 111, 105, 56, 76, 82, 86, 80, 106, 81},
658
659 // node lookup for child 5 (near node 5)
660 { 52, 54, 64, 62, 102, 104, 114, 112, 53, 59, 63, 57, 77, 79, 89, 87,
661 103, 109, 113, 107, 58, 78, 84, 88, 82, 108, 93},
662
663 // node lookup for child 6 (near node 7)
664 { 60, 62, 72, 70, 110, 112, 122, 120, 61, 67, 71, 65, 85, 87, 97, 95,
665 111, 117, 121, 115, 66, 86, 92, 96, 90, 116, 91},
666
667 // node lookup for child 7 (near node 6)
668 { 62, 64, 74, 72, 112, 114, 124, 122, 63, 69, 73, 67, 87, 89, 99, 97,
669 113, 119, 123, 117, 68, 88, 94, 98, 92, 118, 103}
670 };
671
672#endif // LIBMESH_ENABLE_AMR
673
674
675} // namespace libMesh
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
const Point & point(const unsigned int i) const
Definition elem.h:2462
virtual unsigned int n_nodes() const =0
virtual bool is_face(const unsigned int i) const =0
virtual Real quality(const ElemQuality q) const
Definition elem.C:1783
virtual bool is_edge(const unsigned int i) const =0
static dof_id_type compute_key(dof_id_type n0)
Definition elem.h:3311
bool is_internal(const unsigned int i) const
Definition elem.C:3611
Real length(const unsigned int n1, const unsigned int n2) const
Definition elem.C:727
virtual bool is_vertex(const unsigned int i) const =0
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2484
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_hex8.h:179
static const int nodes_per_edge
Definition cell_hex8.h:167
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_hex8.h:173
static const int nodes_per_side
Definition cell_hex8.h:166
virtual dof_id_type low_order_key(const unsigned int s) const override
Definition cell_hex.C:114
virtual unsigned int opposite_side(const unsigned int s) const override final
Definition cell_hex.C:211
virtual bool is_flipped() const override final
Definition cell_hex.C:254
virtual unsigned int n_edges() const override final
Definition cell_hex.h:90
virtual unsigned int n_vertices() const override final
Definition cell_hex.h:85
static const unsigned int adjacent_edges_map[8][3]
This maps the node to the (in this case) 3 edge ids adjacent to the node.
Definition cell_hex.h:244
virtual std::vector< unsigned int > sides_on_edge(const unsigned int e) const override final
Definition cell_hex.C:202
static const int num_edges
Definition cell_hex.h:74
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
Definition cell_hex.C:148
static const unsigned short int _second_order_vertex_child_index[27]
Vector that names the child vertex index for each second order node.
Definition cell_hex.h:224
static const unsigned int edge_sides_map[12][2]
This maps each edge to the sides that contain said edge.
Definition cell_hex.h:195
virtual std::vector< unsigned int > edges_adjacent_to_node(const unsigned int n) const override
Definition cell_hex.C:263
virtual unsigned int n_children() const override final
Definition cell_hex.h:100
virtual unsigned int n_sides() const override final
Definition cell_hex.h:80
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const override final
Definition cell_hex.C:191
virtual std::pair< Real, Real > qual_bounds(const ElemQuality q) const override
Definition cell_hex.C:507
static const unsigned short int _second_order_vertex_child_number[27]
Vector that names a child sharing each second order node.
Definition cell_hex.h:219
virtual bool on_reference_element(const Point &p, const Real eps=TOLERANCE) const override final
Definition cell_hex.C:577
virtual unsigned int local_side_node(unsigned int side, unsigned int side_node) const override
Definition cell_hex.C:126
virtual unsigned int local_edge_node(unsigned int edge, unsigned int edge_node) const override
Definition cell_hex.C:137
virtual dof_id_type key() const
Don't hide Elem::key() defined in the base class.
Definition elem.C:738
static const int num_sides
Geometric constants for all Hexes.
Definition cell_hex.h:73
virtual Real quality(const ElemQuality q) const override
Definition cell_hex.C:280
virtual unsigned int opposite_node(const unsigned int n, const unsigned int s) const override final
Definition cell_hex.C:220
static const int _child_node_lookup[8][27]
Lookup table from child id, child node id to "possible node location" (a simple dictionary-index in a...
Definition cell_hex.h:235
static const int num_children
Definition cell_hex.h:75
static const unsigned short int _second_order_adjacent_vertices[12][2]
Matrix that tells which vertices define the location of mid-side (or second-order) nodes.
Definition cell_hex.h:214
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const override final
Definition cell_hex.C:170
static const Real _master_points[27][3]
Master element node locations.
Definition cell_hex.h:229
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The libMesh namespace provides an interface to certain functionality in the library.
T triple_product(const TypeVector< T > &a, const TypeVector< T > &b, const TypeVector< T > &c)
libmesh_assert(ctx)
OStreamProxy out
ElemQuality
Defines an enum for element quality metrics.
RealTensorValue RealTensor
uint8_t dof_id_type
Definition id_types.h:67
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real