LCOV - code coverage report
Current view: top level - src/fe - fe_hierarchic_shape_2D.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 326 374 87.2 %
Date: 2025-08-19 19:27:09 Functions: 29 47 61.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : // Local includes
      20             : #include "libmesh/fe.h"
      21             : #include "libmesh/elem.h"
      22             : #include "libmesh/number_lookups.h"
      23             : #include "libmesh/enum_to_string.h"
      24             : 
      25             : // Anonymous namespace for functions shared by HIERARCHIC and
      26             : // L2_HIERARCHIC implementations. Implementations appear at the bottom
      27             : // of this file.
      28             : namespace
      29             : {
      30             : using namespace libMesh;
      31             : 
      32             : Real fe_triangle_helper (const Elem & elem,
      33             :                          const Real edgenumerator,
      34             :                          const Real crossval,
      35             :                          const unsigned int basisorder,
      36             :                          const Order totalorder,
      37             :                          const unsigned int noden);
      38             : 
      39             : template <FEFamily T>
      40             : Real fe_hierarchic_2D_shape(const Elem * elem,
      41             :                             const Order order,
      42             :                             const unsigned int i,
      43             :                             const Point & p,
      44             :                             const bool add_p_level);
      45             : 
      46             : template <FEFamily T>
      47             : Real fe_hierarchic_2D_shape_deriv(const Elem * elem,
      48             :                                   const Order order,
      49             :                                   const unsigned int i,
      50             :                                   const unsigned int j,
      51             :                                   const Point & p,
      52             :                                   const bool add_p_level);
      53             : 
      54             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      55             : 
      56             : template <FEFamily T>
      57             : Real fe_hierarchic_2D_shape_second_deriv(const Elem * elem,
      58             :                                          const Order order,
      59             :                                          const unsigned int i,
      60             :                                          const unsigned int j,
      61             :                                          const Point & p,
      62             :                                          const bool add_p_level);
      63             : 
      64             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
      65             : 
      66             : 
      67             : std::tuple<unsigned int, unsigned int, Real>
      68   293257527 : quad_indices(const Elem * elem,
      69             :              const unsigned int totalorder,
      70             :              const unsigned int i)
      71             : {
      72    24088245 :   libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u));
      73             : 
      74             :   // Example i, i0, i1 values for totalorder = 5:
      75             :   //                                    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
      76             :   //  static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 0, 0, 0, 0, 2, 3, 3, 2, 4, 4, 4, 3, 2, 5, 5, 5, 5, 4, 3, 2};
      77             :   //  static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 2, 2, 3, 3, 2, 3, 4, 4, 4, 2, 3, 4, 5, 5, 5, 5};
      78             : 
      79             :   unsigned int i0, i1;
      80             : 
      81             :   // Vertex DoFs
      82    48177277 :   if (i == 0)
      83     1382150 :     { i0 = 0; i1 = 0; }
      84    45412934 :   else if (i == 1)
      85     1382150 :     { i0 = 1; i1 = 0; }
      86    42648591 :   else if (i == 2)
      87     1382150 :     { i0 = 1; i1 = 1; }
      88    39884248 :   else if (i == 3)
      89     1382150 :     { i0 = 0; i1 = 1; }
      90             :   // Edge DoFs
      91   225721487 :   else if (i < totalorder + 3u)
      92    34444787 :     { i0 = i - 2; i1 = 0; }
      93   191276700 :   else if (i < 2u*totalorder + 2)
      94    34444787 :     { i0 = 1; i1 = i - totalorder - 1; }
      95   156831913 :   else if (i < 3u*totalorder + 1)
      96    34444787 :     { i0 = i - 2u*totalorder; i1 = 1; }
      97   122387126 :   else if (i < 4u*totalorder)
      98    34444787 :     { i0 = 0; i1 = i - 3u*totalorder + 1; }
      99             :   // Interior DoFs
     100             :   else
     101             :     {
     102    87942339 :       unsigned int basisnum = i - 4*totalorder;
     103    87942339 :       i0 = square_number_column[basisnum] + 2;
     104    87942339 :       i1 = square_number_row[basisnum] + 2;
     105             :     }
     106             : 
     107             :   // Flip odd degree of freedom values if necessary
     108             :   // to keep continuity on sides
     109    24088245 :   Real f = 1.;
     110             : 
     111   293257527 :   if ((i0%2) && (i0 > 2) && (i1 == 0))
     112    12074514 :     f =  elem->positive_edge_orientation(0)?-1.:1.;
     113   281183013 :   else if ((i0%2) && (i0>2) && (i1 == 1))
     114    12074514 :     f = !elem->positive_edge_orientation(2)?-1.:1.;
     115   269108499 :   else if ((i0 == 0) && (i1%2) && (i1>2))
     116    12074514 :     f = !elem->positive_edge_orientation(3)?-1.:1.;
     117   257033985 :   else if ((i0 == 1) && (i1%2) && (i1>2))
     118    12074514 :     f =  elem->positive_edge_orientation(1)?-1.:1.;
     119             : 
     120   317345772 :   return {i0, i1, f};
     121             : }
     122             : 
     123             : } // anonymous namespace
     124             : 
     125             : 
     126             : 
     127             : namespace libMesh
     128             : {
     129             : 
     130             : 
     131     6299475 : LIBMESH_DEFAULT_VECTORIZED_FE(2,HIERARCHIC)
     132    15451578 : LIBMESH_DEFAULT_VECTORIZED_FE(2,L2_HIERARCHIC)
     133    14645806 : LIBMESH_DEFAULT_VECTORIZED_FE(2,SIDE_HIERARCHIC)
     134             : 
     135             : 
     136             : template <>
     137           0 : Real FE<2,HIERARCHIC>::shape(const ElemType,
     138             :                              const Order,
     139             :                              const unsigned int,
     140             :                              const Point &)
     141             : {
     142           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     143             :   return 0.;
     144             : }
     145             : 
     146             : 
     147             : 
     148             : template <>
     149           0 : Real FE<2,L2_HIERARCHIC>::shape(const ElemType,
     150             :                                 const Order,
     151             :                                 const unsigned int,
     152             :                                 const Point &)
     153             : {
     154           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     155             :   return 0.;
     156             : }
     157             : 
     158             : 
     159             : 
     160             : template <>
     161           0 : Real FE<2,SIDE_HIERARCHIC>::shape(const ElemType,
     162             :                                   const Order,
     163             :                                   const unsigned int,
     164             :                                   const Point &)
     165             : {
     166           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     167             :   return 0.;
     168             : }
     169             : 
     170             : 
     171             : 
     172             : template <>
     173   211781835 : Real FE<2,HIERARCHIC>::shape(const Elem * elem,
     174             :                              const Order order,
     175             :                              const unsigned int i,
     176             :                              const Point & p,
     177             :                              const bool add_p_level)
     178             : {
     179   211781835 :   return fe_hierarchic_2D_shape<HIERARCHIC>(elem, order, i, p, add_p_level);
     180             : }
     181             : 
     182             : 
     183             : 
     184             : template <>
     185           0 : Real FE<2,HIERARCHIC>::shape(const FEType fet,
     186             :                              const Elem * elem,
     187             :                              const unsigned int i,
     188             :                              const Point & p,
     189             :                              const bool add_p_level)
     190             : {
     191           0 :   return fe_hierarchic_2D_shape<HIERARCHIC>(elem, fet.order, i, p, add_p_level);
     192             : }
     193             : 
     194             : 
     195             : template <>
     196  2047163678 : Real FE<2,L2_HIERARCHIC>::shape(const Elem * elem,
     197             :                                 const Order order,
     198             :                                 const unsigned int i,
     199             :                                 const Point & p,
     200             :                                 const bool add_p_level)
     201             : {
     202  2047163678 :   return fe_hierarchic_2D_shape<L2_HIERARCHIC>(elem, order, i, p, add_p_level);
     203             : }
     204             : 
     205             : 
     206             : template <>
     207           0 : Real FE<2,L2_HIERARCHIC>::shape(const FEType fet,
     208             :                                 const Elem * elem,
     209             :                                 const unsigned int i,
     210             :                                 const Point & p,
     211             :                                 const bool add_p_level)
     212             : {
     213           0 :   return fe_hierarchic_2D_shape<L2_HIERARCHIC>(elem, fet.order, i, p, add_p_level);
     214             : }
     215             : 
     216             : 
     217             : template <>
     218    42832020 : Real FE<2,SIDE_HIERARCHIC>::shape(const Elem * elem,
     219             :                                   const Order order,
     220             :                                   const unsigned int i,
     221             :                                   const Point & p,
     222             :                                   const bool add_p_level)
     223             : {
     224     3569614 :   libmesh_assert(elem);
     225    42832020 :   const ElemType type = elem->type();
     226             : 
     227    46401634 :   const Order totalorder = order + add_p_level*elem->p_level();
     228             : 
     229    42832020 :   const unsigned int dofs_per_side = totalorder+1u;
     230             : 
     231    39262406 :   switch (type)
     232             :     {
     233    41184108 :     case TRI6:
     234             :     case TRI7:
     235             :       {
     236     3432222 :         libmesh_assert_less(i, 3*dofs_per_side);
     237             : 
     238             :         // Flip odd degree of freedom values if necessary
     239             :         // to keep continuity on sides.  We'll flip xi/eta rather than
     240             :         // flipping phi, so that we can use this to handle the "nodal"
     241             :         // degrees of freedom too.
     242     3432222 :         Real f = 1.;
     243             : 
     244    41184108 :         const Real zeta1 = p(0);
     245    41184108 :         const Real zeta2 = p(1);
     246    41184108 :         const Real zeta0 = 1. - zeta1 - zeta2;
     247             : 
     248    41184108 :         if (zeta1 > zeta2 && zeta0 > zeta2) // side 0
     249             :           {
     250    13719948 :             if (i >= dofs_per_side)
     251      761988 :               return 0;
     252             : 
     253     4573316 :             if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     254        8240 :               return 1;
     255             : 
     256     8045560 :             if ((i < 2 || i % 2) &&
     257     3571194 :                 elem->positive_edge_orientation(0))
     258      130248 :               f = -1;
     259             : 
     260     4847120 :             return FE<1,HIERARCHIC>::shape(EDGE3, totalorder, i, f*(zeta1-zeta0));
     261             :           }
     262    27464160 :         else if (zeta1 > zeta0 && zeta2 > zeta0) // side 1
     263             :           {
     264    13741794 :             if (i < dofs_per_side ||
     265     9161196 :                 i >= 2*dofs_per_side)
     266      763940 :               return 0;
     267             : 
     268     4580598 :             if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     269        8250 :               return 1;
     270             : 
     271     4481538 :             const unsigned int side_i = i - dofs_per_side;
     272             : 
     273     8057546 :             if ((side_i < 2 || side_i % 2) &&
     274     3576008 :                 elem->positive_edge_orientation(1))
     275      162178 :               f = -1;
     276             : 
     277     4855258 :             return FE<1,HIERARCHIC>::shape(EDGE3, totalorder, side_i, f*(zeta2-zeta1));
     278             :           }
     279             :         else // side 2
     280             :           {
     281     1143330 :             libmesh_assert (zeta2 >= zeta1 && zeta0 >= zeta1); // On a corner???
     282             : 
     283    13722366 :             if (i < 2*dofs_per_side)
     284      762220 :               return 0;
     285             : 
     286     4574122 :             if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     287        8230 :               return 1;
     288             : 
     289     4475202 :             const unsigned int side_i = i - 2*dofs_per_side;
     290             : 
     291     8047102 :             if ((side_i < 2 || side_i % 2) &&
     292     3571900 :                 elem->positive_edge_orientation(2))
     293      162178 :               f = -1;
     294             : 
     295     4848082 :             return FE<1,HIERARCHIC>::shape(EDGE3, totalorder, side_i, f*(zeta0-zeta2));
     296             :           }
     297             :       }
     298     1647912 :     case QUAD8:
     299             :     case QUADSHELL8:
     300             :     case QUAD9:
     301             :     case QUADSHELL9:
     302             :       {
     303      137392 :         libmesh_assert_less(i, 4*dofs_per_side);
     304             : 
     305             :         // Flip odd degree of freedom values if necessary
     306             :         // to keep continuity on sides.  We'll flip xi/eta rather than
     307             :         // flipping phi, so that we can use this to handle the "nodal"
     308             :         // degrees of freedom too.
     309      137392 :         Real f = 1.;
     310             : 
     311     1647912 :         const Real xi = p(0), eta = p(1);
     312     1647912 :         if (eta < xi)
     313             :           {
     314      815232 :             if (eta < -xi) // side 0
     315             :               {
     316      401168 :                 if (i >= dofs_per_side)
     317       24444 :                   return 0;
     318             : 
     319      100292 :                 if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     320        4120 :                   return 1;
     321             : 
     322       88358 :                 if ((i < 2 || i % 2) &&
     323       36206 :                     elem->positive_edge_orientation(0))
     324        1480 :                   f = -1;
     325             : 
     326       56180 :                 return FE<1,HIERARCHIC>::shape(EDGE3, totalorder, i, f*xi);
     327             :               }
     328             :             else           // side 1
     329             :               {
     330      414064 :                 if (i < dofs_per_side ||
     331      310548 :                     i >= 2*dofs_per_side)
     332       26838 :                   return 0;
     333             : 
     334      103516 :                 if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     335        4130 :                   return 1;
     336             : 
     337       55336 :                 const unsigned int side_i = i - dofs_per_side;
     338             : 
     339       93866 :                 if ((side_i < 2 || side_i % 2) &&
     340       38530 :                     elem->positive_edge_orientation(1))
     341         740 :                   f = -1;
     342             : 
     343       60152 :                 return FE<1,HIERARCHIC>::shape(EDGE3, totalorder, side_i, f*eta);
     344             :               }
     345             :           }
     346             :         else // xi < eta
     347             :           {
     348      832680 :             if (eta > -xi)    // side 2
     349             :               {
     350      411344 :                 if (i < 2*dofs_per_side ||
     351      205672 :                     i >= 3*dofs_per_side)
     352       25188 :                   return 0;
     353             : 
     354      102836 :                 if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     355        4120 :                   return 1;
     356             : 
     357       54676 :                 const unsigned int side_i = i - 2*dofs_per_side;
     358             : 
     359       92802 :                 if ((side_i < 2 || side_i % 2) &&
     360       38126 :                     !elem->positive_edge_orientation(2))
     361        1110 :                   f = -1;
     362             : 
     363       58952 :                 return FE<1,HIERARCHIC>::shape(EDGE3, totalorder, side_i, f*xi);
     364             :               }
     365             :             else           // side 3
     366             :               {
     367      421336 :                 if (i < 3*dofs_per_side)
     368       26574 :                   return 0;
     369             : 
     370      105334 :                 if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     371        4130 :                   return 1;
     372             : 
     373       57124 :                 const unsigned int side_i = i - 3*dofs_per_side;
     374             : 
     375       96968 :                 if ((side_i < 2 || side_i % 2) &&
     376       39844 :                     !elem->positive_edge_orientation(3))
     377         740 :                   f = -1;
     378             : 
     379       61852 :                 return FE<1,HIERARCHIC>::shape(EDGE3, totalorder, side_i, f*eta);
     380             :               }
     381             :           }
     382             :       }
     383           0 :     default:
     384           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(elem->type()));
     385             :     }
     386             :   return 0;
     387             : }
     388             : 
     389             : 
     390             : template <>
     391           0 : Real FE<2,SIDE_HIERARCHIC>::shape(const FEType fet,
     392             :                                   const Elem * elem,
     393             :                                   const unsigned int i,
     394             :                                   const Point & p,
     395             :                                   const bool add_p_level)
     396             : {
     397           0 :   return FE<2,SIDE_HIERARCHIC>::shape(elem, fet.order, i, p, add_p_level);
     398             : }
     399             : 
     400             : 
     401             : template <>
     402           0 : Real FE<2,HIERARCHIC>::shape_deriv(const ElemType,
     403             :                                    const Order,
     404             :                                    const unsigned int,
     405             :                                    const unsigned int,
     406             :                                    const Point &)
     407             : {
     408           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     409             :   return 0.;
     410             : }
     411             : 
     412             : 
     413             : 
     414             : template <>
     415           0 : Real FE<2,L2_HIERARCHIC>::shape_deriv(const ElemType,
     416             :                                       const Order,
     417             :                                       const unsigned int,
     418             :                                       const unsigned int,
     419             :                                       const Point &)
     420             : {
     421           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     422             :   return 0.;
     423             : }
     424             : 
     425             : 
     426             : 
     427             : template <>
     428           0 : Real FE<2,SIDE_HIERARCHIC>::shape_deriv(const ElemType,
     429             :                                         const Order,
     430             :                                         const unsigned int,
     431             :                                         const unsigned int,
     432             :                                         const Point &)
     433             : {
     434           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     435             :   return 0.;
     436             : }
     437             : 
     438             : 
     439             : 
     440             : template <>
     441    42878854 : Real FE<2,HIERARCHIC>::shape_deriv(const Elem * elem,
     442             :                                    const Order order,
     443             :                                    const unsigned int i,
     444             :                                    const unsigned int j,
     445             :                                    const Point & p,
     446             :                                    const bool add_p_level)
     447             : {
     448    42878854 :   return fe_hierarchic_2D_shape_deriv<HIERARCHIC>(elem, order, i, j, p, add_p_level);
     449             : }
     450             : 
     451             : 
     452             : template <>
     453           0 : Real FE<2,HIERARCHIC>::shape_deriv(const FEType fet,
     454             :                                    const Elem * elem,
     455             :                                    const unsigned int i,
     456             :                                    const unsigned int j,
     457             :                                    const Point & p,
     458             :                                    const bool add_p_level)
     459             : {
     460           0 :   return fe_hierarchic_2D_shape_deriv<HIERARCHIC>(elem, fet.order, i, j, p, add_p_level);
     461             : }
     462             : 
     463             : 
     464             : 
     465             : 
     466             : template <>
     467   106336976 : Real FE<2,L2_HIERARCHIC>::shape_deriv(const Elem * elem,
     468             :                                       const Order order,
     469             :                                       const unsigned int i,
     470             :                                       const unsigned int j,
     471             :                                       const Point & p,
     472             :                                       const bool add_p_level)
     473             : {
     474   106336976 :   return fe_hierarchic_2D_shape_deriv<L2_HIERARCHIC>(elem, order, i, j, p, add_p_level);
     475             : }
     476             : 
     477             : 
     478             : template <>
     479           0 : Real FE<2,L2_HIERARCHIC>::shape_deriv(const FEType fet,
     480             :                                       const Elem * elem,
     481             :                                       const unsigned int i,
     482             :                                       const unsigned int j,
     483             :                                       const Point & p,
     484             :                                       const bool add_p_level)
     485             : {
     486           0 :   return fe_hierarchic_2D_shape_deriv<L2_HIERARCHIC>(elem, fet.order, i, j, p, add_p_level);
     487             : }
     488             : 
     489             : 
     490             : 
     491             : template <>
     492     4594560 : Real FE<2,SIDE_HIERARCHIC>::shape_deriv(const Elem * elem,
     493             :                                         const Order order,
     494             :                                         const unsigned int i,
     495             :                                         const unsigned int j,
     496             :                                         const Point & p,
     497             :                                         const bool add_p_level)
     498             : {
     499      382880 :   libmesh_assert(elem);
     500             : 
     501     4594560 :   const ElemType type = elem->type();
     502             : 
     503     4977440 :   const Order totalorder = order + add_p_level*elem->p_level();
     504             : 
     505     4594560 :   if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     506        2720 :     return 0;
     507             : 
     508     4561920 :   const unsigned int dofs_per_side = totalorder+1u;
     509             : 
     510     4181760 :   switch (type)
     511             :     {
     512     3732480 :     case TRI6:
     513             :     case TRI7:
     514             :       {
     515     3732480 :         return fe_fdm_deriv(elem, order, i, j, p, add_p_level, FE<2,SIDE_HIERARCHIC>::shape);
     516             :       }
     517             : #if 0
     518             :       {
     519             :         libmesh_assert_less(i, 3*dofs_per_side);
     520             :         libmesh_assert_less (j, 2);
     521             : 
     522             :         // Flip odd degree of freedom values if necessary
     523             :         // to keep continuity on sides.  We'll flip xi/eta rather than
     524             :         // flipping phi, so that we can use this to handle the "nodal"
     525             :         // degrees of freedom too.
     526             :         Real f = 1.;
     527             : 
     528             :         const Real zeta1 = p(0);
     529             :         const Real zeta2 = p(1);
     530             :         const Real zeta0 = 1. - zeta1 - zeta2;
     531             : 
     532             :         if (zeta1 > zeta2 && zeta0 > zeta2) // side 0
     533             :           {
     534             :             if (j == 1) // d/deta is perpendicular here
     535             :               return 0;
     536             : 
     537             :             if (i >= dofs_per_side)
     538             :               return 0;
     539             : 
     540             :             if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     541             :               return 0;
     542             : 
     543             :             if ((i < 2 || i % 2) &&
     544             :                 elem->positive_edge_orientation(0))
     545             :               f = -1;
     546             : 
     547             :             return f*FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, i, 0, f*(zeta1-zeta0));
     548             :           }
     549             :         else if (zeta1 > zeta0 && zeta2 > zeta0) // side 1
     550             :           {
     551             :             if (i < dofs_per_side ||
     552             :                 i >= 2*dofs_per_side)
     553             :               return 0;
     554             : 
     555             :             if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     556             :               return 0;
     557             : 
     558             :             const unsigned int side_i = i - dofs_per_side;
     559             : 
     560             :             if ((side_i < 2 || side_i % 2) &&
     561             :                 elem->positive_edge_orientation(1))
     562             :               f = -1;
     563             : 
     564             :             Real g = 1;
     565             :             if (j == 0) // 2D d/dxi is in the opposite direction on this edge
     566             :               g = -1;
     567             : 
     568             :             return f*g*FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, side_i, 0, f*(zeta2-zeta1));
     569             :           }
     570             :         else // side 2
     571             :           {
     572             :             libmesh_assert (zeta2 >= zeta1 && zeta0 >= zeta1); // On a corner???
     573             : 
     574             :             if (j == 0) // d/dxi is perpendicular here
     575             :               return 0;
     576             : 
     577             :             if (i < 2*dofs_per_side)
     578             :               return 0;
     579             : 
     580             :             if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     581             :               return 0;
     582             : 
     583             :             const unsigned int side_i = i - 2*dofs_per_side;
     584             : 
     585             :             if ((side_i < 2 || side_i % 2) &&
     586             :                 elem->positive_edge_orientation(2))
     587             :               f = -1;
     588             : 
     589             :             return -f*FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, side_i, 0, f*(zeta0-zeta2));
     590             :           }
     591             :       }
     592             : #endif
     593      829440 :     case QUAD8:
     594             :     case QUADSHELL8:
     595             :     case QUAD9:
     596             :     case QUADSHELL9:
     597             :       {
     598       69120 :         libmesh_assert_less(i, 4*dofs_per_side);
     599             : 
     600             :         // Flip odd degree of freedom values if necessary
     601             :         // to keep continuity on sides.  We'll flip xi/eta rather than
     602             :         // flipping phi, so that we can use this to handle the "nodal"
     603             :         // degrees of freedom too.
     604       69120 :         Real f = 1.;
     605             : 
     606      829440 :         const Real xi = p(0), eta = p(1);
     607      829440 :         if (eta < xi)
     608             :           {
     609      414720 :             if (eta < -xi) // side 0
     610             :               {
     611      207360 :                 if (i >= dofs_per_side)
     612       12960 :                   return 0;
     613       51840 :                 if (j != 0)
     614        2160 :                   return 0;
     615       43680 :                 if ((i < 2 || i % 2) &&
     616       17760 :                     elem->positive_edge_orientation(0))
     617         370 :                   f = -1;
     618             : 
     619       28080 :                 return f*FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, i, 0, f*xi);
     620             :               }
     621             :             else           // side 1
     622             :               {
     623      207360 :                 if (i < dofs_per_side ||
     624      155520 :                     i >= 2*dofs_per_side)
     625       12960 :                   return 0;
     626       51840 :                 if (j != 1)
     627        2160 :                   return 0;
     628             : 
     629       25920 :                 const unsigned int side_i = i - dofs_per_side;
     630             : 
     631       43680 :                 if ((side_i < 2 || side_i % 2) &&
     632       17760 :                     elem->positive_edge_orientation(1))
     633         370 :                   f = -1;
     634             : 
     635       28080 :                 return f*FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, side_i, 0, f*eta);
     636             :               }
     637             :           }
     638             :         else // xi < eta
     639             :           {
     640      414720 :             if (eta > -xi)    // side 2
     641             :               {
     642      207360 :                 if (i < 2*dofs_per_side ||
     643      103680 :                     i >= 3*dofs_per_side)
     644       12960 :                   return 0;
     645       51840 :                 if (j != 0)
     646        2160 :                   return 0;
     647             : 
     648       25920 :                 const unsigned int side_i = i - 2*dofs_per_side;
     649             : 
     650       43680 :                 if ((side_i < 2 || side_i % 2) &&
     651       17760 :                     !elem->positive_edge_orientation(2))
     652         370 :                   f = -1;
     653             : 
     654       28080 :                 return f*FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, side_i, 0, f*xi);
     655             :               }
     656             :             else           // side 3
     657             :               {
     658      207360 :                 if (i < 3*dofs_per_side)
     659       12960 :                   return 0;
     660       51840 :                 if (j != 1)
     661        2160 :                   return 0;
     662             : 
     663       25920 :                 const unsigned int side_i = i - 3*dofs_per_side;
     664             : 
     665       43680 :                 if ((side_i < 2 || side_i % 2) &&
     666       17760 :                     !elem->positive_edge_orientation(3))
     667         370 :                   f = -1;
     668             : 
     669       28080 :                 return f*FE<1,HIERARCHIC>::shape_deriv(EDGE3, totalorder, side_i, 0, f*eta);
     670             :               }
     671             :           }
     672             :       }
     673           0 :     default:
     674           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(elem->type()));
     675             :     }
     676             :   return 0;
     677             : }
     678             : 
     679             : 
     680             : template <>
     681           0 : Real FE<2,SIDE_HIERARCHIC>::shape_deriv(const FEType fet,
     682             :                                         const Elem * elem,
     683             :                                         const unsigned int i,
     684             :                                         const unsigned int j,
     685             :                                         const Point & p,
     686             :                                         const bool add_p_level)
     687             : {
     688           0 :   return FE<2,SIDE_HIERARCHIC>::shape_deriv(elem, fet.order, i, j, p, add_p_level);
     689             : }
     690             : 
     691             : 
     692             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     693             : 
     694             : template <>
     695           0 : Real FE<2,HIERARCHIC>::shape_second_deriv(const ElemType,
     696             :                                           const Order,
     697             :                                           const unsigned int,
     698             :                                           const unsigned int,
     699             :                                           const Point &)
     700             : {
     701           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     702             :   return 0.;
     703             : }
     704             : 
     705             : 
     706             : 
     707             : template <>
     708           0 : Real FE<2,L2_HIERARCHIC>::shape_second_deriv(const ElemType,
     709             :                                              const Order,
     710             :                                              const unsigned int,
     711             :                                              const unsigned int,
     712             :                                              const Point &)
     713             : {
     714           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     715             :   return 0.;
     716             : }
     717             : 
     718             : 
     719             : 
     720             : template <>
     721           0 : Real FE<2,SIDE_HIERARCHIC>::shape_second_deriv(const ElemType,
     722             :                                                const Order,
     723             :                                                const unsigned int,
     724             :                                                const unsigned int,
     725             :                                                const Point &)
     726             : {
     727           0 :   libmesh_error_msg("Hierarchic shape functions require an Elem for edge orientation.");
     728             :   return 0.;
     729             : }
     730             : 
     731             : 
     732             : 
     733             : template <>
     734     4466391 : Real FE<2,HIERARCHIC>::shape_second_deriv(const Elem * elem,
     735             :                                           const Order order,
     736             :                                           const unsigned int i,
     737             :                                           const unsigned int j,
     738             :                                           const Point & p,
     739             :                                           const bool add_p_level)
     740             : {
     741     8608608 :   return fe_hierarchic_2D_shape_second_deriv<HIERARCHIC>(elem, order, i, j, p, add_p_level);
     742             : }
     743             : 
     744             : 
     745             : template <>
     746           0 : Real FE<2,HIERARCHIC>::shape_second_deriv(const FEType fet,
     747             :                                           const Elem * elem,
     748             :                                           const unsigned int i,
     749             :                                           const unsigned int j,
     750             :                                           const Point & p,
     751             :                                           const bool add_p_level)
     752             : {
     753           0 :   return fe_hierarchic_2D_shape_second_deriv<HIERARCHIC>(elem, fet.order, i, j, p, add_p_level);
     754             : }
     755             : 
     756             : 
     757             : template <>
     758    34506282 : Real FE<2,L2_HIERARCHIC>::shape_second_deriv(const Elem * elem,
     759             :                                              const Order order,
     760             :                                              const unsigned int i,
     761             :                                              const unsigned int j,
     762             :                                              const Point & p,
     763             :                                              const bool add_p_level)
     764             : {
     765    66120906 :   return fe_hierarchic_2D_shape_second_deriv<L2_HIERARCHIC>(elem, order, i, j, p, add_p_level);
     766             : }
     767             : 
     768             : 
     769             : template <>
     770           0 : Real FE<2,L2_HIERARCHIC>::shape_second_deriv(const FEType fet,
     771             :                                              const Elem * elem,
     772             :                                              const unsigned int i,
     773             :                                              const unsigned int j,
     774             :                                              const Point & p,
     775             :                                              const bool add_p_level)
     776             : {
     777           0 :   return fe_hierarchic_2D_shape_second_deriv<L2_HIERARCHIC>(elem, fet.order, i, j, p, add_p_level);
     778             : }
     779             : 
     780             : 
     781             : template <>
     782     2692800 : Real FE<2,SIDE_HIERARCHIC>::shape_second_deriv(const Elem * elem,
     783             :                                                const Order order,
     784             :                                                const unsigned int i,
     785             :                                                const unsigned int j,
     786             :                                                const Point & p,
     787             :                                                const bool add_p_level)
     788             : {
     789      224400 :   libmesh_assert(elem);
     790     2692800 :   const ElemType type = elem->type();
     791             : 
     792     2917200 :   const Order totalorder = order + add_p_level*elem->p_level();
     793             : 
     794     2692800 :   if (totalorder == 0) // special case since raw HIERARCHIC lacks CONSTANTs
     795        4080 :     return 0;
     796             : 
     797     2643840 :   const unsigned int dofs_per_side = totalorder+1u;
     798             : 
     799     2423520 :   switch (type)
     800             :     {
     801     1399680 :     case TRI6:
     802             :     case TRI7:
     803             :       {
     804     1399680 :         return fe_fdm_second_deriv(elem, order, i, j, p, add_p_level,
     805     1399680 :                                    FE<2,SIDE_HIERARCHIC>::shape_deriv);
     806             :       }
     807     1244160 :     case QUAD8:
     808             :     case QUADSHELL8:
     809             :     case QUAD9:
     810             :     case QUADSHELL9:
     811             :       {
     812      103680 :         libmesh_assert_less(i, 4*dofs_per_side);
     813             : 
     814             :         // Flip odd degree of freedom values if necessary
     815             :         // to keep continuity on sides.  We'll flip xi/eta rather than
     816             :         // flipping phi, so that we can use this to handle the "nodal"
     817             :         // degrees of freedom too.
     818      103680 :         Real f = 1.;
     819             : 
     820     1244160 :         const Real xi = p(0), eta = p(1);
     821     1244160 :         if (eta < xi)
     822             :           {
     823      622080 :             if (eta < -xi) // side 0
     824             :               {
     825      311040 :                 if (i >= dofs_per_side)
     826       19440 :                   return 0;
     827       77760 :                 if (j != 0)
     828        4320 :                   return 0;
     829       43680 :                 if ((i < 2 || i % 2) &&
     830       17760 :                     elem->positive_edge_orientation(0))
     831         370 :                   f = -1;
     832             : 
     833       28080 :                 return FE<1,HIERARCHIC>::shape_second_deriv(EDGE3, totalorder, i, 0, f*xi);
     834             :               }
     835             :             else           // side 1
     836             :               {
     837      311040 :                 if (i < dofs_per_side ||
     838      233280 :                     i >= 2*dofs_per_side)
     839       19440 :                   return 0;
     840       77760 :                 if (j != 2)
     841        4320 :                   return 0;
     842             : 
     843       25920 :                 const unsigned int side_i = i - dofs_per_side;
     844             : 
     845       43680 :                 if ((side_i < 2 || side_i % 2) &&
     846       17760 :                     elem->positive_edge_orientation(1))
     847         370 :                   f = -1;
     848             : 
     849       28080 :                 return FE<1,HIERARCHIC>::shape_second_deriv(EDGE3, totalorder, side_i, 0, f*eta);
     850             :               }
     851             :           }
     852             :         else // xi < eta
     853             :           {
     854      622080 :             if (eta > -xi)    // side 2
     855             :               {
     856      311040 :                 if (i < 2*dofs_per_side ||
     857      155520 :                     i >= 3*dofs_per_side)
     858       19440 :                   return 0;
     859       77760 :                 if (j != 0)
     860        4320 :                   return 0;
     861             : 
     862       25920 :                 const unsigned int side_i = i - 2*dofs_per_side;
     863             : 
     864       43680 :                 if ((side_i < 2 || side_i % 2) &&
     865       17760 :                     !elem->positive_edge_orientation(2))
     866         370 :                   f = -1;
     867             : 
     868       28080 :                 return FE<1,HIERARCHIC>::shape_second_deriv(EDGE3, totalorder, side_i, 0, f*xi);
     869             :               }
     870             :             else           // side 3
     871             :               {
     872      311040 :                 if (i < 3*dofs_per_side)
     873       19440 :                   return 0;
     874       77760 :                 if (j != 2)
     875        4320 :                   return 0;
     876             : 
     877       25920 :                 const unsigned int side_i = i - 3*dofs_per_side;
     878             : 
     879       43680 :                 if ((side_i < 2 || side_i % 2) &&
     880       17760 :                     !elem->positive_edge_orientation(3))
     881         370 :                   f = -1;
     882             : 
     883       28080 :                 return FE<1,HIERARCHIC>::shape_second_deriv(EDGE3, totalorder, side_i, 0, f*eta);
     884             :               }
     885             :           }
     886             :       }
     887           0 :     default:
     888           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(elem->type()));
     889             :     }
     890             :   return 0;
     891             : }
     892             : 
     893             : 
     894             : template <>
     895           0 : Real FE<2,SIDE_HIERARCHIC>::shape_second_deriv(const FEType fet,
     896             :                                                const Elem * elem,
     897             :                                                const unsigned int i,
     898             :                                                const unsigned int j,
     899             :                                                const Point & p,
     900             :                                                const bool add_p_level)
     901             : {
     902           0 :   return FE<2,SIDE_HIERARCHIC>::shape_second_deriv(elem, fet.order, i, j, p, add_p_level);
     903             : }
     904             : 
     905             : #endif //  LIBMESH_ENABLE_SECOND_DERIVATIVES
     906             : 
     907             : } // namespace libMesh
     908             : 
     909             : 
     910             : 
     911             : namespace
     912             : {
     913             : using namespace libMesh;
     914             : 
     915  1088110698 : Real fe_triangle_helper (const Elem & elem,
     916             :                          const Real edgenumerator,
     917             :                          const Real crossval,
     918             :                          const unsigned int basisorder,
     919             :                          const Order totalorder,
     920             :                          const unsigned int noden)
     921             : {
     922             :   // Get factors to account for edge-flipping
     923    93504117 :   Real flip = 1;
     924  1088110698 :   if (basisorder%2 && (elem.point(noden) > elem.point((noden+1)%3)))
     925    13122225 :     flip = -1.;
     926             : 
     927             :   // Avoid NaN around vertices ... but we still have to match the true
     928             :   // function, even when we're *outside* the triangle (crossval==0 on
     929             :   // a line, not just at a point!), to handle imprecise queries and
     930             :   // FDM derivatives correctly!
     931  1088110698 :   if (crossval == 0.)
     932             :     {
     933       35982 :       unsigned int basisfactorial = 1.;
     934     1190704 :       for (unsigned int n=2; n <= basisorder; ++n)
     935      727972 :         basisfactorial *= n;
     936             : 
     937      462732 :       return std::pow(edgenumerator, basisorder) / basisfactorial;
     938             :     }
     939             :   // Experimentally, as c -> 0, n propto c, I'm still seeing good
     940             :   // behavior from the default implementation below:
     941             : 
     942  1087647966 :   const Real edgeval = edgenumerator / crossval;
     943    93468135 :   const Real crossfunc = std::pow(crossval, basisorder);
     944             : 
     945  1087647966 :   return flip * crossfunc *
     946  1087647966 :     FE<1,HIERARCHIC>::shape(EDGE3, totalorder,
     947  1087647966 :                             basisorder, edgeval);
     948             : }
     949             : 
     950             : template <FEFamily T>
     951  2258945513 : Real fe_hierarchic_2D_shape(const Elem * elem,
     952             :                             const Order order,
     953             :                             const unsigned int i,
     954             :                             const Point & p,
     955             :                             const bool add_p_level)
     956             : {
     957   193094111 :   libmesh_assert(elem);
     958             : 
     959  2452041971 :   const Order totalorder = order + add_p_level*elem->p_level();
     960   193094111 :   libmesh_assert_greater (totalorder, 0);
     961             : 
     962  2258945513 :   switch (elem->type())
     963             :     {
     964  1982945368 :     case TRI3:
     965             :     case TRISHELL3:
     966             :     case TRI6:
     967             :     case TRI7:
     968             :       {
     969  1982945368 :         const Real zeta1 = p(0);
     970  1982945368 :         const Real zeta2 = p(1);
     971  1982945368 :         const Real zeta0 = 1. - zeta1 - zeta2;
     972             : 
     973   170233916 :         libmesh_assert_less (i, (totalorder+1u)*(totalorder+2u)/2);
     974     9735327 :         libmesh_assert (T == L2_HIERARCHIC || elem->type() == TRI6 ||
     975             :                         elem->type() == TRI7 || totalorder < 2);
     976             : 
     977             :         // Vertex DoFs
     978  1982945368 :         if (i == 0)
     979    17972469 :           return zeta0;
     980  1773040271 :         else if (i == 1)
     981    17972469 :           return zeta1;
     982  1563135174 :         else if (i == 2)
     983    17972469 :           return zeta2;
     984             :         // Edge DoFs
     985  1353230077 :         else if (i < totalorder + 2u)
     986             :           {
     987   362703566 :             const unsigned int basisorder = i - 1;
     988             : 
     989   362703566 :             const Real crossval = zeta0 + zeta1;
     990   362703566 :             const Real edgenumerator = zeta1 - zeta0;
     991             : 
     992   362703566 :             return fe_triangle_helper(*elem, edgenumerator, crossval,
     993   362703566 :                                       basisorder, totalorder, 0);
     994             :           }
     995   990526511 :         else if (i < 2u*totalorder + 1)
     996             :           {
     997   362703566 :             const unsigned int basisorder = i - totalorder;
     998             : 
     999   362703566 :             const Real crossval = zeta2 + zeta1;
    1000   362703566 :             const Real edgenumerator = zeta2 - zeta1;
    1001             : 
    1002   362703566 :             return fe_triangle_helper(*elem, edgenumerator, crossval,
    1003   362703566 :                                       basisorder, totalorder, 1);
    1004             :           }
    1005   627822945 :         else if (i < 3u*totalorder)
    1006             :           {
    1007   362703566 :             const unsigned int basisorder = i - (2u*totalorder) + 1;
    1008             : 
    1009   362703566 :             const Real crossval = zeta0 + zeta2;
    1010   362703566 :             const Real edgenumerator = zeta0 - zeta2;
    1011             : 
    1012   362703566 :             return fe_triangle_helper(*elem, edgenumerator, crossval,
    1013   362703566 :                                       basisorder, totalorder, 2);
    1014             :           }
    1015             :         // Interior DoFs
    1016             :         else
    1017             :           {
    1018   265119379 :             const unsigned int basisnum = i - (3u*totalorder);
    1019   265119379 :             unsigned int exp0 = triangular_number_column[basisnum] + 1;
    1020   265119379 :             unsigned int exp1 = triangular_number_row[basisnum] + 1 -
    1021             :               triangular_number_column[basisnum];
    1022             : 
    1023    22812392 :             Real returnval = 1;
    1024   600204608 :             for (unsigned int n = 0; n != exp0; ++n)
    1025   335085229 :               returnval *= zeta0;
    1026   600204608 :             for (unsigned int n = 0; n != exp1; ++n)
    1027   335085229 :               returnval *= zeta1;
    1028   265119379 :             returnval *= zeta2;
    1029   265119379 :             return returnval;
    1030             :           }
    1031             :       }
    1032             : 
    1033             :       // Hierarchic shape functions on the quadrilateral.
    1034   268052965 :     case QUAD4:
    1035             :     case QUADSHELL4:
    1036    14913015 :       libmesh_assert (T == L2_HIERARCHIC || totalorder < 2);
    1037             :       libmesh_fallthrough();
    1038             :     case QUAD8:
    1039             :     case QUADSHELL8:
    1040             :     case QUAD9:
    1041             :     case QUADSHELL9:
    1042             :       {
    1043             :         // Compute quad shape functions as a tensor-product
    1044   276000145 :         auto [i0, i1, f] = quad_indices(elem, totalorder, i);
    1045             : 
    1046   298861127 :         return f*(FE<1,T>::shape(EDGE3, totalorder, i0, p(0))*
    1047   298861127 :                   FE<1,T>::shape(EDGE3, totalorder, i1, p(1)));
    1048             :       }
    1049             : 
    1050           0 :     default:
    1051           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(elem->type()));
    1052             :     }
    1053             : 
    1054             :   return 0.;
    1055             : }
    1056             : 
    1057             : 
    1058             : template <FEFamily T>
    1059   149215830 : Real fe_hierarchic_2D_shape_deriv(const Elem * elem,
    1060             :                                   const Order order,
    1061             :                                   const unsigned int i,
    1062             :                                   const unsigned int j,
    1063             :                                   const Point & p,
    1064             :                                   const bool add_p_level)
    1065             : {
    1066    12287378 :   libmesh_assert(elem);
    1067             : 
    1068   149215830 :   const ElemType type = elem->type();
    1069             : 
    1070   161503208 :   const Order totalorder = order + add_p_level*elem->p_level();
    1071             : 
    1072    12287378 :   libmesh_assert_greater (totalorder, 0);
    1073             : 
    1074   136928452 :   switch (type)
    1075             :     {
    1076             :       // 1st & 2nd-order Hierarchics.
    1077   131958448 :     case TRI3:
    1078             :     case TRISHELL3:
    1079             :     case TRI6:
    1080             :     case TRI7:
    1081             :       {
    1082   131958448 :         return fe_fdm_deriv(elem, order, i, j, p, add_p_level, FE<2,T>::shape);
    1083             :       }
    1084             : 
    1085    16087804 :     case QUAD4:
    1086             :     case QUADSHELL4:
    1087       58472 :       libmesh_assert (T == L2_HIERARCHIC || totalorder < 2);
    1088             :       libmesh_fallthrough();
    1089             :     case QUAD8:
    1090             :     case QUADSHELL8:
    1091             :     case QUAD9:
    1092             :     case QUADSHELL9:
    1093             :       {
    1094             :         // Compute quad shape functions as a tensor-product
    1095    17257382 :         auto [i0, i1, f] = quad_indices(elem, totalorder, i);
    1096             : 
    1097    17257382 :         switch (j)
    1098             :           {
    1099             :             // d()/dxi
    1100    10326014 :           case 0:
    1101    11063965 :             return f*(FE<1,T>::shape_deriv(EDGE3, totalorder, i0, 0, p(0))*
    1102    11063965 :                       FE<1,T>::shape      (EDGE3, totalorder, i1,    p(1)));
    1103             : 
    1104             :             // d()/deta
    1105     6931368 :           case 1:
    1106     7421467 :             return f*(FE<1,T>::shape      (EDGE3, totalorder, i0,    p(0))*
    1107     7421467 :                       FE<1,T>::shape_deriv(EDGE3, totalorder, i1, 0, p(1)));
    1108             : 
    1109           0 :           default:
    1110           0 :             libmesh_error_msg("Invalid derivative index j = " << j);
    1111             :           }
    1112             :       }
    1113             : 
    1114           0 :     default:
    1115           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
    1116             :     }
    1117             : 
    1118             :   return 0.;
    1119             : }
    1120             : 
    1121             : 
    1122             : 
    1123             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1124             : 
    1125             : template <FEFamily T>
    1126     3215832 : Real fe_hierarchic_2D_shape_second_deriv(const Elem * elem,
    1127             :                                          const Order order,
    1128             :                                          const unsigned int i,
    1129             :                                          const unsigned int j,
    1130             :                                          const Point & p,
    1131             :                                          const bool add_p_level)
    1132             : {
    1133    38972673 :   return fe_fdm_second_deriv(elem, order, i, j, p, add_p_level,
    1134     3215832 :                              FE<2,T>::shape_deriv);
    1135             : }
    1136             : 
    1137             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
    1138             : 
    1139             : } // anonymous namespace

Generated by: LCOV version 1.14