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

Generated by: LCOV version 1.14