LCOV - code coverage report
Current view: top level - src/fe - hdiv_fe_transformation.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4529 (d6a6ff) with base 9779e6 Lines: 181 209 86.6 %
Date: 2026-09-01 14:14:34 Functions: 7 14 50.0 %
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             : #include "libmesh/hdiv_fe_transformation.h"
      19             : #include "libmesh/fe_interface.h"
      20             : #include "libmesh/int_range.h"
      21             : 
      22             : namespace {
      23             : 
      24             : using namespace libMesh;
      25             : 
      26             : // The contravariant Piola map phi = J^{-1} * (dx/dxi) * phihat, shared by
      27             : // map_phi and map_dphi (which also needs the physical shape function value
      28             : // for the term coming from the derivative of J^{-1}).
      29             : template<typename OutputShape>
      30     8661238 : OutputShape hdiv_piola_map(const RealGradient & dx_dxi,
      31             :                            const RealGradient & dx_deta,
      32             :                            Real J,
      33             :                            const OutputShape & phi_ref)
      34             : {
      35     2848736 :   OutputShape phi_val;
      36    11509974 :   phi_val(0) = (dx_dxi(0)*phi_ref(0) + dx_deta(0)*phi_ref(1))/J;
      37    11509974 :   phi_val(1) = (dx_dxi(1)*phi_ref(0) + dx_deta(1)*phi_ref(1))/J;
      38             : #if LIBMESH_DIM > 2
      39    11509974 :   phi_val(2) = (dx_dxi(2)*phi_ref(0) + dx_deta(2)*phi_ref(1))/J;
      40             : #endif
      41     8661238 :   return phi_val;
      42             : }
      43             : 
      44             : template<typename OutputShape>
      45    29182982 : OutputShape hdiv_piola_map(const RealGradient & dx_dxi,
      46             :                            const RealGradient & dx_deta,
      47             :                            const RealGradient & dx_dzeta,
      48             :                            Real J,
      49             :                            const OutputShape & phi_ref)
      50             : {
      51     6607276 :   OutputShape phi_val;
      52    29182982 :   phi_val(0) = (dx_dxi(0)*phi_ref(0) + dx_deta(0)*phi_ref(1) + dx_dzeta(0)*phi_ref(2))/J;
      53    29182982 :   phi_val(1) = (dx_dxi(1)*phi_ref(0) + dx_deta(1)*phi_ref(1) + dx_dzeta(1)*phi_ref(2))/J;
      54    29182982 :   phi_val(2) = (dx_dxi(2)*phi_ref(0) + dx_deta(2)*phi_ref(1) + dx_dzeta(2)*phi_ref(2))/J;
      55    29182982 :   return phi_val;
      56             : }
      57             : 
      58             : } // anonymous namespace
      59             : 
      60             : namespace libMesh
      61             : {
      62             : 
      63             : template<typename OutputShape>
      64     1339905 : void HDivFETransformation<OutputShape>::init_map_phi(const FEGenericBase<OutputShape> & fe) const
      65             : {
      66      319974 :   fe.get_fe_map().get_dxidx();
      67     1339905 : }
      68             : 
      69             : 
      70             : 
      71             : template<typename OutputShape>
      72      485047 : void HDivFETransformation<OutputShape>::init_map_dphi(const FEGenericBase<OutputShape> & fe) const
      73             : {
      74      111482 :   fe.get_fe_map().get_dxidx();
      75             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      76      111482 :   fe.get_fe_map().get_d2xyzdxi2();
      77             : #endif
      78      485047 : }
      79             : 
      80             : 
      81             : 
      82             : template<typename OutputShape>
      83           0 : void HDivFETransformation<OutputShape>::init_map_d2phi(const FEGenericBase<OutputShape> & fe) const
      84             : {
      85           0 :   fe.get_fe_map().get_dxidx();
      86             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      87           0 :   fe.get_fe_map().get_d2xidxyz2();
      88             : #endif
      89           0 : }
      90             : 
      91             : 
      92             : 
      93             : template<typename OutputShape>
      94      509996 : void HDivFETransformation<OutputShape>::map_phi(const unsigned int dim,
      95             :                                                 const Elem * const elem,
      96             :                                                 const std::vector<Point> & qp,
      97             :                                                 const FEGenericBase<OutputShape> & fe,
      98             :                                                 std::vector<std::vector<OutputShape>> & phi,
      99             :                                                 const bool /*add_p_level*/) const
     100             : {
     101      509996 :   switch (dim)
     102             :     {
     103           0 :     case 0:
     104             :     case 1:
     105           0 :       libmesh_error_msg("These element transformations only make sense in 2D and 3D.");
     106             : 
     107      157032 :     case 2:
     108             :       {
     109       38662 :         const std::vector<RealGradient> & dxyz_dxi   = fe.get_fe_map().get_dxyzdxi();
     110       38662 :         const std::vector<RealGradient> & dxyz_deta  = fe.get_fe_map().get_dxyzdeta();
     111             : 
     112       38662 :         const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
     113             : 
     114             :         // phi = J^{-1} * (dx/dxi) * \hat{phi}
     115     1101900 :         for (auto i : index_range(phi))
     116     9086222 :           for (auto p : index_range(phi[i]))
     117             :             {
     118             :               // Need to temporarily cache reference shape functions
     119             :               // We are computing mapping basis functions, so we explicitly ignore
     120             :               // any non-zero p_level() the Elem might have.
     121     2016562 :               OutputShape phi_ref;
     122    12174478 :               FEInterface::shape(fe.get_fe_type(), /*extra_order=*/0, elem, i, qp[p], phi_ref);
     123             : 
     124    18224164 :               phi[i][p] = hdiv_piola_map(dxyz_dxi[p], dxyz_deta[p], J[p], phi_ref);
     125             :             }
     126             : 
     127       38662 :         break;
     128             :       }
     129      352964 :     case 3:
     130             :       {
     131       81444 :         const std::vector<RealGradient> & dxyz_dxi   = fe.get_fe_map().get_dxyzdxi();
     132       81444 :         const std::vector<RealGradient> & dxyz_deta  = fe.get_fe_map().get_dxyzdeta();
     133       81444 :         const std::vector<RealGradient> & dxyz_dzeta = fe.get_fe_map().get_dxyzdzeta();
     134             : 
     135       81444 :         const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
     136             : 
     137             :         // phi = J^{-1} * (dx/dxi) * \hat{phi}
     138     1977784 :         for (auto i : index_range(phi))
     139    23079828 :           for (auto p : index_range(phi[i]))
     140             :             {
     141             :               // Need to temporarily cache reference shape functions
     142             :               // We are computing mapping basis functions, so we explicitly ignore
     143             :               // any non-zero p_level() the Elem might have.
     144     4879292 :               OutputShape phi_ref;
     145    31213592 :               FEInterface::shape(fe.get_fe_type(), /*extra_order=*/0, elem, i, qp[p], phi_ref);
     146             : 
     147    40972176 :               phi[i][p] = hdiv_piola_map(dxyz_dxi[p], dxyz_deta[p], dxyz_dzeta[p], J[p], phi_ref);
     148             :             }
     149             : 
     150       81444 :         break;
     151             :       }
     152             : 
     153           0 :     default:
     154           0 :       libmesh_error_msg("Invalid dim = " << dim);
     155             :     } // switch(dim)
     156      509996 : }
     157             : 
     158             : template<typename OutputShape>
     159      113819 : void HDivFETransformation<OutputShape>::map_dphi(const unsigned int dim,
     160             :                                                   const Elem * const elem,
     161             :                                                   const std::vector<Point> & qp,
     162             :                                                   const FEGenericBase<OutputShape> & fe,
     163             :                                                   std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputGradient>> & dphi,
     164             :                                                   std::vector<std::vector<OutputShape>> & dphidx,
     165             :                                                   std::vector<std::vector<OutputShape>> & dphidy,
     166             :                                                   std::vector<std::vector<OutputShape>> & dphidz) const
     167             : {
     168             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     169      113819 :   switch (dim)
     170             :     {
     171           0 :     case 0:
     172             :     case 1:
     173           0 :       libmesh_error_msg("These element transformations only make sense in 2D and 3D.");
     174             : 
     175       30770 :     case 2:
     176             :       {
     177        7374 :         const std::vector<RealGradient> & dxyz_dxi   = fe.get_fe_map().get_dxyzdxi();
     178        7374 :         const std::vector<RealGradient> & dxyz_deta  = fe.get_fe_map().get_dxyzdeta();
     179             : 
     180        7374 :         const std::vector<RealGradient> & d2xyz_dxi2    = fe.get_fe_map().get_d2xyzdxi2();
     181        7374 :         const std::vector<RealGradient> & d2xyz_deta2   = fe.get_fe_map().get_d2xyzdeta2();
     182        7374 :         const std::vector<RealGradient> & d2xyz_dxideta = fe.get_fe_map().get_d2xyzdxideta();
     183             : 
     184        7374 :         const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
     185             : 
     186        7374 :         const std::vector<Real> & dxi_dx  = fe.get_fe_map().get_dxidx();
     187        7374 :         const std::vector<Real> & dxi_dy  = fe.get_fe_map().get_dxidy();
     188        7374 :         const std::vector<Real> & deta_dx = fe.get_fe_map().get_detadx();
     189        7374 :         const std::vector<Real> & deta_dy = fe.get_fe_map().get_detady();
     190             : #if LIBMESH_DIM > 2
     191        7374 :         const std::vector<Real> & dxi_dz  = fe.get_fe_map().get_dxidz();
     192        7374 :         const std::vector<Real> & deta_dz = fe.get_fe_map().get_detadz();
     193             : #endif
     194             : 
     195        7374 :         const std::vector<std::vector<OutputShape>> & dphi_dxi  = fe.get_dphidxi();
     196        7374 :         const std::vector<std::vector<OutputShape>> & dphi_deta = fe.get_dphideta();
     197             : 
     198      256670 :         for (auto i : index_range(dphi))
     199     3594520 :           for (auto p : index_range(dphi[i]))
     200             :             {
     201             :               // Need to temporarily cache reference shape functions
     202             :               // We are computing mapping basis functions, so we explicitly ignore
     203             :               // any non-zero p_level() the Elem might have.
     204      832174 :               OutputShape phi_ref;
     205     5032968 :               FEInterface::shape(fe.get_fe_type(), /*extra_order=*/0, elem, i, qp[p], phi_ref);
     206             : 
     207             :               const OutputShape phi_val =
     208     5032968 :                 hdiv_piola_map(dxyz_dxi[p], dxyz_deta[p], J[p], phi_ref);
     209             : 
     210             :               // Jacobi's formula: dJ/dxi_n = J * tr(F^{-1} * dF/dxi_n)
     211     3368620 :               Real dJ_dxi =
     212     5865142 :                 J[p] * (dxi_dx[p]*d2xyz_dxi2[p](0)    + deta_dx[p]*d2xyz_dxideta[p](0) +
     213     4200794 :                         dxi_dy[p]*d2xyz_dxi2[p](1)    + deta_dy[p]*d2xyz_dxideta[p](1));
     214     3368620 :               Real dJ_deta =
     215     3368620 :                 J[p] * (dxi_dx[p]*d2xyz_dxideta[p](0) + deta_dx[p]*d2xyz_deta2[p](0) +
     216     4200794 :                         dxi_dy[p]*d2xyz_dxideta[p](1) + deta_dy[p]*d2xyz_deta2[p](1));
     217             : #if LIBMESH_DIM > 2
     218     4200794 :               dJ_dxi  += J[p] * (dxi_dz[p]*d2xyz_dxi2[p](2)    + deta_dz[p]*d2xyz_dxideta[p](2));
     219     3368620 :               dJ_deta += J[p] * (dxi_dz[p]*d2xyz_dxideta[p](2) + deta_dz[p]*d2xyz_deta2[p](2));
     220             : #endif
     221             : 
     222    13474480 :               for (unsigned int k = 0; k < LIBMESH_DIM; ++k)
     223             :                 {
     224             :                   // dphi_k/dx_l = A + B + C, where (n, m summed over reference directions):
     225             :                   //   A = -phi_k(x) * SUM_n (dxi_n/dx_l) * (1/J) * (dJ/dxi_n)
     226             :                   //   B =  (1/J) * SUM_n (dxi_n/dx_l) * SUM_m (d^2 x_k/dxi_m dxi_n) * phihat_m
     227             :                   //   C =  (1/J) * SUM_n (dxi_n/dx_l) * SUM_m F_{km} * dphihat_m/dxi_n
     228             : 
     229             :                   // Term A: -phi_k(x) * SUM_n (dxi_n/dx_l)*(1/J)*(dJ/dxi_n)
     230    10105860 :                   const Real phik = (k == 0) ? phi_val(0) : (k == 1) ? phi_val(1) : phi_val(2);
     231             : 
     232             :                   // Term B: (1/J) * SUM_n (dxi_n/dx_l) * SUM_m (d^2 x_k/dxi_m dxi_n) * phihat_m
     233    10105860 :                   const Real d2x_k_dxi2    = (k == 0) ? d2xyz_dxi2[p](0)    : (k == 1) ? d2xyz_dxi2[p](1)    : d2xyz_dxi2[p](2);
     234    10105860 :                   const Real d2x_k_deta2   = (k == 0) ? d2xyz_deta2[p](0)   : (k == 1) ? d2xyz_deta2[p](1)   : d2xyz_deta2[p](2);
     235    10105860 :                   const Real d2x_k_dxideta = (k == 0) ? d2xyz_dxideta[p](0) : (k == 1) ? d2xyz_dxideta[p](1) : d2xyz_dxideta[p](2);
     236             : 
     237    10105860 :                   const Real dphik_dxi_B  = (d2x_k_dxi2*phi_ref(0)    + d2x_k_dxideta*phi_ref(1))/J[p];
     238    10105860 :                   const Real dphik_deta_B = (d2x_k_dxideta*phi_ref(0) + d2x_k_deta2*phi_ref(1))/J[p];
     239             : 
     240             :                   // Term C: (1/J) * SUM_n (dxi_n/dx_l) * SUM_m F_{km} * dphihat_m/dxi_n
     241    10105860 :                   const Real Fk_xi  = (k == 0) ? dxyz_dxi[p](0)  : (k == 1) ? dxyz_dxi[p](1)  : dxyz_dxi[p](2);
     242    10105860 :                   const Real Fk_eta = (k == 0) ? dxyz_deta[p](0) : (k == 1) ? dxyz_deta[p](1) : dxyz_deta[p](2);
     243             : 
     244    12602382 :                   const Real dphik_dxi_C  = (Fk_xi*dphi_dxi[i][p](0)  + Fk_eta*dphi_dxi[i][p](1))/J[p];
     245    12602382 :                   const Real dphik_deta_C = (Fk_xi*dphi_deta[i][p](0) + Fk_eta*dphi_deta[i][p](1))/J[p];
     246             : 
     247    10105860 :                   const Real dphik_dxi_total  = -phik*dJ_dxi/J[p]  + dphik_dxi_B  + dphik_dxi_C;
     248    10105860 :                   const Real dphik_deta_total = -phik*dJ_deta/J[p] + dphik_deta_B + dphik_deta_C;
     249             : 
     250    12602382 :                   dphidx[i][p](k) = dxi_dx[p]*dphik_dxi_total + deta_dx[p]*dphik_deta_total;
     251    12602382 :                   dphidy[i][p](k) = dxi_dy[p]*dphik_dxi_total + deta_dy[p]*dphik_deta_total;
     252             : #if LIBMESH_DIM > 2
     253    15098904 :                   dphidz[i][p](k) = dxi_dz[p]*dphik_dxi_total + deta_dz[p]*dphik_deta_total;
     254             : #endif
     255             :                 }
     256             : 
     257     6697316 :               dphi[i][p].slice(0) = dphidx[i][p];
     258     4200794 :               dphi[i][p].slice(1) = dphidy[i][p];
     259             : #if LIBMESH_DIM > 2
     260     4200794 :               dphi[i][p].slice(2) = dphidz[i][p];
     261             : #endif
     262             :             }
     263             : 
     264        7374 :         break;
     265             :       }
     266       83049 :     case 3:
     267             :       {
     268       18670 :         const std::vector<RealGradient> & dxyz_dxi   = fe.get_fe_map().get_dxyzdxi();
     269       18670 :         const std::vector<RealGradient> & dxyz_deta  = fe.get_fe_map().get_dxyzdeta();
     270       18670 :         const std::vector<RealGradient> & dxyz_dzeta = fe.get_fe_map().get_dxyzdzeta();
     271             : 
     272       18670 :         const std::vector<RealGradient> & d2xyz_dxi2     = fe.get_fe_map().get_d2xyzdxi2();
     273       18670 :         const std::vector<RealGradient> & d2xyz_deta2    = fe.get_fe_map().get_d2xyzdeta2();
     274       18670 :         const std::vector<RealGradient> & d2xyz_dzeta2   = fe.get_fe_map().get_d2xyzdzeta2();
     275       18670 :         const std::vector<RealGradient> & d2xyz_dxideta  = fe.get_fe_map().get_d2xyzdxideta();
     276       18670 :         const std::vector<RealGradient> & d2xyz_dxidzeta = fe.get_fe_map().get_d2xyzdxidzeta();
     277       18670 :         const std::vector<RealGradient> & d2xyz_detadzeta = fe.get_fe_map().get_d2xyzdetadzeta();
     278             : 
     279       18670 :         const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
     280             : 
     281       18670 :         const std::vector<Real> & dxi_dx   = fe.get_fe_map().get_dxidx();
     282       18670 :         const std::vector<Real> & dxi_dy   = fe.get_fe_map().get_dxidy();
     283       18670 :         const std::vector<Real> & dxi_dz   = fe.get_fe_map().get_dxidz();
     284       18670 :         const std::vector<Real> & deta_dx  = fe.get_fe_map().get_detadx();
     285       18670 :         const std::vector<Real> & deta_dy  = fe.get_fe_map().get_detady();
     286       18670 :         const std::vector<Real> & deta_dz  = fe.get_fe_map().get_detadz();
     287       18670 :         const std::vector<Real> & dzeta_dx = fe.get_fe_map().get_dzetadx();
     288       18670 :         const std::vector<Real> & dzeta_dy = fe.get_fe_map().get_dzetady();
     289       18670 :         const std::vector<Real> & dzeta_dz = fe.get_fe_map().get_dzetadz();
     290             : 
     291       18670 :         const std::vector<std::vector<OutputShape>> & dphi_dxi   = fe.get_dphidxi();
     292       18670 :         const std::vector<std::vector<OutputShape>> & dphi_deta  = fe.get_dphideta();
     293       18670 :         const std::vector<std::vector<OutputShape>> & dphi_dzeta = fe.get_dphidzeta();
     294             : 
     295      474875 :         for (auto i : index_range(dphi))
     296     8119800 :           for (auto p : index_range(dphi[i]))
     297             :             {
     298             :               // Need to temporarily cache reference shape functions
     299             :               // We are computing mapping basis functions, so we explicitly ignore
     300             :               // any non-zero p_level() the Elem might have.
     301     1727984 :               OutputShape phi_ref;
     302    11183942 :               FEInterface::shape(fe.get_fe_type(), /*extra_order=*/0, elem, i, qp[p], phi_ref);
     303             : 
     304             :               const OutputShape phi_val =
     305    14639910 :                 hdiv_piola_map(dxyz_dxi[p], dxyz_deta[p], dxyz_dzeta[p], J[p], phi_ref);
     306             : 
     307             :               // Jacobi's formula: dJ/dxi_n = J * tr(F^{-1} * dF/dxi_n)
     308     7727974 :               const Real dJ_dxi =
     309    18095878 :                 J[p] * (dxi_dx[p]*d2xyz_dxi2[p](0)     + deta_dx[p]*d2xyz_dxideta[p](0)  + dzeta_dx[p]*d2xyz_dxidzeta[p](0) +
     310    11183942 :                         dxi_dy[p]*d2xyz_dxi2[p](1)     + deta_dy[p]*d2xyz_dxideta[p](1)  + dzeta_dy[p]*d2xyz_dxidzeta[p](1) +
     311    11183942 :                         dxi_dz[p]*d2xyz_dxi2[p](2)     + deta_dz[p]*d2xyz_dxideta[p](2)  + dzeta_dz[p]*d2xyz_dxidzeta[p](2));
     312     7727974 :               const Real dJ_deta =
     313     9455958 :                 J[p] * (dxi_dx[p]*d2xyz_dxideta[p](0)  + deta_dx[p]*d2xyz_deta2[p](0)    + dzeta_dx[p]*d2xyz_detadzeta[p](0) +
     314    11183942 :                         dxi_dy[p]*d2xyz_dxideta[p](1)  + deta_dy[p]*d2xyz_deta2[p](1)    + dzeta_dy[p]*d2xyz_detadzeta[p](1) +
     315     9455958 :                         dxi_dz[p]*d2xyz_dxideta[p](2)  + deta_dz[p]*d2xyz_deta2[p](2)    + dzeta_dz[p]*d2xyz_detadzeta[p](2));
     316     7727974 :               const Real dJ_dzeta =
     317     7727974 :                 J[p] * (dxi_dx[p]*d2xyz_dxidzeta[p](0) + deta_dx[p]*d2xyz_detadzeta[p](0) + dzeta_dx[p]*d2xyz_dzeta2[p](0) +
     318    11183942 :                         dxi_dy[p]*d2xyz_dxidzeta[p](1) + deta_dy[p]*d2xyz_detadzeta[p](1) + dzeta_dy[p]*d2xyz_dzeta2[p](1) +
     319     7727974 :                         dxi_dz[p]*d2xyz_dxidzeta[p](2) + deta_dz[p]*d2xyz_detadzeta[p](2) + dzeta_dz[p]*d2xyz_dzeta2[p](2));
     320             : 
     321    30911896 :               for (unsigned int k = 0; k < 3; ++k)
     322             :                 {
     323             :                   // dphi_k/dx_l = A + B + C, where (n, m summed over reference directions):
     324             :                   //   A = -phi_k(x) * SUM_n (dxi_n/dx_l) * (1/J) * (dJ/dxi_n)
     325             :                   //   B =  (1/J) * SUM_n (dxi_n/dx_l) * SUM_m (d^2 x_k/dxi_m dxi_n) * phihat_m
     326             :                   //   C =  (1/J) * SUM_n (dxi_n/dx_l) * SUM_m F_{km} * dphihat_m/dxi_n
     327             : 
     328             :                   // Term A: -phi_k(x) * SUM_n (dxi_n/dx_l)*(1/J)*(dJ/dxi_n)
     329    23183922 :                   const Real phik = (k == 0) ? phi_val(0) : (k == 1) ? phi_val(1) : phi_val(2);
     330             : 
     331             :                   // Term B: (1/J) * SUM_n (dxi_n/dx_l) * SUM_m (d^2 x_k/dxi_m dxi_n) * phihat_m
     332    23183922 :                   const Real d2x_k_dxi2      = (k == 0) ? d2xyz_dxi2[p](0)      : (k == 1) ? d2xyz_dxi2[p](1)      : d2xyz_dxi2[p](2);
     333    23183922 :                   const Real d2x_k_deta2     = (k == 0) ? d2xyz_deta2[p](0)     : (k == 1) ? d2xyz_deta2[p](1)     : d2xyz_deta2[p](2);
     334    23183922 :                   const Real d2x_k_dzeta2    = (k == 0) ? d2xyz_dzeta2[p](0)    : (k == 1) ? d2xyz_dzeta2[p](1)    : d2xyz_dzeta2[p](2);
     335    23183922 :                   const Real d2x_k_dxideta   = (k == 0) ? d2xyz_dxideta[p](0)   : (k == 1) ? d2xyz_dxideta[p](1)   : d2xyz_dxideta[p](2);
     336    23183922 :                   const Real d2x_k_dxidzeta  = (k == 0) ? d2xyz_dxidzeta[p](0)  : (k == 1) ? d2xyz_dxidzeta[p](1)  : d2xyz_dxidzeta[p](2);
     337    23183922 :                   const Real d2x_k_detadzeta = (k == 0) ? d2xyz_detadzeta[p](0) : (k == 1) ? d2xyz_detadzeta[p](1) : d2xyz_detadzeta[p](2);
     338             : 
     339    23183922 :                   const Real dphik_dxi_B   = (d2x_k_dxi2*phi_ref(0)     + d2x_k_dxideta*phi_ref(1)   + d2x_k_dxidzeta*phi_ref(2))/J[p];
     340    23183922 :                   const Real dphik_deta_B  = (d2x_k_dxideta*phi_ref(0) + d2x_k_deta2*phi_ref(1)      + d2x_k_detadzeta*phi_ref(2))/J[p];
     341    23183922 :                   const Real dphik_dzeta_B = (d2x_k_dxidzeta*phi_ref(0) + d2x_k_detadzeta*phi_ref(1) + d2x_k_dzeta2*phi_ref(2))/J[p];
     342             : 
     343             :                   // Term C: (1/J) * SUM_n (dxi_n/dx_l) * SUM_m F_{km} * dphihat_m/dxi_n
     344    23183922 :                   const Real Fk_xi   = (k == 0) ? dxyz_dxi[p](0)   : (k == 1) ? dxyz_dxi[p](1)   : dxyz_dxi[p](2);
     345    23183922 :                   const Real Fk_eta  = (k == 0) ? dxyz_deta[p](0)  : (k == 1) ? dxyz_deta[p](1)  : dxyz_deta[p](2);
     346    23183922 :                   const Real Fk_zeta = (k == 0) ? dxyz_dzeta[p](0) : (k == 1) ? dxyz_dzeta[p](1) : dxyz_dzeta[p](2);
     347             : 
     348    28367874 :                   const Real dphik_dxi_C   = (Fk_xi*dphi_dxi[i][p](0)   + Fk_eta*dphi_dxi[i][p](1)   + Fk_zeta*dphi_dxi[i][p](2))/J[p];
     349    28367874 :                   const Real dphik_deta_C  = (Fk_xi*dphi_deta[i][p](0)  + Fk_eta*dphi_deta[i][p](1)  + Fk_zeta*dphi_deta[i][p](2))/J[p];
     350    28367874 :                   const Real dphik_dzeta_C = (Fk_xi*dphi_dzeta[i][p](0) + Fk_eta*dphi_dzeta[i][p](1) + Fk_zeta*dphi_dzeta[i][p](2))/J[p];
     351             : 
     352    23183922 :                   const Real dphik_dxi_total   = -phik*dJ_dxi/J[p]   + dphik_dxi_B   + dphik_dxi_C;
     353    23183922 :                   const Real dphik_deta_total  = -phik*dJ_deta/J[p]  + dphik_deta_B  + dphik_deta_C;
     354    23183922 :                   const Real dphik_dzeta_total = -phik*dJ_dzeta/J[p] + dphik_dzeta_B + dphik_dzeta_C;
     355             : 
     356    28367874 :                   dphidx[i][p](k) = dxi_dx[p]*dphik_dxi_total  + deta_dx[p]*dphik_deta_total  + dzeta_dx[p]*dphik_dzeta_total;
     357    28367874 :                   dphidy[i][p](k) = dxi_dy[p]*dphik_dxi_total  + deta_dy[p]*dphik_deta_total  + dzeta_dy[p]*dphik_dzeta_total;
     358    33551826 :                   dphidz[i][p](k) = dxi_dz[p]*dphik_dxi_total  + deta_dz[p]*dphik_deta_total  + dzeta_dz[p]*dphik_dzeta_total;
     359             :                 }
     360             : 
     361    14639910 :               dphi[i][p].slice(0) = dphidx[i][p];
     362     9455958 :               dphi[i][p].slice(1) = dphidy[i][p];
     363     9455958 :               dphi[i][p].slice(2) = dphidz[i][p];
     364             :             }
     365             : 
     366       18670 :         break;
     367             :       }
     368             : 
     369           0 :     default:
     370           0 :       libmesh_error_msg("Invalid dim = " << dim);
     371             :     } // switch(dim)
     372             : #else
     373             :   libmesh_ignore(dim, elem, qp, fe, dphi, dphidx, dphidy, dphidz);
     374             :   libmesh_error_msg("HDiv shape function gradients require the library to be configured "
     375             :                      "with --enable-second-derivatives (LIBMESH_ENABLE_SECOND_DERIVATIVES).");
     376             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
     377      113819 : }
     378             : 
     379             : template<typename OutputShape>
     380      236485 : void HDivFETransformation<OutputShape>::map_div(const unsigned int dim,
     381             :                                                 const Elem * const,
     382             :                                                 const std::vector<Point> &,
     383             :                                                 const FEGenericBase<OutputShape> & fe,
     384             :                                                 std::vector<std::vector<typename FEGenericBase<OutputShape>::OutputDivergence>> & div_phi) const
     385             : {
     386      236485 :   switch (dim)
     387             :     {
     388           0 :     case 0:
     389             :     case 1:
     390           0 :       libmesh_error_msg("These element transformations only make sense in 2D and 3D.");
     391             : 
     392       15756 :     case 2:
     393             :       {
     394       15756 :         const std::vector<std::vector<OutputShape>> & dphi_dxi = fe.get_dphidxi();
     395       15756 :         const std::vector<std::vector<OutputShape>> & dphi_deta = fe.get_dphideta();
     396             : 
     397       15756 :         const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
     398             : 
     399             :         // div(phi) = J^{-1} * div(\hat{phi})
     400      530838 :         for (auto i : index_range(div_phi))
     401     6041358 :           for (auto p : index_range(div_phi[i]))
     402             :             {
     403    13846972 :               div_phi[i][p] = (dphi_dxi[i][p](0) + dphi_deta[i][p](1))/J[p];
     404             :             }
     405             : 
     406       15756 :         break;
     407             :       }
     408       38492 :     case 3:
     409             :       {
     410       38492 :         const std::vector<std::vector<OutputShape>> & dphi_dxi = fe.get_dphidxi();
     411       38492 :         const std::vector<std::vector<OutputShape>> & dphi_deta = fe.get_dphideta();
     412       38492 :         const std::vector<std::vector<OutputShape>> & dphi_dzeta = fe.get_dphidzeta();
     413             : 
     414       38492 :         const std::vector<Real> & J = fe.get_fe_map().get_jacobian();
     415             : 
     416             :         // div(phi) = J^{-1} * div(\hat{phi})
     417      972315 :         for (auto i : index_range(div_phi))
     418    11624328 :           for (auto p : index_range(div_phi[i]))
     419             :             {
     420    30317370 :               div_phi[i][p] = (dphi_dxi[i][p](0) + dphi_deta[i][p](1) + dphi_dzeta[i][p](2))/J[p];
     421             :             }
     422             : 
     423       38492 :         break;
     424             :       }
     425             : 
     426           0 :     default:
     427           0 :       libmesh_error_msg("Invalid dim = " << dim);
     428             :     } // switch(dim)
     429      236485 : }
     430             : 
     431             : template class LIBMESH_EXPORT HDivFETransformation<RealGradient>;
     432             : 
     433             : template<>
     434           0 : void HDivFETransformation<Real>::init_map_phi(const FEGenericBase<Real> & ) const
     435             : {
     436           0 :   libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
     437             : }
     438             : 
     439             : template<>
     440           0 : void HDivFETransformation<Real>::init_map_dphi(const FEGenericBase<Real> & ) const
     441             : {
     442           0 :   libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
     443             : }
     444             : 
     445             : template<>
     446           0 : void HDivFETransformation<Real>::init_map_d2phi(const FEGenericBase<Real> & ) const
     447             : {
     448           0 :   libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
     449             : }
     450             : 
     451             : template<>
     452           0 : void HDivFETransformation<Real>::map_phi(const unsigned int,
     453             :                                          const Elem * const,
     454             :                                          const std::vector<Point> &,
     455             :                                          const FEGenericBase<Real> &,
     456             :                                          std::vector<std::vector<Real>> &,
     457             :                                          bool) const
     458             : {
     459           0 :   libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
     460             : }
     461             : 
     462             : template<>
     463           0 : void HDivFETransformation<Real>::map_dphi(const unsigned int,
     464             :                                           const Elem * const,
     465             :                                           const std::vector<Point> &,
     466             :                                           const FEGenericBase<Real> &,
     467             :                                           std::vector<std::vector<FEGenericBase<Real>::OutputGradient>> &,
     468             :                                           std::vector<std::vector<Real>> &,
     469             :                                           std::vector<std::vector<Real>> &,
     470             :                                           std::vector<std::vector<Real>> &) const
     471             : {
     472           0 :   libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
     473             : }
     474             : 
     475             : template<>
     476           0 : void HDivFETransformation<Real>::map_div(const unsigned int,
     477             :                                          const Elem * const,
     478             :                                          const std::vector<Point> &,
     479             :                                          const FEGenericBase<Real> &,
     480             :                                          std::vector<std::vector<Real>> &) const
     481             : {
     482           0 :   libmesh_error_msg("HDiv transformations only make sense for vector-valued elements.");
     483             : }
     484             : 
     485             : 
     486             : } // namespace libMesh

Generated by: LCOV version 1.14