LCOV - code coverage report
Current view: top level - src/geom - cell_hex.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 70 233 30.0 %
Date: 2025-08-19 19:27:09 Functions: 13 16 81.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 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             : const int Hex::num_sides;
      39             : const int Hex::num_edges;
      40             : const int Hex::num_children;
      41             : 
      42             : const 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             : 
      72             : const 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             : 
      88             : const 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
     102      144576 : dof_id_type Hex::key (const unsigned int s) const
     103             : {
     104       12048 :   libmesh_assert_less (s, this->n_sides());
     105             : 
     106      156624 :   return this->compute_key(this->node_id(Hex8::side_nodes_map[s][0]),
     107      144576 :                            this->node_id(Hex8::side_nodes_map[s][1]),
     108      144576 :                            this->node_id(Hex8::side_nodes_map[s][2]),
     109      156624 :                            this->node_id(Hex8::side_nodes_map[s][3]));
     110             : }
     111             : 
     112             : 
     113             : 
     114    32354539 : dof_id_type Hex::low_order_key (const unsigned int s) const
     115             : {
     116      899692 :   libmesh_assert_less (s, this->n_sides());
     117             : 
     118    33254219 :   return this->compute_key(this->node_id(Hex8::side_nodes_map[s][0]),
     119    32354539 :                            this->node_id(Hex8::side_nodes_map[s][1]),
     120    32354539 :                            this->node_id(Hex8::side_nodes_map[s][2]),
     121    33254231 :                            this->node_id(Hex8::side_nodes_map[s][3]));
     122             : }
     123             : 
     124             : 
     125             : 
     126     3970039 : unsigned int Hex::local_side_node(unsigned int side,
     127             :                                   unsigned int side_node) const
     128             : {
     129      330322 :   libmesh_assert_less (side, this->n_sides());
     130      330322 :   libmesh_assert_less (side_node, Hex8::nodes_per_side);
     131             : 
     132     3970039 :   return Hex8::side_nodes_map[side][side_node];
     133             : }
     134             : 
     135             : 
     136             : 
     137   157743520 : unsigned int Hex::local_edge_node(unsigned int edge,
     138             :                                   unsigned int edge_node) const
     139             : {
     140    11805302 :   libmesh_assert_less (edge, this->n_edges());
     141    11805302 :   libmesh_assert_less (edge_node, Hex8::nodes_per_edge);
     142             : 
     143   157743520 :   return Hex8::edge_nodes_map[edge][edge_node];
     144             : }
     145             : 
     146             : 
     147             : 
     148   546721277 : std::unique_ptr<Elem> Hex::side_ptr (const unsigned int i)
     149             : {
     150    44766268 :   libmesh_assert_less (i, this->n_sides());
     151             : 
     152   546721277 :   std::unique_ptr<Elem> face = std::make_unique<Quad4>();
     153             : 
     154  2733606385 :   for (auto n : face->node_index_range())
     155  2365950180 :     face->set_node(n, this->node_ptr(Hex8::side_nodes_map[i][n]));
     156             : 
     157   546721277 :   return face;
     158           0 : }
     159             : 
     160             : 
     161             : 
     162    28156828 : void Hex::side_ptr (std::unique_ptr<Elem> & side,
     163             :                     const unsigned int i)
     164             : {
     165    28156828 :   this->simple_side_ptr<Hex,Hex8>(side, i, QUAD4);
     166    28156828 : }
     167             : 
     168             : 
     169             : 
     170     3509190 : bool Hex::is_child_on_side(const unsigned int c,
     171             :                            const unsigned int s) const
     172             : {
     173     1285960 :   libmesh_assert_less (c, this->n_children());
     174     1285960 :   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     3509190 :   const unsigned int node_child_map[8] = { 0, 1, 3, 2, 4, 5, 7, 6 };
     181             : 
     182    13524906 :   for (unsigned int i = 0; i != 4; ++i)
     183    11624470 :     if (node_child_map[Hex8::side_nodes_map[s][i]] == c)
     184      585656 :       return true;
     185             : 
     186      700304 :   return false;
     187             : }
     188             : 
     189             : 
     190             : 
     191    18727108 : bool Hex::is_edge_on_side(const unsigned int e,
     192             :                           const unsigned int s) const
     193             : {
     194    11132724 :   libmesh_assert_less (e, this->n_edges());
     195    11132724 :   libmesh_assert_less (s, this->n_sides());
     196             : 
     197    18727108 :   return (edge_sides_map[e][0] == s || edge_sides_map[e][1] == s);
     198             : }
     199             : 
     200             : 
     201             : 
     202       13824 : std::vector<unsigned int> Hex::sides_on_edge(const unsigned int e) const
     203             : {
     204        1152 :   libmesh_assert_less(e, this->n_edges());
     205             : 
     206       13824 :   return {edge_sides_map[e][0], edge_sides_map[e][1]};
     207             : }
     208             : 
     209             : 
     210             : 
     211           0 : unsigned int Hex::opposite_side(const unsigned int side_in) const
     212             : {
     213           0 :   libmesh_assert_less (side_in, 6);
     214             :   static const unsigned char hex_opposites[6] = {5, 3, 4, 1, 2, 0};
     215           0 :   return hex_opposites[side_in];
     216             : }
     217             : 
     218             : 
     219             : 
     220           0 : unsigned int Hex::opposite_node(const unsigned int node_in,
     221             :                                 const unsigned int side_in) const
     222             : {
     223           0 :   libmesh_assert_less (node_in, 26);
     224           0 :   libmesh_assert_less (node_in, this->n_nodes());
     225           0 :   libmesh_assert_less (side_in, this->n_sides());
     226           0 :   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           0 :   switch (side_in)
     236             :     {
     237           0 :     case 0:
     238             :     case 5:
     239           0 :       return side05_nodes_map[node_in];
     240           0 :     case 1:
     241             :     case 3:
     242           0 :       return side13_nodes_map[node_in];
     243           0 :     case 2:
     244             :     case 4:
     245           0 :       return side24_nodes_map[node_in];
     246           0 :     default:
     247           0 :       libmesh_error_msg("Unsupported side_in = " << side_in);
     248             :     }
     249             : }
     250             : 
     251             : 
     252             : 
     253             : bool
     254        2760 : Hex::is_flipped() const
     255             : {
     256        2592 :   return (triple_product(this->point(1)-this->point(0),
     257        2592 :                          this->point(3)-this->point(0),
     258        3096 :                          this->point(4)-this->point(0)) < 0);
     259             : }
     260             : 
     261             : 
     262             : std::vector<unsigned int>
     263       26400 : Hex::edges_adjacent_to_node(const unsigned int n) const
     264             : {
     265        2200 :   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       26400 :   if (this->is_vertex(n))
     271       12480 :     return {std::begin(adjacent_edges_map[n]), std::end(adjacent_edges_map[n])};
     272       14880 :   else if (this->is_edge(n))
     273       11520 :     return {n - this->n_vertices()};
     274             : 
     275         280 :   libmesh_assert(this->is_face(n) || this->is_internal(n));
     276        3080 :   return {};
     277             : }
     278             : 
     279             : 
     280        2016 : Real Hex::quality (const ElemQuality q) const
     281             : {
     282        2016 :   switch (q)
     283             :     {
     284             : 
     285             : #if LIBMESH_DIM >= 3
     286             :       /**
     287             :        * Compute the min/max diagonal ratio.
     288             :        * Source: CUBIT User's Manual.
     289             :        */
     290           0 :     case DIAGONAL:
     291             :       {
     292             :         // Diagonal between node 0 and node 6
     293           0 :         const Real d06 = this->length(0,6);
     294             : 
     295             :         // Diagonal between node 3 and node 5
     296           0 :         const Real d35 = this->length(3,5);
     297             : 
     298             :         // Diagonal between node 1 and node 7
     299           0 :         const Real d17 = this->length(1,7);
     300             : 
     301             :         // Diagonal between node 2 and node 4
     302           0 :         const Real d24 = this->length(2,4);
     303             : 
     304             :         // Find the biggest and smallest diagonals
     305           0 :         const Real min = std::min(d06, std::min(d35, std::min(d17, d24)));
     306           0 :         const Real max = std::max(d06, std::max(d35, std::max(d17, d24)));
     307             : 
     308           0 :         libmesh_assert_not_equal_to (max, 0.0);
     309             : 
     310           0 :         return min / max;
     311             : 
     312             :         break;
     313             :       }
     314             : 
     315             :       /**
     316             :        * Minimum ratio of lengths derived from opposite edges.
     317             :        * Source: CUBIT User's Manual.
     318             :        */
     319           0 :     case TAPER:
     320             :       {
     321             : 
     322             :         /**
     323             :          * Compute the side lengths.
     324             :          */
     325           0 :         const Real d01 = this->length(0,1);
     326           0 :         const Real d12 = this->length(1,2);
     327           0 :         const Real d23 = this->length(2,3);
     328           0 :         const Real d03 = this->length(0,3);
     329           0 :         const Real d45 = this->length(4,5);
     330           0 :         const Real d56 = this->length(5,6);
     331           0 :         const Real d67 = this->length(6,7);
     332           0 :         const Real d47 = this->length(4,7);
     333           0 :         const Real d04 = this->length(0,4);
     334           0 :         const Real d15 = this->length(1,5);
     335           0 :         const Real d37 = this->length(3,7);
     336           0 :         const Real d26 = this->length(2,6);
     337             : 
     338           0 :         std::vector<Real> edge_ratios(12);
     339             :         // Front
     340           0 :         edge_ratios[0] = std::min(d01, d45) / std::max(d01, d45);
     341           0 :         edge_ratios[1] = std::min(d04, d15) / std::max(d04, d15);
     342             : 
     343             :         // Right
     344           0 :         edge_ratios[2] = std::min(d15, d26) / std::max(d15, d26);
     345           0 :         edge_ratios[3] = std::min(d12, d56) / std::max(d12, d56);
     346             : 
     347             :         // Back
     348           0 :         edge_ratios[4] = std::min(d67, d23) / std::max(d67, d23);
     349           0 :         edge_ratios[5] = std::min(d26, d37) / std::max(d26, d37);
     350             : 
     351             :         // Left
     352           0 :         edge_ratios[6] = std::min(d04, d37) / std::max(d04, d37);
     353           0 :         edge_ratios[7] = std::min(d03, d47) / std::max(d03, d47);
     354             : 
     355             :         // Bottom
     356           0 :         edge_ratios[8] = std::min(d01, d23) / std::max(d01, d23);
     357           0 :         edge_ratios[9] = std::min(d03, d12) / std::max(d03, d12);
     358             : 
     359             :         // Top
     360           0 :         edge_ratios[10] = std::min(d45, d67) / std::max(d45, d67);
     361           0 :         edge_ratios[11] = std::min(d56, d47) / std::max(d56, d47);
     362             : 
     363           0 :         return *(std::min_element(edge_ratios.begin(), edge_ratios.end())) ;
     364             : 
     365             :         break;
     366             :       }
     367             : 
     368             : 
     369             :       /**
     370             :        * Minimum edge length divided by max diagonal length.
     371             :        * Source: CUBIT User's Manual.
     372             :        */
     373           0 :     case STRETCH:
     374             :       {
     375           0 :         const Real sqrt3 = 1.73205080756888;
     376             : 
     377             :         /**
     378             :          * Compute the maximum diagonal.
     379             :          */
     380           0 :         const Real d06 = this->length(0,6);
     381           0 :         const Real d17 = this->length(1,7);
     382           0 :         const Real d35 = this->length(3,5);
     383           0 :         const Real d24 = this->length(2,4);
     384           0 :         const Real max_diag = std::max(d06, std::max(d17, std::max(d35, d24)));
     385             : 
     386           0 :         libmesh_assert_not_equal_to ( max_diag, 0.0 );
     387             : 
     388             :         /**
     389             :          * Compute the minimum edge length.
     390             :          */
     391           0 :         std::vector<Real> edges(12);
     392           0 :         edges[0]  = this->length(0,1);
     393           0 :         edges[1]  = this->length(1,2);
     394           0 :         edges[2]  = this->length(2,3);
     395           0 :         edges[3]  = this->length(0,3);
     396           0 :         edges[4]  = this->length(4,5);
     397           0 :         edges[5]  = this->length(5,6);
     398           0 :         edges[6]  = this->length(6,7);
     399           0 :         edges[7]  = this->length(4,7);
     400           0 :         edges[8]  = this->length(0,4);
     401           0 :         edges[9]  = this->length(1,5);
     402           0 :         edges[10] = this->length(2,6);
     403           0 :         edges[11] = this->length(3,7);
     404             : 
     405           0 :         const Real min_edge = *(std::min_element(edges.begin(), edges.end()));
     406           0 :         return sqrt3 * min_edge / max_diag ;
     407             :       }
     408             : 
     409             : 
     410           0 :     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           0 :           x0 = point(0), x1 = point(1), x2 = point(2), x3 = point(3),
     421           0 :           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           0 :         const Point a1 = -x0 + x1 - x2 + x3 + x4 - x5 + x6 - x7;
     429           0 :         const Point b1 =  x0 - x1 + x2 - x3 + x4 - x5 + x6 - x7;
     430           0 :         const Point c1 =  x0 - x1 - x2 + x3 - x4 + x5 + x6 - x7;
     431           0 :         const Point d1 = -x0 + x1 + x2 - x3 - x4 + x5 + x6 - x7;
     432             : 
     433           0 :         const Point a2 =  a1;
     434           0 :         const Point b2 =  b1;
     435           0 :         const Point c2 =  x0 + x1 - x2 - x3 - x4 - x5 + x6 + x7;
     436           0 :         const Point d2 = -x0 - x1 + x2 + x3 - x4 - x5 + x6 + x7;
     437             : 
     438           0 :         const Point a3 =  a1;
     439           0 :         const Point b3 =  c1;
     440           0 :         const Point c3 =  c2;
     441           0 :         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           0 :             RealTensor(d1, b2 + d2, b3 + d3),
     453           0 :             RealTensor(b1 + d1, b2 + d2, a3 + b3 + c3 + d3),
     454           0 :             RealTensor(b1 + d1, d2, c3 + d3),
     455           0 :             RealTensor(c1 + d1, c2 + d2, d3),
     456           0 :             RealTensor(c1 + d1, a2 + b2 + c2 + d2, b3 + d3),
     457           0 :             RealTensor(a1 + b1 + c1 + d1, a2 + b2 + c2 + d2, a3 + b3 + c3 + d3),
     458           0 :             RealTensor(a1 + b1 + c1 + d1, c2 + d2, c3 + d3)
     459           0 :           }};
     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           0 :         for (unsigned int k=0; k<alpha.size(); ++k)
     467             :           {
     468           0 :             alpha[k] = A[k].det();
     469           0 :             if (alpha[k] <= 0.)
     470           0 :               return 0.;
     471             :           }
     472             : 
     473             :         // Compute metric tensors, T_k = A_k^T * A_k.
     474           0 :         std::array<RealTensor, 8> T;
     475           0 :         for (unsigned int k=0; k<T.size(); ++k)
     476           0 :           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           0 :         Real den = 0.;
     481           0 :         if (q == SHAPE)
     482             :           {
     483           0 :             for (unsigned int k=0; k<T.size(); ++k)
     484           0 :               den += T[k].tr() / std::pow(alpha[k], 2./3.);
     485           0 :             return (den == 0.) ? 0 : (24. / den);
     486             :           }
     487             :         else
     488             :           {
     489           0 :             for (unsigned int k=0; k<T.size(); ++k)
     490           0 :               den += std::pow(std::sqrt(T[k](0,0) * T[k](1,1) * T[k](2,2)) / alpha[k], 2./3.);
     491           0 :             return (den == 0.) ? 0 : (8. / den);
     492             :           }
     493             :       }
     494             : #endif // LIBMESH_DIM >= 3
     495             : 
     496             :       /**
     497             :        * I don't know what to do for this metric.
     498             :        * Maybe the base class knows...
     499             :        */
     500        2016 :     default:
     501        2016 :       return Elem::quality(q);
     502             :     }
     503             : }
     504             : 
     505             : 
     506             : 
     507           0 : std::pair<Real, Real> Hex::qual_bounds (const ElemQuality q) const
     508             : {
     509           0 :   std::pair<Real, Real> bounds;
     510             : 
     511           0 :   switch (q)
     512             :     {
     513             : 
     514           0 :     case ASPECT_RATIO:
     515           0 :       bounds.first  = 1.;
     516           0 :       bounds.second = 4.;
     517           0 :       break;
     518             : 
     519           0 :     case SKEW:
     520           0 :       bounds.first  = 0.;
     521           0 :       bounds.second = 0.5;
     522           0 :       break;
     523             : 
     524           0 :     case SHEAR:
     525             :     case SHAPE:
     526           0 :       bounds.first  = 0.3;
     527           0 :       bounds.second = 1.;
     528           0 :       break;
     529             : 
     530           0 :     case CONDITION:
     531           0 :       bounds.first  = 1.;
     532           0 :       bounds.second = 8.;
     533           0 :       break;
     534             : 
     535           0 :     case SCALED_JACOBIAN:
     536             :     case JACOBIAN:
     537           0 :       bounds.first  = 0.5;
     538           0 :       bounds.second = 1.;
     539           0 :       break;
     540             : 
     541           0 :     case DISTORTION:
     542           0 :       bounds.first  = 0.6;
     543           0 :       bounds.second = 1.;
     544           0 :       break;
     545             : 
     546           0 :     case TAPER:
     547           0 :       bounds.first  = 0.;
     548           0 :       bounds.second = 0.4;
     549           0 :       break;
     550             : 
     551           0 :     case STRETCH:
     552           0 :       bounds.first  = 0.25;
     553           0 :       bounds.second = 1.;
     554           0 :       break;
     555             : 
     556           0 :     case DIAGONAL:
     557           0 :       bounds.first  = 0.65;
     558           0 :       bounds.second = 1.;
     559           0 :       break;
     560             : 
     561           0 :     case SIZE:
     562           0 :       bounds.first  = 0.5;
     563           0 :       bounds.second = 1.;
     564           0 :       break;
     565             : 
     566           0 :     default:
     567           0 :       libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
     568           0 :       bounds.first  = -1;
     569           0 :       bounds.second = -1;
     570             :     }
     571             : 
     572           0 :   return bounds;
     573             : }
     574             : 
     575             : 
     576             : 
     577    13777552 : bool Hex::on_reference_element(const Point & p,
     578             :                                const Real eps) const
     579             : {
     580     1473852 :   const Real & xi = p(0);
     581     1473852 :   const Real & eta = p(1);
     582     1473852 :   const Real & zeta = p(2);
     583             : 
     584             :   // The reference hexahedral element is [-1,1]^3.
     585    25671034 :   return ((xi   >= -1.-eps) &&
     586    11893482 :           (xi   <=  1.+eps) &&
     587     9157600 :           (eta  >= -1.-eps) &&
     588     7932478 :           (eta  <=  1.+eps) &&
     589    23068562 :           (zeta >= -1.-eps) &&
     590    14970844 :           (zeta <=  1.+eps));
     591             : }
     592             : 
     593             : 
     594             : 
     595             : const 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             : 
     605             : const 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             : 
     614             : const 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
     637             : const 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

Generated by: LCOV version 1.14