libMesh
cell_hex.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2019 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 
31 namespace libMesh
32 {
33 
34 
35 
36 // ------------------------------------------------------------
37 // Hex class static member initializations
38 
39 
40 // We need to require C++11...
41 const Real Hex::_master_points[27][3] =
42  {
43  {-1, -1, -1},
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  {0, -1, -1},
52  {1, 0, -1},
53  {0, 1, -1},
54  {-1, 0, -1},
55  {-1, -1, 0},
56  {1, -1, 0},
57  {1, 1, 0},
58  {-1, 1, 0},
59  {0, -1, 1},
60  {1, 0, 1},
61  {0, 1, 1},
62  {-1, 0, 1},
63  {0, 0, -1},
64  {0, -1, 0},
65  {1, 0, 0},
66  {0, 1, 0},
67  {-1, 0, 0},
68  {0, 0, 1}
69  };
70 
71 
72 
73 
74 // ------------------------------------------------------------
75 // Hex class member functions
76 dof_id_type Hex::key (const unsigned int s) const
77 {
78  libmesh_assert_less (s, this->n_sides());
79 
80  return this->compute_key(this->node_id(Hex8::side_nodes_map[s][0]),
81  this->node_id(Hex8::side_nodes_map[s][1]),
82  this->node_id(Hex8::side_nodes_map[s][2]),
83  this->node_id(Hex8::side_nodes_map[s][3]));
84 }
85 
86 
87 
88 unsigned int Hex::which_node_am_i(unsigned int side,
89  unsigned int side_node) const
90 {
91  libmesh_assert_less (side, this->n_sides());
92  libmesh_assert_less (side_node, 4);
93 
94  return Hex8::side_nodes_map[side][side_node];
95 }
96 
97 
98 
99 std::unique_ptr<Elem> Hex::side_ptr (const unsigned int i)
100 {
101  libmesh_assert_less (i, this->n_sides());
102 
103  std::unique_ptr<Elem> face = libmesh_make_unique<Quad4>();
104 
105  for (auto n : face->node_index_range())
106  face->set_node(n) = this->node_ptr(Hex8::side_nodes_map[i][n]);
107 
108  return face;
109 }
110 
111 
112 
113 void Hex::side_ptr (std::unique_ptr<Elem> & side,
114  const unsigned int i)
115 {
116  this->simple_side_ptr<Hex,Hex8>(side, i, QUAD4);
117 }
118 
119 
120 
121 bool Hex::is_child_on_side(const unsigned int c,
122  const unsigned int s) const
123 {
124  libmesh_assert_less (c, this->n_children());
125  libmesh_assert_less (s, this->n_sides());
126 
127  // This array maps the Hex8 node numbering to the Hex8 child
128  // numbering. I.e.
129  // node 6 touches child 7, and
130  // node 7 touches child 6, etc.
131  const unsigned int node_child_map[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
132 
133  for (unsigned int i = 0; i != 4; ++i)
134  if (node_child_map[Hex8::side_nodes_map[s][i]] == c)
135  return true;
136 
137  return false;
138 }
139 
140 
141 
142 bool Hex::is_edge_on_side(const unsigned int e,
143  const unsigned int s) const
144 {
145  libmesh_assert_less (e, this->n_edges());
146  libmesh_assert_less (s, this->n_sides());
147 
148  return (is_node_on_side(Hex8::edge_nodes_map[e][0],s) &&
150 }
151 
152 
153 
154 unsigned int Hex::opposite_side(const unsigned int side_in) const
155 {
156  libmesh_assert_less (side_in, 6);
157  static const unsigned char hex_opposites[6] = {5, 3, 4, 1, 2, 0};
158  return hex_opposites[side_in];
159 }
160 
161 
162 
163 unsigned int Hex::opposite_node(const unsigned int node_in,
164  const unsigned int side_in) const
165 {
166  libmesh_assert_less (node_in, 26);
167  libmesh_assert_less (node_in, this->n_nodes());
168  libmesh_assert_less (side_in, this->n_sides());
169  libmesh_assert(this->is_node_on_side(node_in, side_in));
170 
171  static const unsigned char side05_nodes_map[] =
172  {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};
173  static const unsigned char side13_nodes_map[] =
174  {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};
175  static const unsigned char side24_nodes_map[] =
176  {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};
177 
178  switch (side_in)
179  {
180  case 0:
181  case 5:
182  return side05_nodes_map[node_in];
183  case 1:
184  case 3:
185  return side13_nodes_map[node_in];
186  case 2:
187  case 4:
188  return side24_nodes_map[node_in];
189  default:
190  libmesh_error_msg("Unsupported side_in = " << side_in);
191  }
192 }
193 
194 
195 
197 {
198  switch (q)
199  {
200 
201 #if LIBMESH_DIM >= 3
202 
206  case DIAGONAL:
207  {
208  // Diagonal between node 0 and node 6
209  const Real d06 = this->length(0,6);
210 
211  // Diagonal between node 3 and node 5
212  const Real d35 = this->length(3,5);
213 
214  // Diagonal between node 1 and node 7
215  const Real d17 = this->length(1,7);
216 
217  // Diagonal between node 2 and node 4
218  const Real d24 = this->length(2,4);
219 
220  // Find the biggest and smallest diagonals
221  const Real min = std::min(d06, std::min(d35, std::min(d17, d24)));
222  const Real max = std::max(d06, std::max(d35, std::max(d17, d24)));
223 
224  libmesh_assert_not_equal_to (max, 0.0);
225 
226  return min / max;
227 
228  break;
229  }
230 
235  case TAPER:
236  {
237 
241  const Real d01 = this->length(0,1);
242  const Real d12 = this->length(1,2);
243  const Real d23 = this->length(2,3);
244  const Real d03 = this->length(0,3);
245  const Real d45 = this->length(4,5);
246  const Real d56 = this->length(5,6);
247  const Real d67 = this->length(6,7);
248  const Real d47 = this->length(4,7);
249  const Real d04 = this->length(0,4);
250  const Real d15 = this->length(1,5);
251  const Real d37 = this->length(3,7);
252  const Real d26 = this->length(2,6);
253 
254  std::vector<Real> edge_ratios(12);
255  // Front
256  edge_ratios[0] = std::min(d01, d45) / std::max(d01, d45);
257  edge_ratios[1] = std::min(d04, d15) / std::max(d04, d15);
258 
259  // Right
260  edge_ratios[2] = std::min(d15, d26) / std::max(d15, d26);
261  edge_ratios[3] = std::min(d12, d56) / std::max(d12, d56);
262 
263  // Back
264  edge_ratios[4] = std::min(d67, d23) / std::max(d67, d23);
265  edge_ratios[5] = std::min(d26, d37) / std::max(d26, d37);
266 
267  // Left
268  edge_ratios[6] = std::min(d04, d37) / std::max(d04, d37);
269  edge_ratios[7] = std::min(d03, d47) / std::max(d03, d47);
270 
271  // Bottom
272  edge_ratios[8] = std::min(d01, d23) / std::max(d01, d23);
273  edge_ratios[9] = std::min(d03, d12) / std::max(d03, d12);
274 
275  // Top
276  edge_ratios[10] = std::min(d45, d67) / std::max(d45, d67);
277  edge_ratios[11] = std::min(d56, d47) / std::max(d56, d47);
278 
279  return *(std::min_element(edge_ratios.begin(), edge_ratios.end())) ;
280 
281  break;
282  }
283 
284 
289  case STRETCH:
290  {
291  const Real sqrt3 = 1.73205080756888;
292 
296  const Real d06 = this->length(0,6);
297  const Real d17 = this->length(1,7);
298  const Real d35 = this->length(3,5);
299  const Real d24 = this->length(2,4);
300  const Real max_diag = std::max(d06, std::max(d17, std::max(d35, d24)));
301 
302  libmesh_assert_not_equal_to ( max_diag, 0.0 );
303 
307  std::vector<Real> edges(12);
308  edges[0] = this->length(0,1);
309  edges[1] = this->length(1,2);
310  edges[2] = this->length(2,3);
311  edges[3] = this->length(0,3);
312  edges[4] = this->length(4,5);
313  edges[5] = this->length(5,6);
314  edges[6] = this->length(6,7);
315  edges[7] = this->length(4,7);
316  edges[8] = this->length(0,4);
317  edges[9] = this->length(1,5);
318  edges[10] = this->length(2,6);
319  edges[11] = this->length(3,7);
320 
321  const Real min_edge = *(std::min_element(edges.begin(), edges.end()));
322  return sqrt3 * min_edge / max_diag ;
323  }
324 
325 
326  case SHAPE:
327  case SKEW:
328  {
329  // From: P. Knupp, "Algebraic mesh quality metrics for
330  // unstructured initial meshes," Finite Elements in Analysis
331  // and Design 39, 2003, p. 217-241, Sections 6.2 and 6.3.
332 
333  // Make local copies of points, we will access these several
334  // times below.
335  const Point
336  x0 = point(0), x1 = point(1), x2 = point(2), x3 = point(3),
337  x4 = point(4), x5 = point(5), x6 = point(6), x7 = point(7);
338 
339  // The columns of the Jacobian matrices are:
340  // \vec{x}_{\xi} = \vec{a1}*eta*zeta + \vec{b1}*eta + \vec{c1}*zeta + \vec{d1}
341  // \vec{x}_{\eta} = \vec{a2}*xi*zeta + \vec{b2}*xi + \vec{c2}*zeta + \vec{d2}
342  // \vec{x}_{\zeta} = \vec{a3}*xi*eta + \vec{b3}*xi + \vec{c3}*eta + \vec{d3}
343  // where the ai, bi, ci, and di are constants defined below.
344  const Point a1 = -x0 + x1 - x2 + x3 + x4 - x5 + x6 - x7;
345  const Point b1 = x0 - x1 + x2 - x3 + x4 - x5 + x6 - x7;
346  const Point c1 = x0 - x1 - x2 + x3 - x4 + x5 + x6 - x7;
347  const Point d1 = -x0 + x1 + x2 - x3 - x4 + x5 + x6 - x7;
348 
349  const Point a2 = a1;
350  const Point b2 = b1;
351  const Point c2 = x0 + x1 - x2 - x3 - x4 - x5 + x6 + x7;
352  const Point d2 = -x0 - x1 + x2 + x3 - x4 - x5 + x6 + x7;
353 
354  const Point a3 = a1;
355  const Point b3 = c1;
356  const Point c3 = c2;
357  const Point d3 = -x0 - x1 - x2 - x3 + x4 + x5 + x6 + x7;
358 
359  // Form the nodal Jacobians. These were computed using a
360  // Python script and the formulas above. Note that we are
361  // actually computing the Jacobian _columns_ and passing them
362  // to the RealTensor constructor which expects _rows_, but
363  // it's OK because we are only interested in determinants and
364  // products which are not affected by taking the transpose.
365  std::array<RealTensor, 8> A =
366  {
367  RealTensor(d1, d2, d3),
368  RealTensor(d1, b2 + d2, b3 + d3),
369  RealTensor(b1 + d1, b2 + d2, a3 + b3 + c3 + d3),
370  RealTensor(b1 + d1, d2, c3 + d3),
371  RealTensor(c1 + d1, c2 + d2, d3),
372  RealTensor(c1 + d1, a2 + b2 + c2 + d2, b3 + d3),
373  RealTensor(a1 + b1 + c1 + d1, a2 + b2 + c2 + d2, a3 + b3 + c3 + d3),
374  RealTensor(a1 + b1 + c1 + d1, c2 + d2, c3 + d3)
375  };
376 
377  // Compute Nodal areas, alpha_k = det(A_k).
378  // If any of these are zero or negative, we return zero
379  // (lowest possible value) for the quality, since the formulas
380  // below require positive nodal areas.
381  std::array<Real, 8> alpha;
382  for (unsigned int k=0; k<alpha.size(); ++k)
383  {
384  alpha[k] = A[k].det();
385  if (alpha[k] <= 0.)
386  return 0.;
387  }
388 
389  // Compute metric tensors, T_k = A_k^T * A_k.
390  std::array<RealTensor, 8> T;
391  for (unsigned int k=0; k<T.size(); ++k)
392  T[k] = A[k] * A[k].transpose();
393 
394  // Compute and return the shape metric. These only use the
395  // diagonal entries of the T_k.
396  Real den = 0.;
397  if (q == SHAPE)
398  {
399  for (unsigned int k=0; k<T.size(); ++k)
400  den += T[k].tr() / std::pow(alpha[k], 2./3.);
401  return (den == 0.) ? 0 : (24. / den);
402  }
403  else
404  {
405  for (unsigned int k=0; k<T.size(); ++k)
406  den += std::pow(std::sqrt(T[k](0,0) * T[k](1,1) * T[k](2,2)) / alpha[k], 2./3.);
407  return (den == 0.) ? 0 : (8. / den);
408  }
409  }
410 #endif // LIBMESH_DIM >= 3
411 
416  default:
417  return Elem::quality(q);
418  }
419 }
420 
421 
422 
423 std::pair<Real, Real> Hex::qual_bounds (const ElemQuality q) const
424 {
425  std::pair<Real, Real> bounds;
426 
427  switch (q)
428  {
429 
430  case ASPECT_RATIO:
431  bounds.first = 1.;
432  bounds.second = 4.;
433  break;
434 
435  case SKEW:
436  bounds.first = 0.;
437  bounds.second = 0.5;
438  break;
439 
440  case SHEAR:
441  case SHAPE:
442  bounds.first = 0.3;
443  bounds.second = 1.;
444  break;
445 
446  case CONDITION:
447  bounds.first = 1.;
448  bounds.second = 8.;
449  break;
450 
451  case JACOBIAN:
452  bounds.first = 0.5;
453  bounds.second = 1.;
454  break;
455 
456  case DISTORTION:
457  bounds.first = 0.6;
458  bounds.second = 1.;
459  break;
460 
461  case TAPER:
462  bounds.first = 0.;
463  bounds.second = 0.4;
464  break;
465 
466  case STRETCH:
467  bounds.first = 0.25;
468  bounds.second = 1.;
469  break;
470 
471  case DIAGONAL:
472  bounds.first = 0.65;
473  bounds.second = 1.;
474  break;
475 
476  case SIZE:
477  bounds.first = 0.5;
478  bounds.second = 1.;
479  break;
480 
481  default:
482  libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
483  bounds.first = -1;
484  bounds.second = -1;
485  }
486 
487  return bounds;
488 }
489 
490 
491 
492 const unsigned short int Hex::_second_order_vertex_child_number[27] =
493  {
494  99,99,99,99,99,99,99,99, // Vertices
495  0,1,2,0,0,1,2,3,4,5,6,5, // Edges
496  0,0,1,2,0,4, // Faces
497  0 // Interior
498  };
499 
500 
501 
502 const unsigned short int Hex::_second_order_vertex_child_index[27] =
503  {
504  99,99,99,99,99,99,99,99, // Vertices
505  1,2,3,3,4,5,6,7,5,6,7,7, // Edges
506  2,5,6,7,7,6, // Faces
507  6 // Interior
508  };
509 
510 
511 const unsigned short int Hex::_second_order_adjacent_vertices[12][2] =
512  {
513  { 0, 1}, // vertices adjacent to node 8
514  { 1, 2}, // vertices adjacent to node 9
515  { 2, 3}, // vertices adjacent to node 10
516  { 0, 3}, // vertices adjacent to node 11
517 
518  { 0, 4}, // vertices adjacent to node 12
519  { 1, 5}, // vertices adjacent to node 13
520  { 2, 6}, // vertices adjacent to node 14
521  { 3, 7}, // vertices adjacent to node 15
522 
523  { 4, 5}, // vertices adjacent to node 16
524  { 5, 6}, // vertices adjacent to node 17
525  { 6, 7}, // vertices adjacent to node 18
526  { 4, 7} // vertices adjacent to node 19
527  };
528 
529 
530 #ifdef LIBMESH_ENABLE_AMR
531 
532 // We number 125 "possible node locations" for a 2x2x2 refinement of
533 // hexes with up to 3x3x3 nodes each
534 const int Hex::_child_node_lookup[8][27] =
535  {
536  // node lookup for child 0 (near node 0)
537  { 0, 2, 12, 10, 50, 52, 62, 60, 1, 7, 11, 5, 25, 27, 37, 35,
538  51, 57, 61, 55, 6, 26, 32, 36, 30, 56, 31},
539 
540  // node lookup for child 1 (near node 1)
541  { 2, 4, 14, 12, 52, 54, 64, 62, 3, 9, 13, 7, 27, 29, 39, 37,
542  53, 59, 63, 57, 8, 28, 34, 38, 32, 58, 33},
543 
544  // node lookup for child 2 (near node 3)
545  { 10, 12, 22, 20, 60, 62, 72, 70, 11, 17, 21, 15, 35, 37, 47, 45,
546  61, 67, 71, 65, 16, 36, 42, 46, 40, 66, 41},
547 
548  // node lookup for child 3 (near node 2)
549  { 12, 14, 24, 22, 62, 64, 74, 72, 13, 19, 23, 17, 37, 39, 49, 47,
550  63, 69, 73, 67, 18, 38, 44, 48, 42, 68, 43},
551 
552  // node lookup for child 4 (near node 4)
553  { 50, 52, 62, 60, 100, 102, 112, 110, 51, 57, 61, 55, 75, 77, 87, 85,
554  101, 107, 111, 105, 56, 76, 82, 86, 80, 106, 81},
555 
556  // node lookup for child 5 (near node 5)
557  { 52, 54, 64, 62, 102, 104, 114, 112, 53, 59, 63, 57, 77, 79, 89, 87,
558  103, 109, 113, 107, 58, 78, 84, 88, 82, 108, 93},
559 
560  // node lookup for child 6 (near node 7)
561  { 60, 62, 72, 70, 110, 112, 122, 120, 61, 67, 71, 65, 85, 87, 97, 95,
562  111, 117, 121, 115, 66, 86, 92, 96, 90, 116, 91},
563 
564  // node lookup for child 7 (near node 6)
565  { 62, 64, 74, 72, 112, 114, 124, 122, 63, 69, 73, 67, 87, 89, 99, 97,
566  113, 119, 123, 117, 68, 88, 94, 98, 92, 118, 103}
567  };
568 
569 #endif // LIBMESH_ENABLE_AMR
570 
571 
572 } // namespace libMesh
libMesh::Hex::is_child_on_side
virtual bool is_child_on_side(const unsigned int c, const unsigned int s) const override final
Definition: cell_hex.C:121
libMesh::dof_id_type
uint8_t dof_id_type
Definition: id_types.h:67
libMesh::Elem::is_node_on_side
virtual bool is_node_on_side(const unsigned int n, const unsigned int s) const =0
libMesh::Hex::_second_order_vertex_child_number
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:182
libMesh::STRETCH
Definition: enum_elem_quality.h:45
libMesh::Elem::compute_key
static dof_id_type compute_key(dof_id_type n0)
Definition: elem.h:2683
libMesh::Hex::n_children
virtual unsigned int n_children() const override final
Definition: cell_hex.h:93
libMesh::Hex::side_ptr
virtual std::unique_ptr< Elem > side_ptr(const unsigned int i) override final
Definition: cell_hex.C:99
libMesh::DISTORTION
Definition: enum_elem_quality.h:42
libMesh::Elem::n_nodes
virtual unsigned int n_nodes() const =0
libMesh::Hex::qual_bounds
virtual std::pair< Real, Real > qual_bounds(const ElemQuality q) const override
Definition: cell_hex.C:423
libMesh::Hex::_second_order_vertex_child_index
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:187
libMesh
The libMesh namespace provides an interface to certain functionality in the library.
Definition: factoryfunction.C:55
libMesh::RealTensor
RealTensorValue RealTensor
Definition: hp_coarsentest.h:50
std::sqrt
MetaPhysicL::DualNumber< T, D > sqrt(const MetaPhysicL::DualNumber< T, D > &in)
libMesh::Hex::opposite_side
virtual unsigned int opposite_side(const unsigned int s) const override final
Definition: cell_hex.C:154
libMesh::Hex::opposite_node
virtual unsigned int opposite_node(const unsigned int n, const unsigned int s) const override final
Definition: cell_hex.C:163
libMesh::DIAGONAL
Definition: enum_elem_quality.h:46
libMesh::Elem::length
Real length(const unsigned int n1, const unsigned int n2) const
Definition: elem.C:399
libMesh::Elem::point
const Point & point(const unsigned int i) const
Definition: elem.h:1955
libMesh::Hex::which_node_am_i
virtual unsigned int which_node_am_i(unsigned int side, unsigned int side_node) const override
Definition: cell_hex.C:88
libMesh::Hex::_child_node_lookup
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:198
libMesh::libmesh_assert
libmesh_assert(ctx)
libMesh::Hex8::side_nodes_map
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:165
libMesh::Hex::_master_points
static const Real _master_points[27][3]
Master element node locations.
Definition: cell_hex.h:192
libMesh::QUAD4
Definition: enum_elem_type.h:41
libMesh::SHEAR
Definition: enum_elem_quality.h:37
libMesh::Point
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:38
libMesh::Elem::key
virtual dof_id_type key() const
Definition: elem.C:410
std::pow
double pow(double a, int b)
Definition: libmesh_augment_std_namespace.h:58
libMesh::Elem::quality
virtual Real quality(const ElemQuality q) const
Definition: elem.C:1326
A
static PetscErrorCode Mat * A
Definition: petscdmlibmeshimpl.C:1026
libMesh::ASPECT_RATIO
Definition: enum_elem_quality.h:35
libMesh::Hex::is_edge_on_side
virtual bool is_edge_on_side(const unsigned int e, const unsigned int s) const override final
Definition: cell_hex.C:142
libMesh::JACOBIAN
Definition: enum_elem_quality.h:50
libMesh::SIZE
Definition: enum_elem_quality.h:49
libMesh::ElemQuality
ElemQuality
Defines an enum for element quality metrics.
Definition: enum_elem_quality.h:34
libMesh::CONDITION
Definition: enum_elem_quality.h:41
libMesh::SHAPE
Definition: enum_elem_quality.h:38
libMesh::Hex::n_sides
virtual unsigned int n_sides() const override final
Definition: cell_hex.h:73
libMesh::TAPER
Definition: enum_elem_quality.h:43
libMesh::Hex8::edge_nodes_map
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:171
libMesh::Elem::node_id
dof_id_type node_id(const unsigned int i) const
Definition: elem.h:1977
libMesh::Real
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Definition: libmesh_common.h:121
libMesh::Hex::_second_order_adjacent_vertices
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:177
libMesh::Hex::n_edges
virtual unsigned int n_edges() const override final
Definition: cell_hex.h:83
libMesh::out
OStreamProxy out
libMesh::Elem::node_ptr
const Node * node_ptr(const unsigned int i) const
Definition: elem.h:2009
libMesh::Hex::quality
virtual Real quality(const ElemQuality q) const override
Definition: cell_hex.C:196
libMesh::SKEW
Definition: enum_elem_quality.h:36