LCOV - code coverage report
Current view: top level - src/fe - fe_map.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4476 (4beb67) with base a68cc6 Lines: 631 736 85.7 %
Date: 2026-06-03 20:22:46 Functions: 18 21 85.7 %
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             : 
      20             : // Local includes
      21             : #include "libmesh/fe.h"
      22             : #include "libmesh/elem.h"
      23             : #include "libmesh/libmesh_logging.h"
      24             : #include "libmesh/fe_interface.h"
      25             : #include "libmesh/fe_macro.h"
      26             : #include "libmesh/fe_map.h"
      27             : #include "libmesh/fe_xyz_map.h"
      28             : #include "libmesh/inf_fe_map.h"
      29             : #include "libmesh/mesh_subdivision_support.h"
      30             : #include "libmesh/dense_matrix.h"
      31             : #include "libmesh/dense_vector.h"
      32             : #include "libmesh/tensor_value.h"
      33             : #include "libmesh/enum_elem_type.h"
      34             : #include "libmesh/int_range.h"
      35             : 
      36             : // C++ includes
      37             : #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
      38             : #include <cmath> // for std::sqrt, std::abs
      39             : #include <memory>
      40             : 
      41             : namespace libMesh
      42             : {
      43             : Threads::spin_mutex FEMap::_point_inv_err_mutex;
      44             : 
      45             : FEFamily
      46  1533164277 : FEMap::map_fe_type(const Elem & elem)
      47             : {
      48  1533164277 :   switch (elem.mapping_type())
      49             :   {
      50      635365 :   case RATIONAL_BERNSTEIN_MAP:
      51      635365 :     return RATIONAL_BERNSTEIN;
      52  1526118510 :   case LAGRANGE_MAP:
      53  1526118510 :     return LAGRANGE;
      54           0 :   default:
      55           0 :     libmesh_error_msg("Unknown mapping type " << elem.mapping_type());
      56             :   }
      57             :   return LAGRANGE;
      58             : }
      59             : 
      60             : 
      61             : 
      62             : // Constructor
      63    16480155 : FEMap::FEMap(Real jtol) :
      64    14813317 :   calculations_started(false),
      65    14813317 :   calculate_xyz(false),
      66    14813317 :   calculate_dxyz(false),
      67             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      68    14813317 :   calculate_d2xyz(false),
      69             : #endif
      70    17313256 :   jacobian_tolerance(jtol)
      71    16480155 : {}
      72             : 
      73             : 
      74             : 
      75    16400178 : std::unique_ptr<FEMap> FEMap::build( FEType fe_type )
      76             : {
      77    16400178 :   switch( fe_type.family )
      78             :     {
      79      897192 :     case XYZ:
      80      897192 :       return std::make_unique<FEXYZMap>();
      81             : 
      82    15502986 :     default:
      83    15502986 :       return std::make_unique<FEMap>();
      84             :     }
      85             : }
      86             : 
      87             : 
      88             : 
      89    26157967 : void FEMap::add_calculations()
      90             : {
      91    26157967 :   this->calculations_started = false;
      92    23805148 :   this->phi_map.clear();
      93    23805148 :   this->dphidxi_map.clear();
      94    23805148 :   this->dphideta_map.clear();
      95    23805148 :   this->dphidzeta_map.clear();
      96             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      97    23805148 :   this->d2phidxi2_map.clear();
      98    23805148 :   this->d2phidxideta_map.clear();
      99    23805148 :   this->d2phideta2_map.clear();
     100    23805148 :   this->d2phidxidzeta_map.clear();
     101    23805148 :   this->d2phidetadzeta_map.clear();
     102    23805148 :   this->d2phidzeta2_map.clear();
     103             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     104    26157967 : }
     105             : 
     106             : 
     107             : 
     108             : template<unsigned int Dim>
     109    53639958 : void FEMap::init_reference_to_physical_map(const std::vector<Point> & qp,
     110             :                                            const Elem * elem)
     111             : {
     112             :   // Start logging the reference->physical map initialization
     113     9321120 :   LOG_SCOPE("init_reference_to_physical_map()", "FEMap");
     114             : 
     115             :   // We're calculating now!
     116     4660560 :   this->determine_calculations();
     117             : 
     118             :   // The number of quadrature points.
     119     9320510 :   const std::size_t n_qp = qp.size();
     120             : 
     121             :   // The element type and order to use in
     122             :   // the map
     123    53639958 :   const FEFamily mapping_family = FEMap::map_fe_type(*elem);
     124    53639958 :   const FEType map_fe_type(elem->default_order(), mapping_family);
     125             : 
     126             :   // Number of shape functions used to construct the map
     127             :   // (Lagrange shape functions are used for mapping)
     128             :   // Do not consider the Elem::p_level(), if any, when computing the
     129             :   // number of shape functions.
     130             :   const unsigned int n_mapping_shape_functions =
     131    53639958 :     FEInterface::n_shape_functions (map_fe_type, /*extra_order=*/0, elem);
     132             : 
     133             :   // Maybe we already have correctly-sized data?  Check data sizes,
     134             :   // and get ready to break out of a "loop" if all these resize()
     135             :   // calls are redundant.
     136     4660560 :   unsigned int old_n_qp = 0;
     137             : 
     138             :   do
     139             :     {
     140    53639958 :       if (calculate_xyz)
     141             :         {
     142    32299660 :           if (this->phi_map.size() == n_mapping_shape_functions)
     143             :             {
     144     3115228 :               old_n_qp = n_mapping_shape_functions ? this->phi_map[0].size() : 0;
     145      253169 :               break;
     146             :             }
     147    26552524 :           this->phi_map.resize         (n_mapping_shape_functions);
     148             :         }
     149             :       if (Dim > 0)
     150             :         {
     151    50325950 :           if (calculate_dxyz)
     152             :             {
     153    41526117 :               if (this->dphidxi_map.size() == n_mapping_shape_functions)
     154             :                 {
     155     7752294 :                   old_n_qp = n_mapping_shape_functions ? this->dphidxi_map[0].size() : 0;
     156      700170 :                   break;
     157             :                 }
     158    30412636 :               this->dphidxi_map.resize     (n_mapping_shape_functions);
     159             :             }
     160             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     161             :           // Don't waste time considering early break here; if we
     162             :           // asked for d2xyz then we surely asked for dxyz too and
     163             :           // considered early break above.
     164    42573656 :           if (calculate_d2xyz)
     165     1900180 :             this->d2phidxi2_map.resize   (n_mapping_shape_functions);
     166             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     167             :         }
     168             : 
     169             :       if (Dim > 1)
     170             :         {
     171    39881481 :           if (calculate_dxyz)
     172    30040771 :             this->dphideta_map.resize  (n_mapping_shape_functions);
     173             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     174    39881481 :           if (calculate_d2xyz)
     175             :             {
     176     1614833 :               this->d2phidxideta_map.resize   (n_mapping_shape_functions);
     177     1614833 :               this->d2phideta2_map.resize     (n_mapping_shape_functions);
     178             :             }
     179             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     180             :         }
     181             : 
     182             :       if (Dim > 2)
     183             :         {
     184    18669314 :           if (calculate_dxyz)
     185    16369427 :             this->dphidzeta_map.resize (n_mapping_shape_functions);
     186             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     187    18669314 :           if (calculate_d2xyz)
     188             :             {
     189     1455887 :               this->d2phidxidzeta_map.resize  (n_mapping_shape_functions);
     190     1455887 :               this->d2phidetadzeta_map.resize (n_mapping_shape_functions);
     191     1455887 :               this->d2phidzeta2_map.resize    (n_mapping_shape_functions);
     192             :             }
     193             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     194             :         }
     195             :     }
     196             :   while (false);
     197             : 
     198    53639958 :   if (old_n_qp != n_qp)
     199   435716067 :     for (unsigned int i=0; i<n_mapping_shape_functions; i++)
     200             :       {
     201   392914921 :         if (calculate_xyz)
     202   284190996 :           this->phi_map[i].resize         (n_qp);
     203             :         if (Dim > 0)
     204             :           {
     205   392716141 :             if (calculate_dxyz)
     206   319497002 :               this->dphidxi_map[i].resize     (n_qp);
     207             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     208   392716141 :             if (calculate_d2xyz)
     209             :               {
     210    17237214 :                 this->d2phidxi2_map[i].resize     (n_qp);
     211             :                 if (Dim > 1)
     212             :                   {
     213    16644552 :                     this->d2phidxideta_map[i].resize (n_qp);
     214    16644552 :                     this->d2phideta2_map[i].resize (n_qp);
     215             :                   }
     216             :                 if (Dim > 2)
     217             :                   {
     218    15247613 :                     this->d2phidxidzeta_map[i].resize  (n_qp);
     219    15247613 :                     this->d2phidetadzeta_map[i].resize (n_qp);
     220    15247613 :                     this->d2phidzeta2_map[i].resize    (n_qp);
     221             :                   }
     222             :               }
     223             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     224             : 
     225   387191549 :             if (Dim > 1 && calculate_dxyz)
     226   318624734 :               this->dphideta_map[i].resize  (n_qp);
     227             : 
     228   252973143 :             if (Dim > 2 && calculate_dxyz)
     229   234296308 :                 this->dphidzeta_map[i].resize (n_qp);
     230             :           }
     231             :       }
     232             : 
     233             :   // Optimize for the *linear* geometric elements case:
     234    53639958 :   bool is_linear = elem->is_linear();
     235             : 
     236             :   FEInterface::shape_deriv_ptr shape_deriv_ptr =
     237    53639958 :     FEInterface::shape_deriv_function(map_fe_type, elem);
     238             : 
     239             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     240             :   FEInterface::shape_second_deriv_ptr shape_second_deriv_ptr =
     241    53639958 :     FEInterface::shape_second_deriv_function(map_fe_type, elem);
     242             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     243             : 
     244    53639958 :   if (calculate_xyz)
     245    29667752 :     FEInterface::all_shapes(Dim, map_fe_type, elem, qp, this->phi_map, false);
     246             : 
     247             :   switch (Dim)
     248             :     {
     249             :       //------------------------------------------------------------
     250             :       // 0D
     251             :     case 0:
     252             :       {
     253             :         // No mapping derivatives here
     254       19049 :         break;
     255             :       }
     256             : 
     257             :       //------------------------------------------------------------
     258             :       // 1D
     259     2513041 :     case 1:
     260             :       {
     261             :         // Compute gradients of mapping shape functions i at quadrature points p
     262             : 
     263             :         // TODO: optimizations for the RATIONAL_BERNSTEIN+linear case
     264     2740690 :         if (is_linear)
     265             :           {
     266     7683561 :             for (unsigned int i=0; i<n_mapping_shape_functions; i++)
     267             :               {
     268     5122374 :                 if (calculate_dxyz)
     269             :                   {
     270      582930 :                     this->dphidxi_map[i][0] =
     271      571280 :                       shape_deriv_ptr(map_fe_type, elem, i, 0, qp[0], false);
     272     2237416 :                     for (std::size_t p=1; p<n_qp; p++)
     273     1697230 :                       this->dphidxi_map[i][p]  = this->dphidxi_map[i][0];
     274             :                   }
     275             : 
     276             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     277     5122374 :                 if (calculate_d2xyz)
     278             :                   {
     279      577880 :                     this->d2phidxi2_map[i][0] =
     280      566564 :                       shape_second_deriv_ptr(map_fe_type, elem, i, 0, qp[0], false);
     281     2228492 :                     for (std::size_t p=1; p<n_qp; p++)
     282     1692740 :                       this->d2phidxi2_map[i][p] = this->d2phidxi2_map[i][0];
     283             :                   }
     284             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     285             :               }
     286             :           }
     287             :         else
     288             :           {
     289      179503 :             if (calculate_dxyz)
     290             :               {
     291      178604 :                 std::vector<std::vector<Real>> * comps[3]
     292      178604 :                   { &this->dphidxi_map, &this->dphideta_map, &this->dphidzeta_map };
     293      134740 :                 FEInterface::all_shape_derivs(Dim, map_fe_type, elem, qp, comps, false);
     294             :               }
     295             : 
     296             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     297      179503 :             if (calculate_d2xyz)
     298       85836 :               for (unsigned int i=0; i<n_mapping_shape_functions; i++)
     299      220206 :                 for (std::size_t p=0; p<n_qp; p++)
     300      168003 :                   this->d2phidxi2_map[i][p] = shape_second_deriv_ptr (map_fe_type, elem, i, 0, qp[p], false);
     301             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     302             :           }
     303             : 
     304      227649 :         break;
     305             :       }
     306             :       //------------------------------------------------------------
     307             :       // 2D
     308    22959951 :     case 2:
     309             :       {
     310             :         // Compute gradients of mapping shape functions i at quadrature points p
     311             : 
     312             :         // TODO: optimizations for the RATIONAL_BERNSTEIN+linear case
     313    25288680 :         if (is_linear)
     314             :           {
     315    13083968 :             for (unsigned int i=0; i<n_mapping_shape_functions; i++)
     316             :               {
     317     9812976 :                 if (calculate_dxyz)
     318             :                   {
     319     9693048 :                     this->dphidxi_map[i][0]  = shape_deriv_ptr (map_fe_type, elem, i, 0, qp[0], false);
     320     9693048 :                     this->dphideta_map[i][0] = shape_deriv_ptr (map_fe_type, elem, i, 1, qp[0], false);
     321    10528581 :                     for (std::size_t p=1; p<n_qp; p++)
     322             :                       {
     323      901179 :                         this->dphidxi_map[i][p]  = this->dphidxi_map[i][0];
     324      901179 :                         this->dphideta_map[i][p] = this->dphideta_map[i][0];
     325             :                       }
     326             :                   }
     327             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     328     9812976 :                 if (calculate_d2xyz)
     329             :                   {
     330      145017 :                     this->d2phidxi2_map[i][0]    = shape_second_deriv_ptr (map_fe_type, elem, i, 0, qp[0], false);
     331      145017 :                     this->d2phidxideta_map[i][0] = shape_second_deriv_ptr (map_fe_type, elem, i, 1, qp[0], false);
     332      145017 :                     this->d2phideta2_map[i][0]   = shape_second_deriv_ptr (map_fe_type, elem, i, 2, qp[0], false);
     333      152145 :                     for (std::size_t p=1; p<n_qp; p++)
     334             :                       {
     335        7776 :                         this->d2phidxi2_map[i][p] = this->d2phidxi2_map[i][0];
     336        7776 :                         this->d2phidxideta_map[i][p] = this->d2phidxideta_map[i][0];
     337        7776 :                         this->d2phideta2_map[i][p] = this->d2phideta2_map[i][0];
     338             :                       }
     339             :                   }
     340             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     341             :               }
     342             :           }
     343             :         else
     344             :           {
     345    22017688 :             if (calculate_dxyz)
     346             :               {
     347    20089262 :                 std::vector<std::vector<Real>> * comps[3]
     348    20089262 :                   { &this->dphidxi_map, &this->dphideta_map, &this->dphidzeta_map };
     349    14423626 :                 FEInterface::all_shape_derivs(Dim, map_fe_type, elem, qp, comps, false);
     350             :               }
     351             : 
     352             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     353    22017688 :             if (calculate_d2xyz)
     354     7622625 :               for (unsigned int i=0; i<n_mapping_shape_functions; i++)
     355    37890144 :                 for (std::size_t p=0; p<n_qp; p++)
     356             :                   {
     357    33603152 :                     this->d2phidxi2_map[i][p] = shape_second_deriv_ptr (map_fe_type, elem, i, 0, qp[p], false);
     358    33603152 :                     this->d2phidxideta_map[i][p] = shape_second_deriv_ptr (map_fe_type, elem, i, 1, qp[p], false);
     359    33603152 :                     this->d2phideta2_map[i][p] = shape_second_deriv_ptr (map_fe_type, elem, i, 2, qp[p], false);
     360             :                   }
     361             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     362             :           }
     363             : 
     364     2328729 :         break;
     365             :       }
     366             : 
     367             :       //------------------------------------------------------------
     368             :       // 3D
     369    23326675 :     case 3:
     370             :       {
     371             :         // Compute gradients of mapping shape functions i at quadrature points p
     372             : 
     373             :         // TODO: optimizations for the RATIONAL_BERNSTEIN+linear case
     374    25411808 :         if (is_linear)
     375             :           {
     376      791925 :             for (unsigned int i=0; i<n_mapping_shape_functions; i++)
     377             :               {
     378      633540 :                 if (calculate_dxyz)
     379             :                   {
     380      604980 :                     this->dphidxi_map[i][0]  = shape_deriv_ptr (map_fe_type, elem, i, 0, qp[0], false);
     381      604980 :                     this->dphideta_map[i][0] = shape_deriv_ptr (map_fe_type, elem, i, 1, qp[0], false);
     382      604980 :                     this->dphidzeta_map[i][0] = shape_deriv_ptr (map_fe_type, elem, i, 2, qp[0], false);
     383             : 
     384     1436988 :                     for (std::size_t p=1; p<n_qp; p++)
     385             :                       {
     386      893784 :                         this->dphidxi_map[i][p]  = this->dphidxi_map[i][0];
     387      893784 :                         this->dphideta_map[i][p] = this->dphideta_map[i][0];
     388      893784 :                         this->dphidzeta_map[i][p] = this->dphidzeta_map[i][0];
     389             :                       }
     390             :                   }
     391             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     392      633540 :                 if (calculate_d2xyz)
     393             :                   {
     394      482724 :                     this->d2phidxi2_map[i][0]      = shape_second_deriv_ptr (map_fe_type, elem, i, 0, qp[0], false);
     395      482724 :                     this->d2phidxideta_map[i][0]   = shape_second_deriv_ptr (map_fe_type, elem, i, 1, qp[0], false);
     396      482724 :                     this->d2phideta2_map[i][0]     = shape_second_deriv_ptr (map_fe_type, elem, i, 2, qp[0], false);
     397      482724 :                     this->d2phidxidzeta_map[i][0]  = shape_second_deriv_ptr (map_fe_type, elem, i, 3, qp[0], false);
     398      482724 :                     this->d2phidetadzeta_map[i][0] = shape_second_deriv_ptr (map_fe_type, elem, i, 4, qp[0], false);
     399      482724 :                     this->d2phidzeta2_map[i][0]    = shape_second_deriv_ptr (map_fe_type, elem, i, 5, qp[0], false);
     400             : 
     401      560340 :                     for (std::size_t p=1; p<n_qp; p++)
     402             :                       {
     403       79968 :                         this->d2phidxi2_map[i][p] = this->d2phidxi2_map[i][0];
     404       79968 :                         this->d2phidxideta_map[i][p] = this->d2phidxideta_map[i][0];
     405       79968 :                         this->d2phideta2_map[i][p] = this->d2phideta2_map[i][0];
     406       79968 :                         this->d2phidxidzeta_map[i][p] = this->d2phidxidzeta_map[i][0];
     407       79968 :                         this->d2phidetadzeta_map[i][p] = this->d2phidetadzeta_map[i][0];
     408       79968 :                         this->d2phidzeta2_map[i][p] = this->d2phidzeta2_map[i][0];
     409             :                       }
     410             :                   }
     411             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     412             :               }
     413             :           }
     414             :         else
     415             :           {
     416    25253423 :             if (calculate_dxyz)
     417             :               {
     418    30214118 :                 std::vector<std::vector<Real>> * comps[3]
     419    30214118 :                   { &this->dphidxi_map, &this->dphideta_map, &this->dphidzeta_map };
     420    22733074 :                 FEInterface::all_shape_derivs(Dim, map_fe_type, elem, qp, comps, false);
     421             :               }
     422             : 
     423             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     424    25253423 :             if (calculate_d2xyz)
     425    91980386 :               for (unsigned int i=0; i<n_mapping_shape_functions; i++)
     426   255504883 :                 for (std::size_t p=0; p<n_qp; p++)
     427             :                   {
     428   183154015 :                     this->d2phidxi2_map[i][p]      = shape_second_deriv_ptr (map_fe_type, elem, i, 0, qp[p], false);
     429   183154015 :                     this->d2phidxideta_map[i][p]   = shape_second_deriv_ptr (map_fe_type, elem, i, 1, qp[p], false);
     430   183154015 :                     this->d2phideta2_map[i][p]     = shape_second_deriv_ptr (map_fe_type, elem, i, 2, qp[p], false);
     431   183154015 :                     this->d2phidxidzeta_map[i][p]  = shape_second_deriv_ptr (map_fe_type, elem, i, 3, qp[p], false);
     432   183154015 :                     this->d2phidetadzeta_map[i][p] = shape_second_deriv_ptr (map_fe_type, elem, i, 4, qp[p], false);
     433   183154015 :                     this->d2phidzeta2_map[i][p]    = shape_second_deriv_ptr (map_fe_type, elem, i, 5, qp[p], false);
     434             :                   }
     435             : #endif // ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     436             :           }
     437             : 
     438     2085133 :         break;
     439             :       }
     440             : 
     441             :     default:
     442             :       libmesh_error_msg("Invalid Dim = " << Dim);
     443             :     }
     444    53639958 : }
     445             : 
     446             : 
     447             : 
     448   175516620 : void FEMap::compute_single_point_map(const unsigned int dim,
     449             :                                      const std::vector<Real> & qw,
     450             :                                      const Elem * elem,
     451             :                                      unsigned int p,
     452             :                                      const std::vector<const Node *> & elem_nodes,
     453             :                                      bool compute_second_derivatives)
     454             : {
     455    14711840 :   libmesh_assert(elem);
     456    14711840 :   libmesh_assert(calculations_started);
     457             : #ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
     458             :   libmesh_assert(!compute_second_derivatives);
     459             : #endif
     460             : 
     461             :   // this parameter is only accounted for if LIBMESH_DIM==2.
     462    14711840 :   libmesh_ignore(compute_second_derivatives);
     463             : 
     464   175516620 :   if (calculate_xyz)
     465     3197403 :     libmesh_assert_equal_to(phi_map.size(), elem_nodes.size());
     466             : 
     467             :   auto check_for_degenerate_map =
     468   131666475 :     [this, elem, p]
     469    13208197 :     (Real det_J) {
     470   157816043 :     if (det_J <= jacobian_tolerance)
     471             :       {
     472             :         // Don't call get_info() recursively if we're already
     473             :         // failing.  get_info() calls Elem::volume() which may
     474             :         // call FE::reinit() and trigger the same failure again.
     475             :         static bool failing = false;
     476           0 :         if (!failing)
     477             :           {
     478           0 :             failing = true;
     479           0 :             std::string elem_info = elem->get_info();
     480           0 :             failing = false;
     481           0 :             if (calculate_xyz)
     482             :               {
     483           0 :                 libmesh_degenerate_mapping_msg
     484             :                   ("Jacobian " << det_J << " at or under tolerance " <<
     485             :                    jacobian_tolerance << " at point " << xyz[p] <<
     486             :                    " in element:\n" << elem_info);
     487             :               }
     488             :             else
     489             :               {
     490             :                 // In this case xyz[p] is not defined, so don't
     491             :                 // try to print it out.
     492           0 :                 libmesh_degenerate_mapping_msg
     493             :                   ("Jacobian " << det_J << " at or under tolerance " <<
     494             :                    jacobian_tolerance << " at point index " << p <<
     495             :                    " in element:\n" << elem_info);
     496             :               }
     497             :           }
     498             :         else
     499             :           {
     500             :             // We were already failing when we called this, so just
     501             :             // stop the current computation and return with
     502             :             // incomplete results.
     503           0 :             return;
     504             :           }
     505             :       }
     506   175516620 :   };
     507             : 
     508   175516620 :   switch (dim)
     509             :     {
     510             :       //--------------------------------------------------------------------
     511             :       // 0D
     512      198780 :     case 0:
     513             :       {
     514       19049 :         libmesh_assert(elem_nodes[0]);
     515      198780 :         if (calculate_xyz)
     516           0 :           xyz[p] = *elem_nodes[0];
     517      198780 :         if (calculate_dxyz)
     518             :           {
     519      198780 :             jac[p] = 1.0;
     520      236878 :             JxW[p] = qw[p];
     521             :           }
     522       19049 :         break;
     523             :       }
     524             : 
     525             :       //--------------------------------------------------------------------
     526             :       // 1D
     527    44982388 :     case 1:
     528             :       {
     529             :         // Clear the entities that will be summed
     530    44982388 :         if (calculate_xyz)
     531      127303 :           xyz[p].zero();
     532    44982388 :         if (calculate_dxyz)
     533    42648305 :           dxyzdxi_map[p].zero();
     534             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     535    44982388 :         if (calculate_d2xyz)
     536             :           {
     537    42506017 :             d2xyzdxi2_map[p].zero();
     538             :             // Inverse map second derivatives
     539    45132028 :             d2xidxyz2_map[p].assign(6, 0.);
     540             :           }
     541             : #endif
     542             : 
     543             :         // compute x, dx, d2x at the quadrature point
     544   135180923 :         for (auto i : index_range(elem_nodes)) // sum over the nodes
     545             :           {
     546             :             // Reference to the point, helps eliminate
     547             :             // excessive temporaries in the inner loop
     548     6135907 :             libmesh_assert(elem_nodes[i]);
     549    90198535 :             const Point & elem_point = *elem_nodes[i];
     550             : 
     551    90198535 :             if (calculate_xyz)
     552      442475 :               xyz[p].add_scaled          (elem_point, phi_map[i][p]    );
     553    90198535 :             if (calculate_dxyz)
     554    96052002 :               dxyzdxi_map[p].add_scaled  (elem_point, dphidxi_map[i][p]);
     555             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     556    90198535 :             if (calculate_d2xyz)
     557    95558324 :               d2xyzdxi2_map[p].add_scaled(elem_point, d2phidxi2_map[i][p]);
     558             : #endif
     559             :           }
     560             : 
     561             :         // Compute the jacobian
     562             :         //
     563             :         // 1D elements can live in 2D or 3D space.
     564             :         // The transformation matrix from local->global
     565             :         // coordinates is
     566             :         //
     567             :         // T = | dx/dxi |
     568             :         //     | dy/dxi |
     569             :         //     | dz/dxi |
     570             :         //
     571             :         // The generalized determinant of T (from the
     572             :         // so-called "normal" eqns.) is
     573             :         // jac = "det(T)" = sqrt(det(T'T))
     574             :         //
     575             :         // where T'= transpose of T, so
     576             :         //
     577             :         // jac = sqrt( (dx/dxi)^2 + (dy/dxi)^2 + (dz/dxi)^2 )
     578             : 
     579    44982388 :         if (calculate_dxyz)
     580             :           {
     581    45286080 :             jac[p] = dxyzdxi_map[p].norm();
     582             : 
     583    42648305 :             check_for_degenerate_map(jac[p]);
     584             : 
     585             :             // The inverse Jacobian entries also come from the
     586             :             // generalized inverse of T (see also the 2D element
     587             :             // living in 3D code).
     588    45286080 :             const Real jacm2 = 1./jac[p]/jac[p];
     589    45286080 :             dxidx_map[p] = jacm2*dxdxi_map(p);
     590             : #if LIBMESH_DIM > 1
     591    45286080 :             dxidy_map[p] = jacm2*dydxi_map(p);
     592             : #endif
     593             : #if LIBMESH_DIM > 2
     594    42648305 :             dxidz_map[p] = jacm2*dzdxi_map(p);
     595             : #endif
     596             : 
     597    47923855 :             JxW[p] = jac[p]*qw[p];
     598             :           }
     599             : 
     600             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     601             : 
     602    44982388 :         if (calculate_d2xyz)
     603             :           {
     604             : #if LIBMESH_DIM == 1
     605             :             // Compute inverse map second derivatives for 1D-element-living-in-1D case
     606             :             this->compute_inverse_map_second_derivs(p);
     607             : #elif LIBMESH_DIM == 2
     608             :             // Compute inverse map second derivatives for 1D-element-living-in-2D case
     609             :             // See JWP notes for details
     610             : 
     611             :             // numer = x_xi*x_{xi xi} + y_xi*y_{xi xi}
     612             :             Real numer =
     613             :               dxyzdxi_map[p](0)*d2xyzdxi2_map[p](0) +
     614             :               dxyzdxi_map[p](1)*d2xyzdxi2_map[p](1);
     615             : 
     616             :             // denom = (x_xi)^2 + (y_xi)^2 must be >= 0.0
     617             :             Real denom =
     618             :               dxyzdxi_map[p](0)*dxyzdxi_map[p](0) +
     619             :               dxyzdxi_map[p](1)*dxyzdxi_map[p](1);
     620             : 
     621             :             if (denom <= 0.0)
     622             :               {
     623             :                 // Don't call print_info() recursively if we're already
     624             :                 // failing.  print_info() calls Elem::volume() which may
     625             :                 // call FE::reinit() and trigger the same failure again.
     626             :                 static bool failing = false;
     627             :                 if (!failing)
     628             :                   {
     629             :                     failing = true;
     630             :                     elem->print_info(libMesh::err);
     631             :                     failing = false;
     632             :                     libmesh_error_msg("Encountered invalid 1D element!");
     633             :                   }
     634             :                 else
     635             :                   {
     636             :                     // We were already failing when we called this, so just
     637             :                     // stop the current computation and return with
     638             :                     // incomplete results.
     639             :                     return;
     640             :                   }
     641             :               }
     642             : 
     643             :             // xi_{x x}
     644             :             d2xidxyz2_map[p][0] = -numer * dxidx_map[p]*dxidx_map[p] / denom;
     645             : 
     646             :             // xi_{x y}
     647             :             d2xidxyz2_map[p][1] = -numer * dxidx_map[p]*dxidy_map[p] / denom;
     648             : 
     649             :             // xi_{y y}
     650             :             d2xidxyz2_map[p][3] = -numer * dxidy_map[p]*dxidy_map[p] / denom;
     651             : 
     652             : #elif LIBMESH_DIM == 3
     653             :             // Compute inverse map second derivatives for 1D-element-living-in-3D case
     654             :             // See JWP notes for details
     655             : 
     656             :             // numer = x_xi*x_{xi xi} + y_xi*y_{xi xi} + z_xi*z_{xi xi}
     657             :             Real numer =
     658    45132028 :               dxyzdxi_map[p](0)*d2xyzdxi2_map[p](0) +
     659    42506017 :               dxyzdxi_map[p](1)*d2xyzdxi2_map[p](1) +
     660    42506017 :               dxyzdxi_map[p](2)*d2xyzdxi2_map[p](2);
     661             : 
     662             :             // denom = (x_xi)^2 + (y_xi)^2 + (z_xi)^2 must be >= 0.0
     663             :             Real denom =
     664    45132028 :               dxyzdxi_map[p](0)*dxyzdxi_map[p](0) +
     665    42506017 :               dxyzdxi_map[p](1)*dxyzdxi_map[p](1) +
     666    42506017 :               dxyzdxi_map[p](2)*dxyzdxi_map[p](2);
     667             : 
     668    42506017 :             if (denom <= 0.0)
     669             :               {
     670             :                 // Don't call print_info() recursively if we're already
     671             :                 // failing.  print_info() calls Elem::volume() which may
     672             :                 // call FE::reinit() and trigger the same failure again.
     673             :                 static bool failing = false;
     674           0 :                 if (!failing)
     675             :                   {
     676           0 :                     failing = true;
     677           0 :                     elem->print_info(libMesh::err);
     678           0 :                     failing = false;
     679           0 :                     libmesh_error_msg("Encountered invalid 1D element!");
     680             :                   }
     681             :                 else
     682             :                   {
     683             :                     // We were already failing when we called this, so just
     684             :                     // stop the current computation and return with
     685             :                     // incomplete results.
     686           0 :                     return;
     687             :                   }
     688             :               }
     689             : 
     690             :             // xi_{x x}
     691    45132028 :             d2xidxyz2_map[p][0] = -numer * dxidx_map[p]*dxidx_map[p] / denom;
     692             : 
     693             :             // xi_{x y}
     694    42506017 :             d2xidxyz2_map[p][1] = -numer * dxidx_map[p]*dxidy_map[p] / denom;
     695             : 
     696             :             // xi_{x z}
     697    42506017 :             d2xidxyz2_map[p][2] = -numer * dxidx_map[p]*dxidz_map[p] / denom;
     698             : 
     699             :             // xi_{y y}
     700    42506017 :             d2xidxyz2_map[p][3] = -numer * dxidy_map[p]*dxidy_map[p] / denom;
     701             : 
     702             :             // xi_{y z}
     703    42506017 :             d2xidxyz2_map[p][4] = -numer * dxidy_map[p]*dxidz_map[p] / denom;
     704             : 
     705             :             // xi_{z z}
     706    42506017 :             d2xidxyz2_map[p][5] = -numer * dxidz_map[p]*dxidz_map[p] / denom;
     707             : #endif //LIBMESH_DIM == 3
     708             :           } // calculate_d2xyz
     709             : 
     710             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
     711             : 
     712             :         // done computing the map
     713     3058319 :         break;
     714             :       }
     715             : 
     716             : 
     717             :       //--------------------------------------------------------------------
     718             :       // 2D
     719    94239639 :     case 2:
     720             :       {
     721             :         //------------------------------------------------------------------
     722             :         // Compute the (x,y) values at the quadrature points,
     723             :         // the Jacobian at the quadrature points
     724             : 
     725    94239639 :         if (calculate_xyz)
     726    18888168 :           xyz[p].zero();
     727             : 
     728    94239639 :         if (calculate_dxyz)
     729             :           {
     730    83155048 :             dxyzdxi_map[p].zero();
     731    15379060 :             dxyzdeta_map[p].zero();
     732             :           }
     733             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     734    94239639 :         if (calculate_d2xyz)
     735             :           {
     736     1357795 :             d2xyzdxi2_map[p].zero();
     737      230470 :             d2xyzdxideta_map[p].zero();
     738      230470 :             d2xyzdeta2_map[p].zero();
     739             :             // Inverse map second derivatives
     740     1473030 :             d2xidxyz2_map[p].assign(6, 0.);
     741     1473030 :             d2etadxyz2_map[p].assign(6, 0.);
     742             :           }
     743             : #endif
     744             : 
     745             : 
     746             :         // compute (x,y) at the quadrature points, derivatives once
     747   575355418 :         for (auto i : index_range(elem_nodes)) // sum over the nodes
     748             :           {
     749             :             // Reference to the point, helps eliminate
     750             :             // excessive temporaries in the inner loop
     751    43806166 :             libmesh_assert(elem_nodes[i]);
     752   481115779 :             const Point & elem_point = *elem_nodes[i];
     753             : 
     754   481115779 :             if (calculate_xyz)
     755   145952669 :               xyz[p].add_scaled          (elem_point, phi_map[i][p]     );
     756             : 
     757   481115779 :             if (calculate_dxyz)
     758             :               {
     759   466294110 :                 dxyzdxi_map[p].add_scaled      (elem_point, dphidxi_map[i][p] );
     760   466294110 :                 dxyzdeta_map[p].add_scaled     (elem_point, dphideta_map[i][p]);
     761             :               }
     762             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     763   481115779 :             if (calculate_d2xyz)
     764             :               {
     765    10968668 :                 d2xyzdxi2_map[p].add_scaled    (elem_point, d2phidxi2_map[i][p]);
     766    10968668 :                 d2xyzdxideta_map[p].add_scaled (elem_point, d2phidxideta_map[i][p]);
     767    10968668 :                 d2xyzdeta2_map[p].add_scaled   (elem_point, d2phideta2_map[i][p]);
     768             :               }
     769             : #endif
     770             :           }
     771             : 
     772    94239639 :         if (calculate_dxyz)
     773             :           {
     774             :             // compute the jacobian once
     775     7718362 :             const Real dx_dxi = dxdxi_map(p),
     776     7718362 :               dx_deta = dxdeta_map(p),
     777     7718362 :               dy_dxi = dydxi_map(p),
     778     7718362 :               dy_deta = dydeta_map(p);
     779             : 
     780             : #if LIBMESH_DIM == 2
     781             :             // Compute the Jacobian.  This assumes the 2D face
     782             :             // lives in 2D space
     783             :             //
     784             :             // Symbolically, the matrix determinant is
     785             :             //
     786             :             //         | dx/dxi  dx/deta |
     787             :             // jac =   | dy/dxi  dy/deta |
     788             :             //
     789             :             // jac = dx/dxi*dy/deta - dx/deta*dy/dxi
     790             :             jac[p] = (dx_dxi*dy_deta - dx_deta*dy_dxi);
     791             : 
     792             :             check_for_degenerate_map(jac[p]);
     793             : 
     794             :             JxW[p] = jac[p]*qw[p];
     795             : 
     796             :             // Compute the shape function derivatives wrt x,y at the
     797             :             // quadrature points
     798             :             const Real inv_jac = 1./jac[p];
     799             : 
     800             :             dxidx_map[p]  =  dy_deta*inv_jac; //dxi/dx  =  (1/J)*dy/deta
     801             :             dxidy_map[p]  = -dx_deta*inv_jac; //dxi/dy  = -(1/J)*dx/deta
     802             :             detadx_map[p] = -dy_dxi* inv_jac; //deta/dx = -(1/J)*dy/dxi
     803             :             detady_map[p] =  dx_dxi* inv_jac; //deta/dy =  (1/J)*dx/dxi
     804             : 
     805             :             dxidz_map[p] = detadz_map[p] = 0.;
     806             : 
     807             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     808             :             if (compute_second_derivatives)
     809             :               this->compute_inverse_map_second_derivs(p);
     810             : #endif
     811             : #else // LIBMESH_DIM == 3
     812             : 
     813     7718362 :             const Real dz_dxi = dzdxi_map(p),
     814     7718362 :               dz_deta = dzdeta_map(p);
     815             : 
     816             :             // Compute the Jacobian.  This assumes a 2D face in
     817             :             // 3D space.
     818             :             //
     819             :             // The transformation matrix T from local to global
     820             :             // coordinates is
     821             :             //
     822             :             //         | dx/dxi  dx/deta |
     823             :             //     T = | dy/dxi  dy/deta |
     824             :             //         | dz/dxi  dz/deta |
     825             :             // note det(T' T) = det(T')det(T) = det(T)det(T)
     826             :             // so det(T) = std::sqrt(det(T' T))
     827             :             //
     828             :             //----------------------------------------------
     829             :             // Notes:
     830             :             //
     831             :             //       dX = R dXi -> R'dX = R'R dXi
     832             :             // (R^-1)dX =   dXi    [(R'R)^-1 R']dX = dXi
     833             :             //
     834             :             // so R^-1 = (R'R)^-1 R'
     835             :             //
     836             :             // and R^-1 R = (R'R)^-1 R'R = I.
     837             :             //
     838   113913168 :             const Real g11 = (dx_dxi*dx_dxi +
     839    83155048 :                               dy_dxi*dy_dxi +
     840    83155048 :                               dz_dxi*dz_dxi);
     841             : 
     842   113913168 :             const Real g12 = (dx_dxi*dx_deta +
     843    83155048 :                               dy_dxi*dy_deta +
     844    83155048 :                               dz_dxi*dz_deta);
     845             : 
     846     7718362 :             const Real g21 = g12;
     847             : 
     848   113913168 :             const Real g22 = (dx_deta*dx_deta +
     849    83155048 :                               dy_deta*dy_deta +
     850    83155048 :                               dz_deta*dz_deta);
     851             : 
     852    83155048 :             const Real det = (g11*g22 - g12*g21);
     853             : 
     854    83155048 :             check_for_degenerate_map(det);
     855             : 
     856    83155048 :             const Real inv_det = 1./det;
     857    83155048 :             jac[p] = std::sqrt(det);
     858             : 
     859    90815746 :             JxW[p] = jac[p]*qw[p];
     860             : 
     861    83155048 :             const Real g11inv =  g22*inv_det;
     862    83155048 :             const Real g12inv = -g12*inv_det;
     863     7718362 :             const Real g21inv = -g21*inv_det;
     864    83155048 :             const Real g22inv =  g11*inv_det;
     865             : 
     866    83155048 :             dxidx_map[p]  = g11inv*dx_dxi + g12inv*dx_deta;
     867    83155048 :             dxidy_map[p]  = g11inv*dy_dxi + g12inv*dy_deta;
     868    83155048 :             dxidz_map[p]  = g11inv*dz_dxi + g12inv*dz_deta;
     869             : 
     870    83155048 :             detadx_map[p] = g21inv*dx_dxi + g22inv*dx_deta;
     871    83155048 :             detady_map[p] = g21inv*dy_dxi + g22inv*dy_deta;
     872    83155048 :             detadz_map[p] = g21inv*dz_dxi + g22inv*dz_deta;
     873             : 
     874             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     875             : 
     876    83155048 :             if (calculate_d2xyz)
     877             :               {
     878             :                 // Compute inverse map second derivative values for
     879             :                 // 2D-element-living-in-3D case.  We pursue a least-squares
     880             :                 // solution approach for this "non-square" case, see JWP notes
     881             :                 // for details.
     882             : 
     883             :                 // A = [ x_{xi xi} x_{eta eta} ]
     884             :                 //     [ y_{xi xi} y_{eta eta} ]
     885             :                 //     [ z_{xi xi} z_{eta eta} ]
     886     1588265 :                 DenseMatrix<Real> A(3,2);
     887     1588265 :                 A(0,0) = d2xyzdxi2_map[p](0);  A(0,1) = d2xyzdeta2_map[p](0);
     888     1473030 :                 A(1,0) = d2xyzdxi2_map[p](1);  A(1,1) = d2xyzdeta2_map[p](1);
     889     1473030 :                 A(2,0) = d2xyzdxi2_map[p](2);  A(2,1) = d2xyzdeta2_map[p](2);
     890             : 
     891             :                 // J^T, the transpose of the Jacobian matrix
     892     1588265 :                 DenseMatrix<Real> JT(2,3);
     893     1357795 :                 JT(0,0) = dx_dxi;   JT(0,1) = dy_dxi;   JT(0,2) = dz_dxi;
     894     1473030 :                 JT(1,0) = dx_deta;  JT(1,1) = dy_deta;  JT(1,2) = dz_deta;
     895             : 
     896             :                 // (J^T J)^(-1), this has already been computed for us above...
     897     1588265 :                 DenseMatrix<Real> JTJinv(2,2);
     898     1357795 :                 JTJinv(0,0) = g11inv;  JTJinv(0,1) = g12inv;
     899     1357795 :                 JTJinv(1,0) = g21inv;  JTJinv(1,1) = g22inv;
     900             : 
     901             :                 // Some helper variables
     902             :                 RealVectorValue
     903      460940 :                   dxi  (dxidx_map[p],   dxidy_map[p],   dxidz_map[p]),
     904      460940 :                   deta (detadx_map[p],  detady_map[p],  detadz_map[p]);
     905             : 
     906             :                 // To be filled in below
     907     1357795 :                 DenseVector<Real> tmp1(2);
     908     1357795 :                 DenseVector<Real> tmp2(3);
     909     1357795 :                 DenseVector<Real> tmp3(2);
     910             : 
     911             :                 // For (s,t) in {(x,x), (x,y), (x,z), (y,y), (y,z), (z,z)}, compute the
     912             :                 // vector of inverse map second derivatives [xi_{s t}, eta_{s t}]
     913      115235 :                 unsigned ctr=0;
     914     5431180 :                 for (unsigned s=0; s<3; ++s)
     915    12220155 :                   for (unsigned t=s; t<3; ++t)
     916             :                     {
     917             :                       // Construct tmp1 = [xi_s*xi_t, eta_s*eta_t]
     918     8146770 :                       tmp1(0) = dxi(s)*dxi(t);
     919     8146770 :                       tmp1(1) = deta(s)*deta(t);
     920             : 
     921             :                       // Compute tmp2 = A * tmp1
     922     8146770 :                       A.vector_mult(tmp2, tmp1);
     923             : 
     924             :                       // Compute scalar value "alpha"
     925     8146770 :                       Real alpha = dxi(s)*deta(t) + deta(s)*dxi(t);
     926             : 
     927             :                       // Compute tmp2 <- tmp2 + alpha * x_{xi eta}
     928    32587080 :                       for (unsigned i=0; i<3; ++i)
     929    28588770 :                         tmp2(i) += alpha*d2xyzdxideta_map[p](i);
     930             : 
     931             :                       // Compute tmp3 = J^T * tmp2
     932     8146770 :                       JT.vector_mult(tmp3, tmp2);
     933             : 
     934             :                       // Compute tmp1 = (J^T J)^(-1) * tmp3.  tmp1 is available for us to reuse.
     935     8146770 :                       JTJinv.vector_mult(tmp1, tmp3);
     936             : 
     937             :                       // Fill in appropriate entries, don't forget to multiply by -1!
     938     8838180 :                       d2xidxyz2_map[p][ctr]  = -tmp1(0);
     939     8838180 :                       d2etadxyz2_map[p][ctr] = -tmp1(1);
     940             : 
     941             :                       // Increment the counter
     942     8146770 :                       ctr++;
     943             :                     }
     944     1127325 :               }
     945             : 
     946             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
     947             : 
     948             : #endif // LIBMESH_DIM == 3
     949             :           }
     950             :         // done computing the map
     951     8660419 :         break;
     952             :       }
     953             : 
     954             : 
     955             : 
     956             :       //--------------------------------------------------------------------
     957             :       // 3D
     958    36095813 :     case 3:
     959             :       {
     960             :         //------------------------------------------------------------------
     961             :         // Compute the (x,y,z) values at the quadrature points,
     962             :         // the Jacobian at the quadrature point
     963             : 
     964             :         // Clear the entities that will be summed
     965    36095813 :         if (calculate_xyz)
     966    16795264 :           xyz[p].zero           ();
     967    36095813 :         if (calculate_dxyz)
     968             :           {
     969    32012690 :             dxyzdxi_map[p].zero   ();
     970     5286062 :             dxyzdeta_map[p].zero  ();
     971     5286062 :             dxyzdzeta_map[p].zero ();
     972             :           }
     973             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     974    36095813 :         if (calculate_d2xyz)
     975             :           {
     976     6263849 :             d2xyzdxi2_map[p].zero();
     977     1023344 :             d2xyzdxideta_map[p].zero();
     978     1023344 :             d2xyzdxidzeta_map[p].zero();
     979     1023344 :             d2xyzdeta2_map[p].zero();
     980     1023344 :             d2xyzdetadzeta_map[p].zero();
     981     1023344 :             d2xyzdzeta2_map[p].zero();
     982             :             // Inverse map second derivatives
     983     6775521 :             d2xidxyz2_map[p].assign(6, 0.);
     984     6775521 :             d2etadxyz2_map[p].assign(6, 0.);
     985     6775521 :             d2zetadxyz2_map[p].assign(6, 0.);
     986             :           }
     987             : #endif
     988             : 
     989             : 
     990             :         // compute (x,y,z) at the quadrature points,
     991             :         // dxdxi,   dydxi,   dzdxi,
     992             :         // dxdeta,  dydeta,  dzdeta,
     993             :         // dxdzeta, dydzeta, dzdzeta  all once
     994   518849643 :         for (auto i : index_range(elem_nodes)) // sum over the nodes
     995             :           {
     996             :             // Reference to the point, helps eliminate
     997             :             // excessive temporaries in the inner loop
     998    39568502 :             libmesh_assert(elem_nodes[i]);
     999   482753830 :             const Point & elem_point = *elem_nodes[i];
    1000             : 
    1001   482753830 :             if (calculate_xyz)
    1002   277503852 :               xyz[p].add_scaled           (elem_point, phi_map[i][p]      );
    1003   482753830 :             if (calculate_dxyz)
    1004             :               {
    1005   486254800 :                 dxyzdxi_map[p].add_scaled   (elem_point, dphidxi_map[i][p]  );
    1006   486254800 :                 dxyzdeta_map[p].add_scaled  (elem_point, dphideta_map[i][p] );
    1007   486254800 :                 dxyzdzeta_map[p].add_scaled (elem_point, dphidzeta_map[i][p]);
    1008             :               }
    1009             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1010   482753830 :             if (calculate_d2xyz)
    1011             :               {
    1012   101380770 :                 d2xyzdxi2_map[p].add_scaled      (elem_point,
    1013    23292834 :                                                   d2phidxi2_map[i][p]);
    1014   101380770 :                 d2xyzdxideta_map[p].add_scaled   (elem_point,
    1015    23292834 :                                                   d2phidxideta_map[i][p]);
    1016   101380770 :                 d2xyzdxidzeta_map[p].add_scaled  (elem_point,
    1017    23292834 :                                                   d2phidxidzeta_map[i][p]);
    1018   101380770 :                 d2xyzdeta2_map[p].add_scaled     (elem_point,
    1019    23292834 :                                                   d2phideta2_map[i][p]);
    1020   101380770 :                 d2xyzdetadzeta_map[p].add_scaled (elem_point,
    1021    23292834 :                                                   d2phidetadzeta_map[i][p]);
    1022   101380770 :                 d2xyzdzeta2_map[p].add_scaled    (elem_point,
    1023    23292834 :                                                   d2phidzeta2_map[i][p]);
    1024             :               }
    1025             : #endif
    1026             :           }
    1027             : 
    1028    36095813 :         if (calculate_dxyz)
    1029             :           {
    1030             :             // compute the jacobian
    1031             :             const Real
    1032     2643164 :               dx_dxi   = dxdxi_map(p),   dy_dxi   = dydxi_map(p),   dz_dxi   = dzdxi_map(p),
    1033     2643164 :               dx_deta  = dxdeta_map(p),  dy_deta  = dydeta_map(p),  dz_deta  = dzdeta_map(p),
    1034     2643164 :               dx_dzeta = dxdzeta_map(p), dy_dzeta = dydzeta_map(p), dz_dzeta = dzdzeta_map(p);
    1035             : 
    1036             :             // Symbolically, the matrix determinant is
    1037             :             //
    1038             :             //         | dx/dxi   dy/dxi   dz/dxi   |
    1039             :             // jac =   | dx/deta  dy/deta  dz/deta  |
    1040             :             //         | dx/dzeta dy/dzeta dz/dzeta |
    1041             :             //
    1042             :             // jac = dx/dxi*(dy/deta*dz/dzeta - dz/deta*dy/dzeta) +
    1043             :             //       dy/dxi*(dz/deta*dx/dzeta - dx/deta*dz/dzeta) +
    1044             :             //       dz/dxi*(dx/deta*dy/dzeta - dy/deta*dx/dzeta)
    1045             : 
    1046    47870876 :             jac[p] = (dx_dxi*(dy_deta*dz_dzeta - dz_deta*dy_dzeta)  +
    1047    37298752 :                       dy_dxi*(dz_deta*dx_dzeta - dx_deta*dz_dzeta)  +
    1048    32012690 :                       dz_dxi*(dx_deta*dy_dzeta - dy_deta*dx_dzeta));
    1049             : 
    1050    32012690 :             check_for_degenerate_map(jac[p]);
    1051             : 
    1052    37298486 :             JxW[p] = jac[p]*qw[p];
    1053             : 
    1054             :             // Compute the shape function derivatives wrt x,y at the
    1055             :             // quadrature points
    1056    32012690 :             const Real inv_jac  = 1./jac[p];
    1057             : 
    1058    32012690 :             dxidx_map[p]   = (dy_deta*dz_dzeta - dz_deta*dy_dzeta)*inv_jac;
    1059    32012690 :             dxidy_map[p]   = (dz_deta*dx_dzeta - dx_deta*dz_dzeta)*inv_jac;
    1060    32012690 :             dxidz_map[p]   = (dx_deta*dy_dzeta - dy_deta*dx_dzeta)*inv_jac;
    1061             : 
    1062    32012690 :             detadx_map[p]  = (dz_dxi*dy_dzeta  - dy_dxi*dz_dzeta )*inv_jac;
    1063    32012690 :             detady_map[p]  = (dx_dxi*dz_dzeta  - dz_dxi*dx_dzeta )*inv_jac;
    1064    32012690 :             detadz_map[p]  = (dy_dxi*dx_dzeta  - dx_dxi*dy_dzeta )*inv_jac;
    1065             : 
    1066    32012690 :             dzetadx_map[p] = (dy_dxi*dz_deta   - dz_dxi*dy_deta  )*inv_jac;
    1067    32012690 :             dzetady_map[p] = (dz_dxi*dx_deta   - dx_dxi*dz_deta  )*inv_jac;
    1068    34655588 :             dzetadz_map[p] = (dx_dxi*dy_deta   - dy_dxi*dx_deta  )*inv_jac;
    1069             :           }
    1070             : 
    1071             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1072    36095813 :         if (compute_second_derivatives)
    1073      409096 :           this->compute_inverse_map_second_derivs(p);
    1074             : #endif
    1075             :         // done computing the map
    1076     2974053 :         break;
    1077             :       }
    1078             : 
    1079           0 :     default:
    1080           0 :       libmesh_error_msg("Invalid dim = " << dim);
    1081             :     }
    1082             : }
    1083             : 
    1084             : 
    1085             : 
    1086   168445825 : void FEMap::resize_quadrature_map_vectors(const unsigned int dim, unsigned int n_qp)
    1087             : {
    1088             :   // We're calculating now!
    1089    14122926 :   this->determine_calculations();
    1090             : 
    1091             :   // Resize the vectors to hold data at the quadrature points
    1092   168445825 :   if (calculate_xyz)
    1093    35395161 :     xyz.resize(n_qp);
    1094   168445825 :   if (calculate_dxyz)
    1095             :     {
    1096   150966372 :       dxyzdxi_map.resize(n_qp);
    1097   150966372 :       dxidx_map.resize(n_qp);
    1098   150966372 :       dxidy_map.resize(n_qp); // 1D element may live in 2D ...
    1099   150966372 :       dxidz_map.resize(n_qp); // ... or 3D
    1100             :     }
    1101             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1102   168445825 :   if (calculate_d2xyz)
    1103             :     {
    1104    49935745 :       d2xyzdxi2_map.resize(n_qp);
    1105             : 
    1106             :       // Inverse map second derivatives
    1107    49935745 :       d2xidxyz2_map.resize(n_qp);
    1108   246138105 :       for (auto i : index_range(d2xidxyz2_map))
    1109   208871236 :         d2xidxyz2_map[i].assign(6, 0.);
    1110             :     }
    1111             : #endif
    1112   168445825 :   if (dim > 1)
    1113             :     {
    1114   123267471 :       if (calculate_dxyz)
    1115             :         {
    1116   108122101 :           dxyzdeta_map.resize(n_qp);
    1117   108122101 :           detadx_map.resize(n_qp);
    1118   108122101 :           detady_map.resize(n_qp);
    1119   108122101 :           detadz_map.resize(n_qp);
    1120             :         }
    1121             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1122   123267471 :       if (calculate_d2xyz)
    1123             :         {
    1124     7429728 :           d2xyzdxideta_map.resize(n_qp);
    1125     7429728 :           d2xyzdeta2_map.resize(n_qp);
    1126             : 
    1127             :           // Inverse map second derivatives
    1128     7429728 :           d2etadxyz2_map.resize(n_qp);
    1129    33658503 :           for (auto i : index_range(d2etadxyz2_map))
    1130    28397853 :             d2etadxyz2_map[i].assign(6, 0.);
    1131             :         }
    1132             : #endif
    1133   123267471 :       if (dim > 2)
    1134             :         {
    1135    30806316 :           if (calculate_dxyz)
    1136             :             {
    1137    26745537 :               dxyzdzeta_map.resize (n_qp);
    1138    26745537 :               dzetadx_map.resize   (n_qp);
    1139    26745537 :               dzetady_map.resize   (n_qp);
    1140    26745537 :               dzetadz_map.resize   (n_qp);
    1141             :             }
    1142             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1143    30806316 :           if (calculate_d2xyz)
    1144             :             {
    1145     6231677 :               d2xyzdxidzeta_map.resize(n_qp);
    1146     6231677 :               d2xyzdetadzeta_map.resize(n_qp);
    1147     6231677 :               d2xyzdzeta2_map.resize(n_qp);
    1148             : 
    1149             :               // Inverse map second derivatives
    1150     6231677 :               d2zetadxyz2_map.resize(n_qp);
    1151    24170859 :               for (auto i : index_range(d2zetadxyz2_map))
    1152    19415251 :                 d2zetadxyz2_map[i].assign(6, 0.);
    1153             :             }
    1154             : #endif
    1155             :         }
    1156             :     }
    1157             : 
    1158   168445825 :   if (calculate_dxyz)
    1159             :     {
    1160   150966372 :       jac.resize(n_qp);
    1161   150966372 :       JxW.resize(n_qp);
    1162             :     }
    1163   168445825 : }
    1164             : 
    1165             : 
    1166             : 
    1167   167224669 : void FEMap::compute_affine_map(const unsigned int dim,
    1168             :                                const std::vector<Real> & qw,
    1169             :                                const Elem * elem)
    1170             : {
    1171             :   // Start logging the map computation.
    1172    28054030 :   LOG_SCOPE("compute_affine_map()", "FEMap");
    1173             : 
    1174    14027015 :   libmesh_assert(elem);
    1175             : 
    1176    27787460 :   const unsigned int n_qp = cast_int<unsigned int>(qw.size());
    1177             : 
    1178             :   // Resize the vectors to hold data at the quadrature points
    1179   167224669 :   this->resize_quadrature_map_vectors(dim, n_qp);
    1180             : 
    1181             :   // Determine the nodes contributing to element elem
    1182   167224669 :   unsigned int n_nodes = elem->n_nodes();
    1183   167224669 :   _elem_nodes.resize(elem->n_nodes());
    1184  1128883522 :   for (unsigned int i=0; i<n_nodes; i++)
    1185  1124116101 :     _elem_nodes[i] = elem->node_ptr(i);
    1186             : 
    1187             :   // Compute map at quadrature point 0
    1188   167224669 :   this->compute_single_point_map(dim, qw, elem, 0, _elem_nodes, /*compute_second_derivatives=*/false);
    1189             : 
    1190             :   // Compute xyz at all other quadrature points
    1191   167224669 :   if (calculate_xyz)
    1192   190239041 :     for (unsigned int p=1; p<n_qp; p++)
    1193             :       {
    1194   155109375 :         xyz[p].zero();
    1195  1880553343 :         for (auto i : index_range(phi_map)) // sum over the nodes
    1196  2019180252 :           xyz[p].add_scaled (*_elem_nodes[i], phi_map[i][p]);
    1197             :       }
    1198             : 
    1199             :   // Copy other map data from quadrature point 0
    1200   167224669 :   if (calculate_dxyz)
    1201   646631182 :     for (unsigned int p=1; p<n_qp; p++) // for each extra quadrature point
    1202             :       {
    1203   496877758 :         dxyzdxi_map[p] = dxyzdxi_map[0];
    1204   496877758 :         dxidx_map[p] = dxidx_map[0];
    1205   496877758 :         dxidy_map[p] = dxidy_map[0];
    1206   496877758 :         dxidz_map[p] = dxidz_map[0];
    1207             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1208             :         // The map should be affine, so second derivatives are zero
    1209   496877758 :         if (calculate_d2xyz)
    1210    19458604 :           d2xyzdxi2_map[p] = 0.;
    1211             : #endif
    1212   496877758 :         if (dim > 1)
    1213             :           {
    1214   369318316 :             dxyzdeta_map[p] = dxyzdeta_map[0];
    1215   369318316 :             detadx_map[p] = detadx_map[0];
    1216   369318316 :             detady_map[p] = detady_map[0];
    1217   369318316 :             detadz_map[p] = detadz_map[0];
    1218             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1219   369318316 :             if (calculate_d2xyz)
    1220             :               {
    1221     3084342 :                 d2xyzdxideta_map[p] = 0.;
    1222     3084342 :                 d2xyzdeta2_map[p] = 0.;
    1223             :               }
    1224             : #endif
    1225   369318316 :             if (dim > 2)
    1226             :               {
    1227    98243817 :                 dxyzdzeta_map[p] = dxyzdzeta_map[0];
    1228    98243817 :                 dzetadx_map[p] = dzetadx_map[0];
    1229    98243817 :                 dzetady_map[p] = dzetady_map[0];
    1230    98243817 :                 dzetadz_map[p] = dzetadz_map[0];
    1231             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1232    98243817 :                 if (calculate_d2xyz)
    1233             :                   {
    1234     1928794 :                     d2xyzdxidzeta_map[p] = 0.;
    1235     1928794 :                     d2xyzdetadzeta_map[p] = 0.;
    1236     1928794 :                     d2xyzdzeta2_map[p] = 0.;
    1237             :                   }
    1238             : #endif
    1239             :               }
    1240             :           }
    1241   496877758 :         jac[p] = jac[0];
    1242   578033676 :         JxW[p] = JxW[0] / qw[0] * qw[p];
    1243             :       }
    1244   167224669 : }
    1245             : 
    1246             : 
    1247             : 
    1248           0 : void FEMap::compute_null_map(const unsigned int dim,
    1249             :                              const std::vector<Real> & qw)
    1250             : {
    1251             :   // Start logging the map computation.
    1252           0 :   LOG_SCOPE("compute_null_map()", "FEMap");
    1253             : 
    1254           0 :   const unsigned int n_qp = cast_int<unsigned int>(qw.size());
    1255             : 
    1256             :   // Resize the vectors to hold data at the quadrature points
    1257           0 :   this->resize_quadrature_map_vectors(dim, n_qp);
    1258             : 
    1259             :   // Compute "fake" xyz
    1260           0 :   for (unsigned int p=1; p<n_qp; p++)
    1261             :     {
    1262           0 :       if (calculate_xyz)
    1263           0 :         xyz[p].zero();
    1264             : 
    1265           0 :       if (calculate_dxyz)
    1266             :         {
    1267           0 :           dxyzdxi_map[p] = 0;
    1268           0 :           dxidx_map[p] = 0;
    1269           0 :           dxidy_map[p] = 0;
    1270           0 :           dxidz_map[p] = 0;
    1271             :         }
    1272             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1273           0 :       if (calculate_d2xyz)
    1274             :         {
    1275           0 :           d2xyzdxi2_map[p] = 0;
    1276             :         }
    1277             : #endif
    1278           0 :       if (dim > 1)
    1279             :         {
    1280           0 :           if (calculate_dxyz)
    1281             :             {
    1282           0 :               dxyzdeta_map[p] = 0;
    1283           0 :               detadx_map[p] = 0;
    1284           0 :               detady_map[p] = 0;
    1285           0 :               detadz_map[p] = 0;
    1286             :             }
    1287             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1288           0 :           if (calculate_d2xyz)
    1289             :             {
    1290           0 :               d2xyzdxideta_map[p] = 0.;
    1291           0 :               d2xyzdeta2_map[p] = 0.;
    1292             :             }
    1293             : #endif
    1294           0 :           if (dim > 2)
    1295             :             {
    1296           0 :               if (calculate_dxyz)
    1297             :                 {
    1298           0 :                   dxyzdzeta_map[p] = 0;
    1299           0 :                   dzetadx_map[p] = 0;
    1300           0 :                   dzetady_map[p] = 0;
    1301           0 :                   dzetadz_map[p] = 0;
    1302             :                 }
    1303             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1304           0 :               if (calculate_d2xyz)
    1305             :                 {
    1306           0 :                   d2xyzdxidzeta_map[p] = 0;
    1307           0 :                   d2xyzdetadzeta_map[p] = 0;
    1308           0 :                   d2xyzdzeta2_map[p] = 0;
    1309             :                 }
    1310             : #endif
    1311             :             }
    1312             :         }
    1313           0 :       if (calculate_dxyz)
    1314             :         {
    1315           0 :           jac[p] = 1;
    1316           0 :           JxW[p] = qw[p];
    1317             :         }
    1318             :     }
    1319           0 : }
    1320             : 
    1321             : 
    1322             : 
    1323   168445825 : void FEMap::compute_map(const unsigned int dim,
    1324             :                         const std::vector<Real> & qw,
    1325             :                         const Elem * elem,
    1326             :                         bool calculate_d2phi)
    1327             : {
    1328   168445825 :   if (!elem)
    1329             :     {
    1330           0 :       compute_null_map(dim, qw);
    1331    14027015 :       return;
    1332             :     }
    1333             : 
    1334   168445825 :   if (elem->has_affine_map())
    1335             :     {
    1336   167224669 :       compute_affine_map(dim, qw, elem);
    1337   167224669 :       return;
    1338             :     }
    1339             : #ifndef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1340             :     libmesh_assert(!calculate_d2phi);
    1341             : #endif
    1342             : 
    1343             :   // Start logging the map computation.
    1344      191822 :   LOG_SCOPE("compute_map()", "FEMap");
    1345             : 
    1346       95911 :   libmesh_assert(elem);
    1347             : 
    1348      191818 :   const unsigned int n_qp = cast_int<unsigned int>(qw.size());
    1349             : 
    1350             :   // Resize the vectors to hold data at the quadrature points
    1351     1221156 :   this->resize_quadrature_map_vectors(dim, n_qp);
    1352             : 
    1353             :   // Determine the nodes contributing to element elem
    1354     1221156 :   if (elem->type() == TRI3SUBDIVISION)
    1355             :     {
    1356             :       // Subdivision surface FE require the 1-ring around elem
    1357         256 :       libmesh_assert_equal_to (dim, 2);
    1358         256 :       const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
    1359        3072 :       MeshTools::Subdivision::find_one_ring(sd_elem, _elem_nodes);
    1360             :     }
    1361             :   else
    1362             :     {
    1363             :       // All other FE use only the nodes of elem itself
    1364     1218084 :       _elem_nodes.resize(elem->n_nodes(), nullptr);
    1365    12921987 :       for (auto i : elem->node_index_range())
    1366    13516111 :         _elem_nodes[i] = elem->node_ptr(i);
    1367             :     }
    1368             : 
    1369             :   // Compute map at all quadrature points
    1370     9513107 :   for (unsigned int p=0; p!=n_qp; p++)
    1371     8291951 :     this->compute_single_point_map(dim, qw, elem, p, _elem_nodes, calculate_d2phi);
    1372             : }
    1373             : 
    1374             : 
    1375             : 
    1376           0 : void FEMap::print_JxW(std::ostream & os) const
    1377             : {
    1378           0 :   for (auto i : index_range(JxW))
    1379           0 :     os << " [" << i << "]: " << JxW[i] << std::endl;
    1380           0 : }
    1381             : 
    1382             : 
    1383             : 
    1384           0 : void FEMap::print_xyz(std::ostream & os) const
    1385             : {
    1386           0 :   for (auto i : index_range(xyz))
    1387           0 :     os << " [" << i << "]: " << xyz[i];
    1388           0 : }
    1389             : 
    1390             : 
    1391             : 
    1392      409096 : void FEMap::compute_inverse_map_second_derivs(unsigned p)
    1393             : {
    1394             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1395             :   // Only certain second derivatives are valid depending on the
    1396             :   // dimension...
    1397       57090 :   std::set<unsigned> valid_indices;
    1398             : 
    1399             :   // Construct J^{-1}, A, and B matrices (see JWP's notes for details)
    1400             :   // for cases in which the element dimension matches LIBMESH_DIM.
    1401             : #if LIBMESH_DIM==1
    1402             :   RealTensor
    1403             :     Jinv(dxidx_map[p],  0.,  0.,
    1404             :          0.,            0.,  0.,
    1405             :          0.,            0.,  0.),
    1406             : 
    1407             :     A(d2xyzdxi2_map[p](0), 0., 0.,
    1408             :       0.,                  0., 0.,
    1409             :       0.,                  0., 0.),
    1410             : 
    1411             :     B(0., 0., 0.,
    1412             :       0., 0., 0.,
    1413             :       0., 0., 0.);
    1414             : 
    1415             :   RealVectorValue
    1416             :     dxi  (dxidx_map[p], 0., 0.),
    1417             :     deta (0.,           0., 0.),
    1418             :     dzeta(0.,           0., 0.);
    1419             : 
    1420             :   // In 1D, we have only the xx second derivative
    1421             :   valid_indices.insert(0);
    1422             : 
    1423             : #elif LIBMESH_DIM==2
    1424             :   RealTensor
    1425             :     Jinv(dxidx_map[p],  dxidy_map[p],  0.,
    1426             :          detadx_map[p], detady_map[p], 0.,
    1427             :          0.,            0.,            0.),
    1428             : 
    1429             :     A(d2xyzdxi2_map[p](0), d2xyzdeta2_map[p](0), 0.,
    1430             :       d2xyzdxi2_map[p](1), d2xyzdeta2_map[p](1), 0.,
    1431             :       0.,                  0.,                   0.),
    1432             : 
    1433             :     B(d2xyzdxideta_map[p](0), 0., 0.,
    1434             :       d2xyzdxideta_map[p](1), 0., 0.,
    1435             :       0.,                     0., 0.);
    1436             : 
    1437             :   RealVectorValue
    1438             :     dxi  (dxidx_map[p],  dxidy_map[p],  0.),
    1439             :     deta (detadx_map[p], detady_map[p], 0.),
    1440             :     dzeta(0.,            0.,            0.);
    1441             : 
    1442             :   // In 2D, we have xx, xy, and yy second derivatives
    1443             :   const unsigned tmp[3] = {0,1,3};
    1444             :   valid_indices.insert(tmp, tmp+3);
    1445             : 
    1446             : #elif LIBMESH_DIM==3
    1447             :   RealTensor
    1448      114180 :     Jinv(dxidx_map[p],   dxidy_map[p],   dxidz_map[p],
    1449      114180 :          detadx_map[p],  detady_map[p],  detadz_map[p],
    1450      523276 :          dzetadx_map[p], dzetady_map[p], dzetadz_map[p]),
    1451             : 
    1452       28545 :     A(d2xyzdxi2_map[p](0), d2xyzdeta2_map[p](0), d2xyzdzeta2_map[p](0),
    1453       28545 :       d2xyzdxi2_map[p](1), d2xyzdeta2_map[p](1), d2xyzdzeta2_map[p](1),
    1454      171270 :       d2xyzdxi2_map[p](2), d2xyzdeta2_map[p](2), d2xyzdzeta2_map[p](2)),
    1455             : 
    1456       28545 :     B(d2xyzdxideta_map[p](0), d2xyzdxidzeta_map[p](0), d2xyzdetadzeta_map[p](0),
    1457       28545 :       d2xyzdxideta_map[p](1), d2xyzdxidzeta_map[p](1), d2xyzdetadzeta_map[p](1),
    1458      171270 :       d2xyzdxideta_map[p](2), d2xyzdxidzeta_map[p](2), d2xyzdetadzeta_map[p](2));
    1459             : 
    1460             :   RealVectorValue
    1461       28545 :     dxi  (dxidx_map[p],   dxidy_map[p],   dxidz_map[p]),
    1462       28545 :     deta (detadx_map[p],  detady_map[p],  detadz_map[p]),
    1463       28545 :     dzeta(dzetadx_map[p], dzetady_map[p], dzetadz_map[p]);
    1464             : 
    1465             :   // In 3D, we have xx, xy, xz, yy, yz, and zz second derivatives
    1466      409096 :   const unsigned tmp[6] = {0,1,2,3,4,5};
    1467       28545 :   valid_indices.insert(tmp, tmp+6);
    1468             : 
    1469             : #endif
    1470             : 
    1471             :   // For (s,t) in {(x,x), (x,y), (x,z), (y,y), (y,z), (z,z)}, compute the
    1472             :   // vector of inverse map second derivatives [xi_{s t}, eta_{s t}, zeta_{s t}]
    1473      380551 :   unsigned ctr=0;
    1474     1636384 :   for (unsigned s=0; s<3; ++s)
    1475     3681864 :     for (unsigned t=s; t<3; ++t)
    1476             :       {
    1477      171270 :         if (valid_indices.count(ctr))
    1478             :           {
    1479             :             RealVectorValue
    1480     2454576 :               v1(dxi(s)*dxi(t),
    1481     2454576 :                  deta(s)*deta(t),
    1482     2625846 :                  dzeta(s)*dzeta(t)),
    1483             : 
    1484     2454576 :               v2(dxi(s)*deta(t) + deta(s)*dxi(t),
    1485     2454576 :                  dxi(s)*dzeta(t) + dzeta(s)*dxi(t),
    1486     2625846 :                  deta(s)*dzeta(t) + dzeta(s)*deta(t));
    1487             : 
    1488             :             // Compute the inverse map second derivatives
    1489     2454576 :             RealVectorValue v3 = -Jinv*(A*v1 + B*v2);
    1490             : 
    1491             :             // Store them in the appropriate locations in the class data structures
    1492     2625846 :             d2xidxyz2_map[p][ctr] = v3(0);
    1493             : 
    1494             :             if (LIBMESH_DIM > 1)
    1495     2625846 :               d2etadxyz2_map[p][ctr] = v3(1);
    1496             : 
    1497             :             if (LIBMESH_DIM > 2)
    1498     2797116 :               d2zetadxyz2_map[p][ctr] = v3(2);
    1499             :           }
    1500             : 
    1501             :         // Increment the counter
    1502     2454576 :         ctr++;
    1503             :       }
    1504             : #else
    1505             :    // to avoid compiler warnings:
    1506             :    libmesh_ignore(p);
    1507             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
    1508      409096 : }
    1509             : 
    1510             : 
    1511             : 
    1512   147961096 : Point FEMap::inverse_map (const unsigned int dim,
    1513             :                           const Elem * elem,
    1514             :                           const Point & physical_point,
    1515             :                           const Real tolerance,
    1516             :                           const bool secure,
    1517             :                           const bool
    1518             :                           extra_checks
    1519             :                           )
    1520             : {
    1521     9517943 :   libmesh_assert(elem);
    1522     9517943 :   libmesh_assert_greater_equal (tolerance, 0.);
    1523             : 
    1524     9517943 :   libmesh_ignore(extra_checks);
    1525             : 
    1526             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1527             : 
    1528             :   // TODO: possibly use the extra_checks parameter in InfFEMap::inverse_map() as well.
    1529             : 
    1530    25056915 :   if (elem->infinite())
    1531         716 :     return InfFEMap::inverse_map(dim, elem, physical_point, tolerance,
    1532         728 :                                  secure);
    1533             : #endif
    1534             : 
    1535             :   // Start logging the map inversion.
    1536    19035156 :   LOG_SCOPE("inverse_map()", "FEMap");
    1537             : 
    1538             :   // How much did the point on the reference
    1539             :   // element change by in this Newton step?
    1540     9517578 :   Real inverse_map_error = 0.;
    1541             : 
    1542             :   //  The point on the reference element.  This is
    1543             :   //  the "initial guess" for Newton's method.  The
    1544             :   //  centroid seems like a good idea, but computing
    1545             :   //  it is a little more intensive than, say taking
    1546             :   //  the zero point.
    1547             :   //
    1548             :   //  Convergence should be insensitive of this choice
    1549             :   //  for "good" elements.
    1550     9517578 :   Point p; // the zero point.  No computation required
    1551             : 
    1552             :   //  The number of iterations in the map inversion process.
    1553     9517578 :   unsigned int cnt = 0;
    1554             : 
    1555             :   //  The number of iterations after which we give up and declare
    1556             :   //  divergence
    1557     9517578 :   const unsigned int max_cnt = 10;
    1558             : 
    1559             :   //  The distance (in master element space) beyond which we give up
    1560             :   //  and declare divergence.  This is no longer used...
    1561             :   // Real max_step_length = 4.;
    1562             : 
    1563             : 
    1564             : 
    1565             :   //  Newton iteration loop.
    1566     9322028 :   do
    1567             :     {
    1568             :       //  Where our current iterate \p p maps to.
    1569   295974123 :       const Point physical_guess = map(dim, elem, p);
    1570             : 
    1571             :       //  How far our current iterate is from the actual point.
    1572    18839606 :       const Point delta = physical_point - physical_guess;
    1573             : 
    1574             :       //  Increment in current iterate \p p, will be computed.
    1575    18839606 :       Point dp;
    1576             : 
    1577             : 
    1578             :       //  The form of the map and how we invert it depends
    1579             :       //  on the dimension that we are in.
    1580   295974123 :       switch (dim)
    1581             :         {
    1582             :           // ------------------------------------------------------------------
    1583             :           //  0D map inversion is trivial
    1584        1070 :         case 0:
    1585             :           {
    1586        1070 :             break;
    1587             :           }
    1588             : 
    1589             :           // ------------------------------------------------------------------
    1590             :           //  1D map inversion
    1591             :           //
    1592             :           //  Here we find the point on a 1D reference element that maps to
    1593             :           //  the point \p physical_point in the domain.  This is a bit tricky
    1594             :           //  since we do not want to assume that the point \p physical_point
    1595             :           //  is also in a 1D domain.  In particular, this method might get
    1596             :           //  called on the edge of a 3D element, in which case
    1597             :           //  \p physical_point actually lives in 3D.
    1598     8865561 :         case 1:
    1599             :           {
    1600     8865561 :             const Point dxi = map_deriv (dim, elem, 0, p);
    1601             : 
    1602             :             //  Newton's method in this case looks like
    1603             :             //
    1604             :             //  {X} - {X_n} = [J]*dp
    1605             :             //
    1606             :             //  Where {X}, {X_n} are 3x1 vectors, [J] is a 3x1 matrix
    1607             :             //  d(x,y,z)/dxi, and we seek dp, a scalar.  Since the above
    1608             :             //  system is either overdetermined or rank-deficient, we will
    1609             :             //  solve the normal equations for this system
    1610             :             //
    1611             :             //  [J]^T ({X} - {X_n}) = [J]^T [J] {dp}
    1612             :             //
    1613             :             //  which involves the trivial inversion of the scalar
    1614             :             //  G = [J]^T [J]
    1615      968257 :             const Real G = dxi*dxi;
    1616             : 
    1617     8865561 :             if (secure && G <= 0)
    1618           0 :               libmesh_degenerate_mapping_msg
    1619             :                 ("inverse_map found a singular Jacobian " <<
    1620             :                  " at master point " << p << " in element " <<
    1621             :                  elem->id());
    1622             : 
    1623     8865561 :             const Real Ginv = 1./G;
    1624             : 
    1625      968257 :             const Real  dxidelta = dxi*delta;
    1626             : 
    1627     8865561 :             dp(0) = Ginv*dxidelta;
    1628             : 
    1629             :             // No master elements have radius > 4, but sometimes we
    1630             :             // can take a step that big while still converging
    1631             :             // if (secure)
    1632             :             // libmesh_assert_less (dp.size(), max_step_length);
    1633             : 
    1634      968257 :             break;
    1635             :           }
    1636             : 
    1637             : 
    1638             : 
    1639             :           // ------------------------------------------------------------------
    1640             :           //  2D map inversion
    1641             :           //
    1642             :           //  Here we find the point on a 2D reference element that maps to
    1643             :           //  the point \p physical_point in the domain.  This is a bit tricky
    1644             :           //  since we do not want to assume that the point \p physical_point
    1645             :           //  is also in a 2D domain.  In particular, this method might get
    1646             :           //  called on the face of a 3D element, in which case
    1647             :           //  \p physical_point actually lives in 3D.
    1648   127617708 :         case 2:
    1649             :           {
    1650   127617708 :             const Point dxi  = map_deriv (dim, elem, 0, p);
    1651   127617708 :             const Point deta = map_deriv (dim, elem, 1, p);
    1652             : 
    1653             :             //  Newton's method in this case looks like
    1654             :             //
    1655             :             //  {X} - {X_n} = [J]*{dp}
    1656             :             //
    1657             :             //  Where {X}, {X_n} are 3x1 vectors, [J] is a 3x2 matrix
    1658             :             //  d(x,y,z)/d(xi,eta), and we seek {dp}, a 2x1 vector.  Since
    1659             :             //  the above system is either over-determined or rank-deficient,
    1660             :             //  we will solve the normal equations for this system
    1661             :             //
    1662             :             //  [J]^T ({X} - {X_n}) = [J]^T [J] {dp}
    1663             :             //
    1664             :             //  which involves the inversion of the 2x2 matrix
    1665             :             //  [G] = [J]^T [J]
    1666             :             const Real
    1667    10853940 :               G11 = dxi*dxi,  G12 = dxi*deta,
    1668    10853940 :               G21 = dxi*deta, G22 = deta*deta;
    1669             : 
    1670             : 
    1671   127617708 :             const Real det = (G11*G22 - G12*G21);
    1672             : 
    1673   127617708 :             if (secure && det == 0)
    1674           0 :               libmesh_degenerate_mapping_msg
    1675             :                 ("inverse_map found a singular Jacobian " <<
    1676             :                  " at master point " << p << " in element " <<
    1677             :                  elem->id());
    1678             : 
    1679   127617708 :             const Real inv_det = 1./det;
    1680             : 
    1681             :             const Real
    1682   127617708 :               Ginv11 =  G22*inv_det,
    1683   127617708 :               Ginv12 = -G12*inv_det,
    1684             : 
    1685    10853940 :               Ginv21 = -G21*inv_det,
    1686   127617708 :               Ginv22 =  G11*inv_det;
    1687             : 
    1688             : 
    1689    10853940 :             const Real  dxidelta  = dxi*delta;
    1690    10853940 :             const Real  detadelta = deta*delta;
    1691             : 
    1692   127617708 :             dp(0) = (Ginv11*dxidelta + Ginv12*detadelta);
    1693   127617708 :             dp(1) = (Ginv21*dxidelta + Ginv22*detadelta);
    1694             : 
    1695             :             // No master elements have radius > 4, but sometimes we
    1696             :             // can take a step that big while still converging
    1697             :             // if (secure)
    1698             :             // libmesh_assert_less (dp.size(), max_step_length);
    1699             : 
    1700    10853940 :             break;
    1701             :           }
    1702             : 
    1703             : 
    1704             : 
    1705             :           // ------------------------------------------------------------------
    1706             :           //  3D map inversion
    1707             :           //
    1708             :           //  Here we find the point in a 3D reference element that maps to
    1709             :           //  the point \p physical_point in a 3D domain. Nothing special
    1710             :           //  has to happen here, since (unless the map is singular because
    1711             :           //  you have a BAD element) the map will be invertible and we can
    1712             :           //  apply Newton's method directly.
    1713   159473372 :         case 3:
    1714             :           {
    1715   159473372 :             const Point dxi   = map_deriv (dim, elem, 0, p);
    1716   159473372 :             const Point deta  = map_deriv (dim, elem, 1, p);
    1717   159473372 :             const Point dzeta = map_deriv (dim, elem, 2, p);
    1718             : 
    1719             :             //  Newton's method in this case looks like
    1720             :             //
    1721             :             //  {X} = {X_n} + [J]*{dp}
    1722             :             //
    1723             :             //  Where {X}, {X_n} are 3x1 vectors, [J] is a 3x3 matrix
    1724             :             //  d(x,y,z)/d(xi,eta,zeta), and we seek {dp}, a 3x1 vector.
    1725             :             //  Since the above system is nonsingular for invertible maps
    1726             :             //  we will solve
    1727             :             //
    1728             :             //  {dp} = [J]^-1 ({X} - {X_n})
    1729             :             //
    1730             :             //  which involves the inversion of the 3x3 matrix [J]
    1731             :             libmesh_try
    1732             :               {
    1733   159523497 :                 RealTensorValue(dxi(0), deta(0), dzeta(0),
    1734             :                                 dxi(1), deta(1), dzeta(1),
    1735   159473372 :                                 dxi(2), deta(2), dzeta(2)).solve(delta, dp);
    1736             :               }
    1737      604322 :             libmesh_catch (ConvergenceFailure &)
    1738             :               {
    1739             :                 // If we encountered a singular Jacobian, but are at
    1740             :                 // a singular node, return said singular node.
    1741             :                 const unsigned int local_singular_node =
    1742      573698 :                   elem->local_singular_node(physical_point, tolerance);
    1743      573698 :                 if (local_singular_node != invalid_uint)
    1744             :                 {
    1745         432 :                   libmesh_assert_less(local_singular_node, elem->n_nodes());
    1746       11952 :                   return elem->master_point(local_singular_node);
    1747             :                 }
    1748             : 
    1749             :                 // We encountered a singular Jacobian.  The value of
    1750             :                 // dp is zero, since it was never changed during the
    1751             :                 // call to RealTensorValue::solve().  We don't want to
    1752             :                 // continue iterating until max_cnt since there is no
    1753             :                 // update to the Newton iterate, and we don't want to
    1754             :                 // print the inverse_map_error value since it will
    1755             :                 // confusingly be 0.  Therefore, in the secure case we
    1756             :                 // need to throw an error message while in the !secure
    1757             :                 // case we can just return a far away point.
    1758      561746 :                 if (secure)
    1759             :                   {
    1760           0 :                     libmesh_degenerate_mapping_msg(
    1761             :                       "inverse_map found a singular Jacobian" <<
    1762             :                       " at master point " << p << " in element " <<
    1763             :                       elem->id());
    1764             :                   }
    1765             :                 else
    1766             :                   {
    1767     2246984 :                     for (unsigned int i=0; i != dim; ++i)
    1768     1685238 :                       p(i) = 1e6;
    1769      561746 :                     return p;
    1770             :                   }
    1771      543074 :               }
    1772             : 
    1773             :             // No master elements have radius > 4, but sometimes we
    1774             :             // can take a step that big while still converging
    1775             :             // if (secure)
    1776             :             // libmesh_assert_less (dp.size(), max_step_length);
    1777             : 
    1778   158899674 :             break;
    1779             :           }
    1780             : 
    1781             : 
    1782             :           //  Some other dimension?
    1783           0 :         default:
    1784           0 :           libmesh_error_msg("Invalid dim = " << dim);
    1785             :         } // end switch(Dim), dp now computed
    1786             : 
    1787             : 
    1788             : 
    1789             :       //  ||P_n+1 - P_n||
    1790   276768056 :       inverse_map_error = dp.norm();
    1791             : 
    1792             :       //  P_n+1 = P_n + dp
    1793    18824294 :       p.add (dp);
    1794             : 
    1795             :       //  Increment the iteration count.
    1796   295400425 :       cnt++;
    1797             : 
    1798             :       //  Watch for divergence of Newton's
    1799             :       //  method.  Here's how it goes:
    1800             :       //  (1) For good elements, we expect convergence in 10
    1801             :       //      iterations, with no too-large steps.
    1802             :       //      - If called with (secure == true) and we have not yet converged
    1803             :       //        print out a warning message.
    1804             :       //      - If called with (secure == true) and we have not converged in
    1805             :       //        20 iterations abort
    1806             :       //  (2) This method may be called in cases when the target point is not
    1807             :       //      inside the element and we have no business expecting convergence.
    1808             :       //      For these cases if we have not converged in 10 iterations forget
    1809             :       //      about it.
    1810   295400425 :       if (cnt > max_cnt)
    1811             :         {
    1812             :           //  Warn about divergence when secure is true - this
    1813             :           //  shouldn't happen
    1814      233632 :           if (secure)
    1815             :             {
    1816             :               // Print every time in devel/dbg modes
    1817             : #ifndef NDEBUG
    1818           0 :               libmesh_here();
    1819           0 :               libMesh::err << "WARNING: Newton scheme has not converged in "
    1820           0 :                            << cnt << " iterations:" << std::endl
    1821           0 :                            << "   physical_point="
    1822           0 :                            << physical_point
    1823           0 :                            << "   physical_guess="
    1824           0 :                            << physical_guess
    1825           0 :                            << "   dp="
    1826           0 :                            << dp
    1827           0 :                            << "   p="
    1828           0 :                            << p
    1829           0 :                            << "   error=" << inverse_map_error
    1830           0 :                            << "   in element " << elem->id()
    1831           0 :                            << std::endl;
    1832             : 
    1833           0 :               elem->print_info(libMesh::err);
    1834             : #else
    1835             :               // In optimized mode, just print once that an inverse_map() call
    1836             :               // had trouble converging its Newton iteration.
    1837           0 :               libmesh_do_once(libMesh::err << "WARNING: At least one element took more than "
    1838             :                               << max_cnt
    1839             :                               << " iterations to converge in inverse_map()...\n"
    1840             :                               << "Rerun in devel/dbg mode for more details."
    1841             :                               << std::endl;);
    1842             : 
    1843             : #endif // NDEBUG
    1844             : 
    1845           0 :               if (cnt > 2*max_cnt)
    1846             :                 {
    1847             :                   // Whether or not this is a degenerate map in the
    1848             :                   // "Jacobian becomes singular or negative" sense,
    1849             :                   // it's at least degenerate in the "straightforward
    1850             :                   // Newton is failing to invert it" sense.
    1851           0 :                   libmesh_degenerate_mapping_msg(
    1852             :                     "inverse_map Newton FAILED to converge in " <<
    1853             :                     cnt << " iterations in element " << elem->id() <<
    1854             :                     " for physical point = " << physical_point <<
    1855             :                     std::endl << elem->get_info());
    1856             :                 }
    1857             :             }
    1858             :           //  Return a far off point when secure is false - this
    1859             :           //  should only happen when we're trying to map a point
    1860             :           //  that's outside the element
    1861             :           else
    1862             :             {
    1863      932961 :               for (unsigned int i=0; i != dim; ++i)
    1864      699329 :                 p(i) = 1e6;
    1865             : 
    1866      233632 :               return p;
    1867             :             }
    1868             :         }
    1869             :     }
    1870   295166793 :   while (inverse_map_error > tolerance);
    1871             : 
    1872             : 
    1873             : 
    1874             :   //  If we are in debug mode and the user requested it, do two extra sanity checks.
    1875             : #ifdef DEBUG
    1876             : 
    1877     9497201 :   if (extra_checks)
    1878             :     {
    1879             :       // Make sure the point \p p on the reference element actually
    1880             :       // does map to the point \p physical_point within a tolerance.
    1881             : 
    1882     4504805 :       const Point check = map (dim, elem, p);
    1883     4504805 :       const Point diff  = physical_point - check;
    1884             : 
    1885     4504805 :       if (diff.norm() > tolerance)
    1886             :         {
    1887           0 :           libmesh_here();
    1888           0 :           libMesh::err << "WARNING:  diff is "
    1889           0 :                        << diff.norm()
    1890           0 :                        << std::endl
    1891           0 :                        << " point="
    1892           0 :                        << physical_point;
    1893           0 :           libMesh::err << " local=" << check;
    1894           0 :           libMesh::err << " lref= " << p;
    1895             : 
    1896           0 :           elem->print_info(libMesh::err);
    1897             :         }
    1898             : 
    1899             :       // Make sure the point \p p on the reference element actually
    1900             :       // is
    1901             : 
    1902     4504805 :       if (!elem->on_reference_element(p, 2*tolerance))
    1903             :         {
    1904           0 :           libmesh_here();
    1905           0 :           libMesh::err << "WARNING:  inverse_map of physical point "
    1906           0 :                        << physical_point
    1907           0 :                        << " is not on element." << '\n';
    1908           0 :           elem->print_info(libMesh::err);
    1909             :         }
    1910             :     }
    1911             : 
    1912             : #endif
    1913             : 
    1914   147152322 :   return p;
    1915             : }
    1916             : 
    1917             : 
    1918             : 
    1919     2580145 : void FEMap::inverse_map (const unsigned int dim,
    1920             :                          const Elem * elem,
    1921             :                          const std::vector<Point> & physical_points,
    1922             :                          std::vector<Point> &       reference_points,
    1923             :                          const Real tolerance,
    1924             :                          const bool secure,
    1925             :                          const bool extra_checks)
    1926             : {
    1927             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1928      784500 :   if (elem->infinite())
    1929             :     {
    1930             :       // TODO: possibly use the extra_checks parameter in InfFEMap::inverse_map() as well.
    1931           0 :       libmesh_ignore(extra_checks);
    1932             : 
    1933           0 :       return InfFEMap::inverse_map(dim, elem, physical_points, reference_points, tolerance, secure);
    1934             :     }
    1935             : #endif
    1936             : 
    1937             :   // The number of points to find the
    1938             :   // inverse map of
    1939      553276 :   const std::size_t n_points = physical_points.size();
    1940             : 
    1941             :   // Resize the vector to hold the points
    1942             :   // on the reference element
    1943     2580145 :   reference_points.resize(n_points);
    1944             : 
    1945             :   // Find the coordinates on the reference
    1946             :   // element of each point in physical space
    1947     8462111 :   for (std::size_t p=0; p<n_points; p++)
    1948     6452735 :     reference_points[p] =
    1949     6452735 :       inverse_map (dim, elem, physical_points[p], tolerance, secure, extra_checks);
    1950     1795645 : }
    1951             : 
    1952             : 
    1953             : 
    1954   331156593 : Point FEMap::map (const unsigned int dim,
    1955             :                   const Elem * elem,
    1956             :                   const Point & reference_point)
    1957             : {
    1958    25812479 :   libmesh_assert(elem);
    1959    25812479 :   libmesh_ignore(dim);
    1960             : 
    1961             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1962    60266252 :   if (elem->infinite())
    1963          80 :     return InfFEMap::map(dim, elem, reference_point);
    1964             : #endif
    1965             : 
    1966    25812447 :   Point p;
    1967             : 
    1968   331156513 :   const FEFamily mapping_family = FEMap::map_fe_type(*elem);
    1969   331156513 :   const FEType fe_type (elem->default_order(), mapping_family);
    1970             : 
    1971             :   // Do not consider the Elem::p_level(), if any, when computing the
    1972             :   // number of shape functions.
    1973   331156513 :   const unsigned int n_sf = FEInterface::n_shape_functions(fe_type, /*extra_order=*/0, elem);
    1974             : 
    1975             :   FEInterface::shape_ptr shape_ptr =
    1976   331156513 :     FEInterface::shape_function(fe_type, elem);
    1977             : 
    1978             :   // Lagrange basis functions are used for mapping
    1979  3760621932 :   for (unsigned int i=0; i<n_sf; i++)
    1980  3429465419 :     p.add_scaled (elem->point(i),
    1981  3657768237 :                   shape_ptr(fe_type, elem, i, reference_point, false));
    1982             : 
    1983   331156513 :   return p;
    1984             : }
    1985             : 
    1986             : 
    1987             : 
    1988   794695281 : Point FEMap::map_deriv (const unsigned int dim,
    1989             :                         const Elem * elem,
    1990             :                         const unsigned int j,
    1991             :                         const Point & reference_point)
    1992             : {
    1993    48442331 :   libmesh_assert(elem);
    1994    48442331 :   libmesh_ignore(dim);
    1995             : 
    1996   129364309 :   if (elem->infinite())
    1997           0 :     libmesh_not_implemented();
    1998             : 
    1999    48442331 :   Point p;
    2000             : 
    2001   794695281 :   const FEFamily mapping_family = FEMap::map_fe_type(*elem);
    2002   794695281 :   const FEType fe_type (elem->default_order(), mapping_family);
    2003             : 
    2004             :   // Do not consider the Elem::p_level(), if any, when computing the
    2005             :   // number of shape functions.
    2006             :   const unsigned int n_sf =
    2007   794695281 :     FEInterface::n_shape_functions(fe_type, /*total_order=*/0, elem);
    2008             : 
    2009             :   FEInterface::shape_deriv_ptr shape_deriv_ptr =
    2010   794695281 :     FEInterface::shape_deriv_function(fe_type, elem);
    2011             : 
    2012             :   // Lagrange basis functions are used for mapping
    2013  9757942248 :   for (unsigned int i=0; i<n_sf; i++)
    2014  8963246967 :     p.add_scaled (elem->point(i),
    2015  9449709548 :                   shape_deriv_ptr(fe_type, elem, i, j, reference_point,
    2016             :                                   /*add_p_level=*/false));
    2017             : 
    2018   843137612 :   return p;
    2019             : }
    2020             : 
    2021             : 
    2022             : 
    2023             : // Explicit instantiation of FEMap member functions
    2024             : template LIBMESH_EXPORT void FEMap::init_reference_to_physical_map<0>( const std::vector<Point> &, const Elem *);
    2025             : template LIBMESH_EXPORT void FEMap::init_reference_to_physical_map<1>( const std::vector<Point> &, const Elem *);
    2026             : template LIBMESH_EXPORT void FEMap::init_reference_to_physical_map<2>( const std::vector<Point> &, const Elem *);
    2027             : template LIBMESH_EXPORT void FEMap::init_reference_to_physical_map<3>( const std::vector<Point> &, const Elem *);
    2028             : 
    2029             : // subdivision elements are implemented only for 2D meshes & reimplement
    2030             : // the inverse_maps method separately
    2031             : INSTANTIATE_SUBDIVISION_MAPS;
    2032             : 
    2033             : } // namespace libMesh

Generated by: LCOV version 1.14