LCOV - code coverage report
Current view: top level - src/geom - cell_hex8.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4343 (6ea38c) with base 8c3130 Lines: 175 187 93.6 %
Date: 2026-10-13 21:47:33 Functions: 21 23 91.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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_hex8.h"
      21             : #include "libmesh/edge_edge2.h"
      22             : #include "libmesh/face_quad4.h"
      23             : #include "libmesh/enum_io_package.h"
      24             : #include "libmesh/enum_order.h"
      25             : #include "libmesh/fe_lagrange_shape_1D.h"
      26             : 
      27             : // C++ includes
      28             : #include <array>
      29             : 
      30             : namespace libMesh
      31             : {
      32             : 
      33             : 
      34             : 
      35             : 
      36             : // ------------------------------------------------------------
      37             : // Hex8 class static member initializations
      38             : const int Hex8::num_nodes;
      39             : const int Hex8::nodes_per_side;
      40             : const int Hex8::nodes_per_edge;
      41             : 
      42             : // ------------------------------------------------------------
      43             : // Hex8 class member functions
      44             : 
      45    18430801 : bool Hex8::is_vertex(const unsigned int libmesh_dbg_var(n)) const
      46             : {
      47     1344568 :   libmesh_assert_not_equal_to (n, invalid_uint);
      48    18430801 :   return true;
      49             : }
      50             : 
      51           0 : bool Hex8::is_edge(const unsigned int) const
      52             : {
      53           0 :   return false;
      54             : }
      55             : 
      56           0 : bool Hex8::is_face(const unsigned int) const
      57             : {
      58           0 :   return false;
      59             : }
      60             : 
      61      930114 : bool Hex8::is_node_on_side(const unsigned int n,
      62             :                            const unsigned int s) const
      63             : {
      64       77245 :   libmesh_assert_less (s, n_sides());
      65       77245 :   return std::find(std::begin(side_nodes_map[s]),
      66      930114 :                    std::end(side_nodes_map[s]),
      67      930114 :                    n) != std::end(side_nodes_map[s]);
      68             : }
      69             : 
      70             : std::vector<unsigned>
      71    63750105 : Hex8::nodes_on_side(const unsigned int s) const
      72             : {
      73     4708962 :   libmesh_assert_less(s, n_sides());
      74    68459067 :   return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s])};
      75             : }
      76             : 
      77             : std::vector<unsigned>
      78        7764 : Hex8::nodes_on_edge(const unsigned int e) const
      79             : {
      80         600 :   libmesh_assert_less(e, n_edges());
      81        8364 :   return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
      82             : }
      83             : 
      84     1625184 : bool Hex8::is_node_on_edge(const unsigned int n,
      85             :                            const unsigned int e) const
      86             : {
      87       62824 :   libmesh_assert_less (e, n_edges());
      88       62824 :   return std::find(std::begin(edge_nodes_map[e]),
      89     1625184 :                    std::end(edge_nodes_map[e]),
      90     1625184 :                    n) != std::end(edge_nodes_map[e]);
      91             : }
      92             : 
      93             : 
      94             : 
      95     5907517 : bool Hex8::has_affine_map() const
      96             : {
      97             :   // Make sure x-edge endpoints are affine
      98      985236 :   Point v = this->point(1) - this->point(0);
      99     5825203 :   if (!v.relative_fuzzy_equals(this->point(2) - this->point(3), affine_tol) ||
     100    11719340 :       !v.relative_fuzzy_equals(this->point(5) - this->point(4), affine_tol) ||
     101     6303733 :       !v.relative_fuzzy_equals(this->point(6) - this->point(7), affine_tol))
     102       96506 :     return false;
     103             :   // Make sure xz-faces are identical parallelograms
     104     6297953 :   v = this->point(4) - this->point(0);
     105     5811011 :   if (!v.relative_fuzzy_equals(this->point(7) - this->point(3), affine_tol))
     106          24 :     return false;
     107             :   // If all the above checks out, the map is affine
     108      486930 :   return true;
     109             : }
     110             : 
     111             : 
     112             : 
     113   137451576 : Order Hex8::default_order() const
     114             : {
     115   137451576 :   return FIRST;
     116             : }
     117             : 
     118             : 
     119             : 
     120     1291068 : std::unique_ptr<Elem> Hex8::build_side_ptr (const unsigned int i)
     121             : {
     122     1291068 :   return this->simple_build_side_ptr<Quad4, Hex8>(i);
     123             : }
     124             : 
     125             : 
     126             : 
     127      546488 : void Hex8::build_side_ptr (std::unique_ptr<Elem> & side,
     128             :                            const unsigned int i)
     129             : {
     130      546488 :   this->simple_build_side_ptr<Hex8>(side, i, QUAD4);
     131      546488 : }
     132             : 
     133             : 
     134             : 
     135     6379110 : std::unique_ptr<Elem> Hex8::build_edge_ptr (const unsigned int i)
     136             : {
     137     6379110 :   return this->simple_build_edge_ptr<Edge2,Hex8>(i);
     138             : }
     139             : 
     140             : 
     141             : 
     142      135440 : void Hex8::build_edge_ptr (std::unique_ptr<Elem> & edge, const unsigned int i)
     143             : {
     144      135440 :   this->simple_build_edge_ptr<Hex8>(edge, i, EDGE2);
     145      135440 : }
     146             : 
     147             : 
     148             : 
     149      234943 : void Hex8::connectivity(const unsigned int libmesh_dbg_var(sc),
     150             :                         const IOPackage iop,
     151             :                         std::vector<dof_id_type> & conn) const
     152             : {
     153       20253 :   libmesh_assert(_nodes);
     154       20253 :   libmesh_assert_less (sc, this->n_sub_elem());
     155       20253 :   libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
     156             : 
     157      234943 :   conn.resize(8);
     158             : 
     159      234943 :   switch (iop)
     160             :     {
     161      234943 :     case TECPLOT:
     162             :       {
     163      255196 :         conn[0] = this->node_id(0)+1;
     164      234943 :         conn[1] = this->node_id(1)+1;
     165      234943 :         conn[2] = this->node_id(2)+1;
     166      234943 :         conn[3] = this->node_id(3)+1;
     167      234943 :         conn[4] = this->node_id(4)+1;
     168      234943 :         conn[5] = this->node_id(5)+1;
     169      234943 :         conn[6] = this->node_id(6)+1;
     170      234943 :         conn[7] = this->node_id(7)+1;
     171      234943 :         return;
     172             :       }
     173             : 
     174           0 :     case VTK:
     175             :       {
     176           0 :         for (auto i : index_range(conn))
     177           0 :           conn[i] = this->node_id(i);
     178           0 :         return;
     179             :       }
     180             : 
     181           0 :     default:
     182           0 :       libmesh_error_msg("Unsupported IO package " << iop);
     183             :     }
     184             : }
     185             : 
     186             : 
     187             : 
     188             : #ifdef LIBMESH_ENABLE_AMR
     189             : 
     190             : const Real Hex8::_embedding_matrix[Hex8::num_children][Hex8::num_nodes][Hex8::num_nodes] =
     191             :   {
     192             :     // The 8 children of the Hex-type elements can be thought of as being
     193             :     // associated with the 8 vertices of the Hex.  Some of the children are
     194             :     // numbered the same as their corresponding vertex, while some are
     195             :     // not.  The children which are numbered differently have been marked
     196             :     // with ** in the comments below.
     197             : 
     198             :     // embedding matrix for child 0 (child 0 is associated with vertex 0)
     199             :     {
     200             :       //  0     1     2     3     4     5     6     7
     201             :       { 1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 0
     202             :       { 0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 1
     203             :       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 2
     204             :       { 0.5,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.0}, // 3
     205             :       { 0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0}, // 4
     206             :       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 5
     207             :       {.125, .125, .125, .125, .125, .125, .125, .125}, // 6
     208             :       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}  // 7
     209             :     },
     210             : 
     211             :     // embedding matrix for child 1 (child 1 is associated with vertex 1)
     212             :     {
     213             :       //  0     1     2     3     4     5     6     7
     214             :       { 0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 0
     215             :       { 0.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 1
     216             :       { 0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0}, // 2
     217             :       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 3
     218             :       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 4
     219             :       { 0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0}, // 5
     220             :       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 6
     221             :       {.125, .125, .125, .125, .125, .125, .125, .125}  // 7
     222             :     },
     223             : 
     224             :     // embedding matrix for child 2 (child 2 is associated with vertex 3**)
     225             :     {
     226             :       //  0      1    2     3     4     5     6     7
     227             :       { 0.5,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.0}, // 0
     228             :       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 1
     229             :       { 0.0,  0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0}, // 2
     230             :       { 0.0,  0.0,  0.0,  1.0,  0.0,  0.0,  0.0,  0.0}, // 3
     231             :       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}, // 4
     232             :       {.125, .125, .125, .125, .125, .125, .125, .125}, // 5
     233             :       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}, // 6
     234             :       { 0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5}  // 7
     235             :     },
     236             : 
     237             :     // embedding matrix for child 3 (child 3 is associated with vertex 2**)
     238             :     {
     239             :       //  0      1    2     3     4     5     6     7
     240             :       { .25,  .25,  .25,  .25,  0.0,  0.0,  0.0,  0.0}, // 0
     241             :       { 0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0}, // 1
     242             :       { 0.0,  0.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0}, // 2
     243             :       { 0.0,  0.0,  0.5,  0.5,  0.0,  0.0,  0.0,  0.0}, // 3
     244             :       {.125, .125, .125, .125, .125, .125, .125, .125}, // 4
     245             :       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 5
     246             :       { 0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0}, // 6
     247             :       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}  // 7
     248             :     },
     249             : 
     250             :     // embedding matrix for child 4 (child 4 is associated with vertex 4)
     251             :     {
     252             :       //  0      1    2     3     4     5     6     7
     253             :       { 0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0}, // 0
     254             :       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 1
     255             :       {.125, .125, .125, .125, .125, .125, .125, .125}, // 2
     256             :       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}, // 3
     257             :       { 0.0,  0.0,  0.0,  0.0,  1.0,  0.0,  0.0,  0.0}, // 4
     258             :       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0,  0.0}, // 5
     259             :       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}, // 6
     260             :       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.5}  // 7
     261             :     },
     262             : 
     263             :     // embedding matrix for child 5 (child 5 is associated with vertex 5)
     264             :     {
     265             :       //  0      1    2     3     4     5     6     7
     266             :       { .25,  .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0}, // 0
     267             :       { 0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0}, // 1
     268             :       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 2
     269             :       {.125, .125, .125, .125, .125, .125, .125, .125}, // 3
     270             :       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0,  0.0}, // 4
     271             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  1.0,  0.0,  0.0}, // 5
     272             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0}, // 6
     273             :       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}  // 7
     274             :     },
     275             : 
     276             :     // embedding matrix for child 6 (child 6 is associated with vertex 7**)
     277             :     {
     278             :       //  0      1    2     3     4     5     6     7
     279             :       { .25,  0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25}, // 0
     280             :       {.125, .125, .125, .125, .125, .125, .125, .125}, // 1
     281             :       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}, // 2
     282             :       { 0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5}, // 3
     283             :       { 0.0,  0.0,  0.0,  0.0,  0.5,  0.0,  0.0,  0.5}, // 4
     284             :       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}, // 5
     285             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5}, // 6
     286             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  1.0}  // 7
     287             :     },
     288             : 
     289             :     // embedding matrix for child 7 (child 7 is associated with vertex 6**)
     290             :     {
     291             :       //  0      1    2     3     4     5     6     7
     292             :       {.125, .125, .125, .125, .125, .125, .125, .125}, // 0
     293             :       { 0.0,  .25,  .25,  0.0,  0.0,  .25,  .25,  0.0}, // 1
     294             :       { 0.0,  0.0,  0.5,  0.0,  0.0,  0.0,  0.5,  0.0}, // 2
     295             :       { 0.0,  0.0,  .25,  .25,  0.0,  0.0,  .25,  .25}, // 3
     296             :       { 0.0,  0.0,  0.0,  0.0,  .25,  .25,  .25,  .25}, // 4
     297             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5,  0.0}, // 5
     298             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  1.0,  0.0}, // 6
     299             :       { 0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.5,  0.5}  // 7
     300             :     }
     301             :   };
     302             : 
     303             : 
     304             : 
     305             : 
     306             : #endif
     307             : 
     308             : 
     309             : 
     310        9327 : Point Hex8::centroid_from_points(
     311             :   const Point & x0, const Point & x1, const Point & x2, const Point & x3,
     312             :   const Point & x4, const Point & x5, const Point & x6, const Point & x7)
     313             : {
     314             :   // The Jacobian is dx/d(xi) dot (dx/d(eta) cross dx/d(zeta)), where
     315             :   // dx/d(xi)   = a1*eta*zeta + b1*eta + c1*zeta + d1
     316             :   // dx/d(eta)  = a2*xi*zeta  + b2*xi  + c2*zeta + d2
     317             :   // dx/d(zeta) = a3*xi*eta   + b3*xi  + c3*eta  + d3
     318             : 
     319             :   // Notes:
     320             :   // 1.) Several of these coefficient vectors are equal, as noted below.
     321             :   // 2.) These are all off by a factor of 8, but this cancels when we
     322             :   //     divide by the volume, which will also be off by the same
     323             :   //     factor.
     324             :   Point
     325         554 :     a1 = -x0 + x1 - x2 + x3 + x4 - x5 + x6 - x7,
     326         554 :     a2 = a1,
     327         554 :     a3 = a1;
     328             : 
     329             :   Point
     330         554 :     b1 = x0 - x1 + x2 - x3 + x4 - x5 + x6 - x7,
     331         554 :     b2 = b1,
     332         554 :     b3 = x0 - x1 - x2 + x3 - x4 + x5 + x6 - x7;
     333             : 
     334             :   Point
     335         554 :     c1 = b3,
     336         554 :     c2 = x0 + x1 - x2 - x3 - x4 - x5 + x6 + x7,
     337         554 :     c3 = c2;
     338             : 
     339             :   Point
     340         554 :     d1 = -x0 + x1 + x2 - x3 - x4 + x5 + x6 - x7,
     341         554 :     d2 = -x0 - x1 + x2 + x3 - x4 - x5 + x6 + x7,
     342         554 :     d3 = -x0 - x1 - x2 - x3 + x4 + x5 + x6 + x7;
     343             : 
     344             :   // Use 2x2x2 quadrature to compute the integral of each basis
     345             :   // function (as defined on the [-1,1]^3 reference domain). We use
     346             :   // a quadrature rule which is exact for tri-cubics. The weights for
     347             :   // this rule are all equal to 1.
     348             :   static const Real q[2] = {-std::sqrt(Real(3))/3, std::sqrt(Real(3))/3.};
     349             : 
     350             :   // Indices for computing tensor product basis functions. This is
     351             :   // copied from fe_lagrange_shape_3D.C
     352             :   static const unsigned int i0[] = {0, 1, 1, 0, 0, 1, 1, 0};
     353             :   static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 1, 1};
     354             :   static const unsigned int i2[] = {0, 0, 0, 0, 1, 1, 1, 1};
     355             : 
     356             :   // Compute nodal volumes
     357        9327 :   std::array<Real, Hex8::num_nodes> V{};
     358             : 
     359       27981 :   for (const auto & xi : q)
     360       55962 :     for (const auto & eta : q)
     361      111924 :       for (const auto & zeta : q)
     362             :       {
     363       70184 :         Real jxw = triple_product(a1*eta*zeta + b1*eta + c1*zeta + d1,
     364       74616 :                                   a2*xi*zeta  + b2*xi  + c2*zeta + d2,
     365       79048 :                                   a3*xi*eta   + b3*xi  + c3*eta  + d3);
     366             : 
     367      671544 :         for (int i=0; i<Hex8::num_nodes; ++i)
     368     1158400 :           V[i] += jxw *
     369      596928 :             fe_lagrange_1D_linear_shape(i0[i], xi) *
     370     1158400 :             fe_lagrange_1D_linear_shape(i1[i], eta) *
     371      596928 :             fe_lagrange_1D_linear_shape(i2[i], zeta);
     372             :       }
     373             : 
     374             :   // Compute centroid
     375             :   return
     376         554 :     (x0*V[0] + x1*V[1] + x2*V[2] + x3*V[3] + x4*V[4] + x5*V[5] + x6*V[6] + x7*V[7]) /
     377       10435 :     (V[0] + V[1] + V[2] + V[3] + V[4] + V[5] + V[6] + V[7]);
     378             : }
     379             : 
     380             : 
     381        2968 : Point Hex8::true_centroid () const
     382             : {
     383             :   return Hex8::centroid_from_points
     384        2536 :     (point(0), point(1), point(2), point(3),
     385        3184 :      point(4), point(5), point(6), point(7));
     386             : }
     387             : 
     388             : 
     389      248807 : Real Hex8::volume () const
     390             : {
     391             :   // This specialization is good for Lagrange mappings only in general
     392      248807 :   if (this->mapping_type() != LAGRANGE_MAP)
     393          44 :     return this->Elem::volume();
     394             : 
     395             :   // Make copies of our points.  It makes the subsequent calculations a bit
     396             :   // shorter and avoids dereferencing the same pointer multiple times.
     397             :   Point
     398      331219 :     x0 = point(0), x1 = point(1), x2 = point(2), x3 = point(3),
     399      310605 :     x4 = point(4), x5 = point(5), x6 = point(6), x7 = point(7);
     400             : 
     401             :   // Construct constant data vectors.  The notation is:
     402             :   // \vec{x}_{\xi}   = \vec{a1}*eta*zeta + \vec{b1}*eta + \vec{c1}*zeta + \vec{d1}
     403             :   // \vec{x}_{\eta}  = \vec{a2}*xi*zeta  + \vec{b2}*xi  + \vec{c2}*zeta + \vec{d2}
     404             :   // \vec{x}_{\zeta} = \vec{a3}*xi*eta   + \vec{b3}*xi  + \vec{c3}*eta  + \vec{d3}
     405             :   // but it turns out that a1, a2, and a3 are not needed for the volume calculation.
     406             : 
     407             :   // Build up the 6 unique vectors which make up dx/dxi, dx/deta, and dx/dzeta.
     408             :   Point q[6] =
     409             :     {
     410       21043 :       /*b1*/  x0 - x1 + x2 - x3 + x4 - x5 + x6 - x7, /*=b2*/
     411       21043 :       /*c1*/  x0 - x1 - x2 + x3 - x4 + x5 + x6 - x7, /*=b3*/
     412       21043 :       /*d1*/ -x0 + x1 + x2 - x3 - x4 + x5 + x6 - x7,
     413       21043 :       /*c2*/  x0 + x1 - x2 - x3 - x4 - x5 + x6 + x7, /*=c3*/
     414       21043 :       /*d2*/ -x0 - x1 + x2 + x3 - x4 - x5 + x6 + x7,
     415       21043 :       /*d3*/ -x0 - x1 - x2 - x3 + x4 + x5 + x6 + x7
     416      147301 :     };
     417             : 
     418             :   // We could check for a linear element, but it's probably faster to
     419             :   // just compute the result...
     420             :   return
     421      248763 :     (triple_product(q[0], q[4], q[3]) +
     422      248763 :      triple_product(q[2], q[0], q[1]) +
     423      248763 :      triple_product(q[1], q[3], q[5])) / 192. +
     424      248763 :     triple_product(q[2], q[4], q[5]) / 64.;
     425             : }
     426             : 
     427             : BoundingBox
     428    10295000 : Hex8::loose_bounding_box () const
     429             : {
     430    10295000 :   return Elem::loose_bounding_box();
     431             : }
     432             : 
     433             : 
     434             : void
     435        8532 : Hex8::permute(unsigned int perm_num)
     436             : {
     437         792 :   libmesh_assert_less (perm_num, 24);
     438        8532 :   const unsigned int side = perm_num % 6;
     439        8532 :   const unsigned int rotate = perm_num / 6;
     440             : 
     441       23760 :   for (unsigned int i = 0; i != rotate; ++i)
     442             :     {
     443       15228 :       swap4nodes(0,1,2,3);
     444       15228 :       swap4nodes(4,5,6,7);
     445       13716 :       swap4neighbors(1,2,3,4);
     446             :     }
     447             : 
     448        8532 :   switch (side) {
     449          96 :   case 0:
     450          96 :     break;
     451        1152 :   case 1:
     452        1152 :     swap4nodes(3,7,4,0);
     453        1152 :     swap4nodes(2,6,5,1);
     454        1056 :     swap4neighbors(0,3,5,1);
     455        1056 :     break;
     456        1152 :   case 2:
     457        1152 :     swap4nodes(0,4,5,1);
     458        1152 :     swap4nodes(3,7,6,2);
     459        1056 :     swap4neighbors(0,4,5,2);
     460        1056 :     break;
     461        1152 :   case 3:
     462        1152 :     swap4nodes(0,4,7,3);
     463        1152 :     swap4nodes(1,5,6,2);
     464        1056 :     swap4neighbors(0,1,5,3);
     465        1056 :     break;
     466        1152 :   case 4:
     467        1152 :     swap4nodes(1,5,4,0);
     468        1152 :     swap4nodes(2,6,7,3);
     469        1056 :     swap4neighbors(0,2,5,4);
     470        1056 :     break;
     471        2772 :   case 5:
     472        2772 :     swap2nodes(0,7);
     473        2772 :     swap2nodes(1,6);
     474        2772 :     swap2nodes(2,5);
     475        2772 :     swap2nodes(3,4);
     476         312 :     swap2neighbors(0,5);
     477         312 :     swap2neighbors(1,3);
     478         312 :     break;
     479           0 :   default:
     480           0 :     libmesh_error();
     481             :   }
     482        8532 : }
     483             : 
     484             : 
     485             : void
     486         288 : Hex8::flip(BoundaryInfo * boundary_info)
     487             : {
     488          24 :   libmesh_assert(boundary_info);
     489             : 
     490         288 :   swap2nodes(0,1);
     491         288 :   swap2nodes(2,3);
     492         288 :   swap2nodes(4,5);
     493         288 :   swap2nodes(6,7);
     494          24 :   swap2neighbors(2,4);
     495         288 :   swap2boundarysides(2,4,boundary_info);
     496         288 :   swap2boundaryedges(1,3,boundary_info);
     497         288 :   swap2boundaryedges(4,5,boundary_info);
     498         288 :   swap2boundaryedges(6,7,boundary_info);
     499         288 :   swap2boundaryedges(9,11,boundary_info);
     500         288 : }
     501             : 
     502             : 
     503             : ElemType
     504   126704454 : Hex8::side_type (const unsigned int libmesh_dbg_var(s)) const
     505             : {
     506     9378651 :   libmesh_assert_less (s, 6);
     507   126704454 :   return QUAD4;
     508             : }
     509             : 
     510             : 
     511             : Point
     512         852 : Hex8::side_vertex_average_normal(const unsigned int s) const
     513             : {
     514          24 :   libmesh_assert_less (s, 6);
     515          24 :   libmesh_assert_equal_to(this->mapping_type(), LAGRANGE_MAP);
     516             : 
     517             :   // At the side vertex average, things simplify a bit
     518             :   // We get the side "plane" normal at all vertices, then average them
     519          24 :   Point normal;
     520         900 :   Point current_edge = this->point(side_nodes_map[s][1]) -
     521         852 :                        this->point(side_nodes_map[s][0]);
     522        4260 :   for (auto i : make_range(4))
     523             :   {
     524        3600 :     const Point next_edge = this->point(side_nodes_map[s][(i + 2) % 4]) -
     525        3408 :                             this->point(side_nodes_map[s][(i + 1) % 4]);
     526        3312 :     const Point normal_at_vertex = current_edge.cross(next_edge);
     527             :     // Note: unweighted and unnormalized sum matches the FE computation of normals
     528          96 :     normal += normal_at_vertex;
     529        3312 :     current_edge = next_edge;
     530             :   }
     531          24 :   normal /= 4;
     532         852 :   return normal.unit();
     533             : }
     534             : 
     535             : 
     536             : } // namespace libMesh

Generated by: LCOV version 1.14