LCOV - code coverage report
Current view: top level - src/fe - fe_interface.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4476 (4beb67) with base a68cc6 Lines: 447 931 48.0 %
Date: 2026-06-03 20:22:46 Functions: 40 71 56.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : // Local includes
      21             : #include "libmesh/fe_interface.h"
      22             : 
      23             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
      24             : #include "libmesh/fe_interface_macros.h"
      25             : #include "libmesh/inf_fe.h"
      26             : #endif
      27             : 
      28             : #include "libmesh/elem.h"
      29             : #include "libmesh/fe.h"
      30             : #include "libmesh/fe_compute_data.h"
      31             : #include "libmesh/dof_map.h"
      32             : #include "libmesh/enum_fe_family.h"
      33             : #include "libmesh/enum_order.h"
      34             : #include "libmesh/enum_elem_type.h"
      35             : #include "libmesh/enum_to_string.h"
      36             : 
      37             : namespace libMesh
      38             : {
      39             : 
      40             : //------------------------------------------------------------
      41             : //FEInterface class members
      42           0 : FEInterface::FEInterface()
      43             : {
      44           0 :   libmesh_error_msg("ERROR: Do not define an object of this type.");
      45             : }
      46             : 
      47             : 
      48             : 
      49             : #ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS
      50             : 
      51             : bool
      52           0 : FEInterface::is_InfFE_elem(const ElemType)
      53             : {
      54           0 :   return false;
      55             : }
      56             : 
      57             : #else
      58             : 
      59             : bool
      60  1100462761 : FEInterface::is_InfFE_elem(const ElemType et)
      61             : {
      62             : 
      63  1100462761 :   switch (et)
      64             :     {
      65      184389 :     case INFEDGE2:
      66             :     case INFQUAD4:
      67             :     case INFQUAD6:
      68             :     case INFHEX8:
      69             :     case INFHEX16:
      70             :     case INFHEX18:
      71             :     case INFPRISM6:
      72             :     case INFPRISM12:
      73      184389 :       return true;
      74             : 
      75  1099955668 :     default:
      76  1099955668 :       return false;
      77             :     }
      78             : }
      79             : 
      80             : #endif //ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS
      81             : 
      82             : #define fe_family_case_func(family, dim, func_and_args, prefix, suffix) \
      83             :   case family:                                                          \
      84             :     prefix FE<dim,family>::func_and_args suffix                         \
      85             : 
      86             : #define fe_family_case(family) \
      87             :   case family:
      88             : 
      89             : #define fe_family_scalar_case_func(dim, func_and_args, prefix, suffix)     \
      90             :   fe_family_case_func(CLOUGH, dim, func_and_args, prefix, suffix)          \
      91             :   fe_family_case_func(HERMITE, dim, func_and_args, prefix, suffix)         \
      92             :   fe_family_case_func(HIERARCHIC, dim, func_and_args, prefix, suffix)      \
      93             :   fe_family_case_func(L2_HIERARCHIC, dim, func_and_args, prefix, suffix)   \
      94             :   fe_family_case_func(SIDE_HIERARCHIC, dim, func_and_args, prefix, suffix) \
      95             :   fe_family_case_func(LAGRANGE, dim, func_and_args, prefix, suffix)        \
      96             :   fe_family_case_func(L2_LAGRANGE, dim, func_and_args, prefix, suffix)     \
      97             :   fe_family_case_func(MONOMIAL, dim, func_and_args, prefix, suffix)        \
      98             :   fe_family_case_func(SCALAR, dim, func_and_args, prefix, suffix)          \
      99             :   fe_family_case_func(XYZ, dim, func_and_args, prefix, suffix)             \
     100             :   fe_family_case_func(SUBDIVISION, 2, func_and_args,                       \
     101             :                       libmesh_assert_equal_to (dim, 2); prefix, suffix)
     102             : 
     103             : #define fe_family_scalar_case()   \
     104             :   fe_family_case(CLOUGH)          \
     105             :   fe_family_case(HERMITE)         \
     106             :   fe_family_case(HIERARCHIC)      \
     107             :   fe_family_case(L2_HIERARCHIC)   \
     108             :   fe_family_case(SIDE_HIERARCHIC) \
     109             :   fe_family_case(LAGRANGE)        \
     110             :   fe_family_case(L2_LAGRANGE)     \
     111             :   fe_family_case(MONOMIAL)        \
     112             :   fe_family_case(SCALAR)          \
     113             :   fe_family_case(XYZ)             \
     114             :   fe_family_case(SUBDIVISION)     \
     115             : 
     116             : #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
     117             : 
     118             : #define fe_family_horder_case_func(dim, func_and_args, prefix, suffix)        \
     119             :   fe_family_case_func(BERNSTEIN, dim, func_and_args, prefix, suffix)          \
     120             :   fe_family_case_func(SZABAB, dim, func_and_args, prefix, suffix)             \
     121             :   fe_family_case_func(RATIONAL_BERNSTEIN, dim, func_and_args, prefix, suffix) \
     122             : 
     123             : #define fe_family_horder_case()      \
     124             :   fe_family_case(BERNSTEIN)          \
     125             :   fe_family_case(SZABAB)             \
     126             :   fe_family_case(RATIONAL_BERNSTEIN) \
     127             : 
     128             : #else
     129             : 
     130             : #define fe_family_horder_case_func(dim, func_and_args, prefix, suffix)
     131             : #define fe_family_horder_case()
     132             : 
     133             : #endif
     134             : 
     135             : #define fe_family_vector_case_func(dim, func_and_args, prefix, suffix)       \
     136             :   fe_family_case_func(HIERARCHIC_VEC, dim, func_and_args, prefix, suffix)    \
     137             :   fe_family_case_func(L2_HIERARCHIC_VEC, dim, func_and_args, prefix, suffix) \
     138             :   fe_family_case_func(LAGRANGE_VEC, dim, func_and_args, prefix, suffix)      \
     139             :   fe_family_case_func(L2_LAGRANGE_VEC, dim, func_and_args, prefix, suffix)   \
     140             :   fe_family_case_func(MONOMIAL_VEC, dim, func_and_args, prefix, suffix)      \
     141             :   fe_family_case_func(NEDELEC_ONE, dim, func_and_args, prefix, suffix)       \
     142             :   fe_family_case_func(RAVIART_THOMAS, dim, func_and_args, prefix, suffix)    \
     143             :   fe_family_case_func(L2_RAVIART_THOMAS, dim, func_and_args, prefix, suffix) \
     144             : 
     145             : #define fe_family_vector_case()     \
     146             :   fe_family_case(HIERARCHIC_VEC)    \
     147             :   fe_family_case(L2_HIERARCHIC_VEC) \
     148             :   fe_family_case(LAGRANGE_VEC)      \
     149             :   fe_family_case(L2_LAGRANGE_VEC)   \
     150             :   fe_family_case(MONOMIAL_VEC)      \
     151             :   fe_family_case(NEDELEC_ONE)       \
     152             :   fe_family_case(RAVIART_THOMAS)    \
     153             :   fe_family_case(L2_RAVIART_THOMAS) \
     154             : 
     155             : #define fe_family_switch(dim, func_and_args, prefix, suffix)            \
     156             :   do {                                                                  \
     157             :     switch (fe_t.family)                                                \
     158             :       {                                                                 \
     159             :       fe_family_scalar_case_func(dim, func_and_args, prefix, suffix)    \
     160             :       fe_family_horder_case_func(dim, func_and_args, prefix, suffix)    \
     161             :       default:                                                          \
     162             :         libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
     163             :       }                                                                 \
     164             :   } while (0)
     165             : 
     166             : #define fe_family_with_vec_switch(dim, func_and_args, prefix, suffix)   \
     167             :   do {                                                                  \
     168             :     switch (fe_t.family)                                                \
     169             :       {                                                                 \
     170             :       fe_family_scalar_case_func(dim, func_and_args, prefix, suffix)    \
     171             :       fe_family_horder_case_func(dim, func_and_args, prefix, suffix)    \
     172             :       fe_family_vector_case_func(dim, func_and_args, prefix, suffix)    \
     173             :       default:                                                          \
     174             :         libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
     175             :       }                                                                 \
     176             :   } while (0)
     177             : 
     178             : #define fe_scalar_vec_error_switch(dim, func_and_args, prefix, suffix)  \
     179             :   do {                                                                  \
     180             :     switch (fe_t.family)                                                \
     181             :       {                                                                 \
     182             :       fe_family_scalar_case_func(dim, func_and_args, prefix, suffix)    \
     183             :       fe_family_horder_case_func(dim, func_and_args, prefix, suffix)    \
     184             :       fe_family_vector_case()                                           \
     185             :         libmesh_error_msg("Error: Can only request scalar valued elements for Real FEInterface::func_and_args"); \
     186             :       default:                                                          \
     187             :         libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
     188             :       }                                                                 \
     189             :   } while (0)
     190             : 
     191             : 
     192             : #define fe_vector_scalar_error_switch(dim, func_and_args, prefix, suffix) \
     193             :   do {                                                                    \
     194             :     switch (fe_t.family)                                                  \
     195             :       {                                                                   \
     196             :       fe_family_vector_case_func(dim, func_and_args, prefix, suffix)      \
     197             :       fe_family_scalar_case()                                             \
     198             :       fe_family_horder_case()                                             \
     199             :         libmesh_error_msg("Error: Can only request vector valued elements for RealGradient FEInterface::func_and_args"); \
     200             :       default:                                                            \
     201             :         libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
     202             :       }                                                                   \
     203             :   } while (0)
     204             : 
     205             : 
     206             : #define fe_switch(func_and_args)                        \
     207             :   do {                                                  \
     208             :     switch (dim)                                        \
     209             :       {                                                 \
     210             :         /* 0D */                                        \
     211             :       case 0:                                           \
     212             :         fe_family_switch (0, func_and_args, return, ;); \
     213             :         /* 1D */                                        \
     214             :       case 1:                                           \
     215             :         fe_family_switch (1, func_and_args, return, ;); \
     216             :         /* 2D */                                        \
     217             :       case 2:                                           \
     218             :         fe_family_switch (2, func_and_args, return, ;); \
     219             :         /* 3D */                                        \
     220             :       case 3:                                           \
     221             :         fe_family_switch (3, func_and_args, return, ;); \
     222             :       default:                                          \
     223             :         libmesh_error_msg("Invalid dim = " << dim);     \
     224             :       }                                                 \
     225             :   } while (0)
     226             : 
     227             : #define fe_with_vec_switch(func_and_args)                               \
     228             :   do {                                                                  \
     229             :     switch (dim)                                                        \
     230             :       {                                                                 \
     231             :         /* 0D */                                                        \
     232             :       case 0:                                                           \
     233             :         fe_family_with_vec_switch (0, func_and_args, return, ;);        \
     234             :         /* 1D */                                                        \
     235             :       case 1:                                                           \
     236             :         fe_family_with_vec_switch (1, func_and_args, return, ;);        \
     237             :         /* 2D */                                                        \
     238             :       case 2:                                                           \
     239             :         fe_family_with_vec_switch (2, func_and_args, return, ;);        \
     240             :         /* 3D */                                                        \
     241             :       case 3:                                                           \
     242             :         fe_family_with_vec_switch (3, func_and_args, return, ;);        \
     243             :       default:                                                          \
     244             :         libmesh_error_msg("Invalid dim = " << dim);                     \
     245             :       }                                                                 \
     246             :   } while (0)
     247             : 
     248             : #define void_fe_with_vec_switch(func_and_args)                          \
     249             :   do {                                                                  \
     250             :     switch (dim)                                                        \
     251             :       {                                                                 \
     252             :         /* 0D */                                                        \
     253             :       case 0:                                                           \
     254             :         fe_family_with_vec_switch (0, func_and_args, , ; return;);      \
     255             :         /* 1D */                                                        \
     256             :       case 1:                                                           \
     257             :         fe_family_with_vec_switch (1, func_and_args, , ; return;);      \
     258             :         /* 2D */                                                        \
     259             :       case 2:                                                           \
     260             :         fe_family_with_vec_switch (2, func_and_args, , ; return;);      \
     261             :         /* 3D */                                                        \
     262             :       case 3:                                                           \
     263             :         fe_family_with_vec_switch (3, func_and_args, , ; return;);      \
     264             :       default:                                                          \
     265             :         libmesh_error_msg("Invalid dim = " << dim);                     \
     266             :       }                                                                 \
     267             :   } while (0)
     268             : 
     269             : 
     270             : 
     271             : #ifdef LIBMESH_ENABLE_DEPRECATED
     272           0 : unsigned int FEInterface::n_shape_functions(const unsigned int dim,
     273             :                                             const FEType & fe_t,
     274             :                                             const ElemType t)
     275             : {
     276             :   libmesh_deprecated();
     277             : 
     278             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     279             : 
     280             :   // We no longer support calling this function with an infinite
     281             :   // ElemType, you must call the FeInterface::n_shape_functions()
     282             :   // taking an Elem* instead.
     283           0 :   if (is_InfFE_elem(t))
     284           0 :     libmesh_not_implemented();
     285             : 
     286             : #endif
     287             : 
     288           0 :   const Order o = fe_t.order;
     289             : 
     290           0 :   fe_with_vec_switch(n_shape_functions(t, o));
     291             : }
     292             : #endif // LIBMESH_ENABLE_DEPRECATED
     293             : 
     294             : 
     295             : 
     296             : unsigned int
     297     5737705 : FEInterface::n_shape_functions(const FEType & fe_t,
     298             :                                const Elem * elem,
     299             :                                const bool add_p_level)
     300             : {
     301             :   // dim is required by the fe_with_vec_switch macro
     302     5737705 :   auto dim = elem->dim();
     303             : 
     304             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     305             :   /*
     306             :    * Since the FEType, stored in DofMap/(some System child), has to
     307             :    * be the _same_ for InfFE and FE, we have to catch calls
     308             :    * to infinite elements through the element type.
     309             :    */
     310             : 
     311     1189203 :   if (is_InfFE_elem(elem->type()))
     312           0 :     return ifem_n_shape_functions(fe_t, elem);
     313             : 
     314             : #endif
     315             : 
     316             :   // Account for Elem::p_level() when computing total_order
     317     6275818 :   auto total_order = fe_t.order + add_p_level*elem->p_level();
     318             : 
     319     5737705 :   fe_with_vec_switch(n_dofs(elem, total_order));
     320             : }
     321             : 
     322             : 
     323             : 
     324             : unsigned int
     325  1620109341 : FEInterface::n_shape_functions(const FEType & fe_t,
     326             :                                const int extra_order,
     327             :                                const Elem * elem)
     328             : {
     329             :   // dim is required by the fe_with_vec_switch macro
     330  1620109341 :   auto dim = elem->dim();
     331             : 
     332             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     333             :   /*
     334             :    * Since the FEType, stored in DofMap/(some System child), has to
     335             :    * be the _same_ for InfFE and FE, we have to catch calls
     336             :    * to infinite elements through the element type.
     337             :    */
     338             : 
     339   296951402 :   if (is_InfFE_elem(elem->type()))
     340           0 :     return ifem_n_shape_functions(fe_t, elem);
     341             : 
     342             : #endif
     343             : 
     344             :   // Ignore Elem::p_level() and instead use extra_order to compute total_order.
     345   220932389 :   auto total_order = fe_t.order + extra_order;
     346             : 
     347  1620109341 :   fe_with_vec_switch(n_dofs(elem, total_order));
     348             : }
     349             : 
     350             : 
     351             : 
     352             : #ifdef LIBMESH_ENABLE_DEPRECATED
     353           0 : unsigned int FEInterface::n_dofs(const unsigned int dim,
     354             :                                  const FEType & fe_t,
     355             :                                  const ElemType t)
     356             : {
     357             :   libmesh_deprecated();
     358             : 
     359             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     360             : 
     361             :   // We no longer support calling this function with an infinite
     362             :   // ElemType, you must call the FeInterface::n_dofs() taking an Elem*
     363             :   // instead.
     364           0 :   if (is_InfFE_elem(t))
     365           0 :     libmesh_not_implemented();
     366             : 
     367             : #endif
     368             : 
     369           0 :   const Order o = fe_t.order;
     370             : 
     371           0 :   fe_with_vec_switch(n_dofs(t, o));
     372             : }
     373             : 
     374             : 
     375             : 
     376             : 
     377             : unsigned int
     378           0 : FEInterface::n_dofs (const unsigned int dim,
     379             :                      const FEType & fe_t,
     380             :                      const Elem * elem)
     381             : {
     382             :   libmesh_deprecated();
     383             : 
     384           0 :   fe_with_vec_switch(n_dofs(elem, fe_t.order + elem->p_level()));
     385             : }
     386             : #endif // LIBMESH_ENABLE_DEPRECATED
     387             : 
     388             : 
     389             : 
     390             : unsigned int
     391     9093312 : FEInterface::n_dofs(const FEType & fe_t,
     392             :                     const Elem * elem,
     393             :                     const bool add_p_level)
     394             : {
     395             :   // dim is required by the fe_with_vec_switch macro
     396     9093312 :   auto dim = elem->dim();
     397             : 
     398             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     399             : 
     400             :   // InfElems currently don't support p_level()
     401     1588796 :   if (is_InfFE_elem(elem->type()))
     402      223092 :     return ifem_n_dofs(fe_t, elem);
     403             : 
     404             : #endif
     405             : 
     406             :   // Account for Elem::p_level() when computing total_order
     407     8870220 :   fe_with_vec_switch(n_dofs(elem, fe_t.order + add_p_level*elem->p_level()));
     408             : }
     409             : 
     410             : 
     411             : 
     412             : unsigned int
     413    24657887 : FEInterface::n_dofs(const FEType & fe_t,
     414             :                     int extra_order,
     415             :                     const Elem * elem)
     416             : {
     417             :   // dim is required by the fe_with_vec_switch macro
     418    24657887 :   auto dim = elem->dim();
     419             : 
     420             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     421             : 
     422             :   // InfElems currently don't support p_level()
     423    24657199 :   if (is_InfFE_elem(elem->type()))
     424        4257 :     return ifem_n_dofs(fe_t, elem);
     425             : 
     426             : #endif
     427             : 
     428             :   // Elem::p_level() is ignored, extra_order is used instead.
     429    24652865 :   auto total_order = fe_t.order + extra_order;
     430             : 
     431    24653630 :   fe_with_vec_switch(n_dofs(elem, total_order));
     432             : }
     433             : 
     434             : 
     435             : 
     436             : #ifdef LIBMESH_ENABLE_DEPRECATED
     437           0 : unsigned int FEInterface::n_dofs_at_node(const unsigned int dim,
     438             :                                          const FEType & fe_t,
     439             :                                          const ElemType t,
     440             :                                          const unsigned int n)
     441             : {
     442             :   libmesh_deprecated();
     443             : 
     444             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     445             : 
     446           0 :   if (is_InfFE_elem(t))
     447           0 :     return ifem_n_dofs_at_node(dim, fe_t, t, n);
     448             : 
     449             : #endif
     450             : 
     451           0 :   const Order o = fe_t.order;
     452             : 
     453           0 :   fe_with_vec_switch(n_dofs_at_node(t, o, n));
     454             : }
     455             : 
     456             : 
     457             : 
     458             : FEInterface::n_dofs_at_node_ptr
     459           0 : FEInterface::n_dofs_at_node_function(const unsigned int dim,
     460             :                                      const FEType & fe_t)
     461             : {
     462             :   libmesh_deprecated();
     463             : 
     464           0 :   fe_with_vec_switch(n_dofs_at_node);
     465             : }
     466             : #endif // LIBMESH_ENABLE_DEPRECATED
     467             : 
     468             : 
     469             : 
     470             : FEInterface::n_dofs_at_node_ptr
     471   308269153 : FEInterface::n_dofs_at_node_function(const FEType & fe_t,
     472             :                                      const Elem * elem)
     473             : {
     474             :   // dim is required by the fe_with_vec_switch macro
     475   308269153 :   auto dim = elem->dim();
     476             : 
     477   308269153 :   fe_with_vec_switch(n_dofs_at_node);
     478             : }
     479             : 
     480             : 
     481             : 
     482             : unsigned int
     483   187023041 : FEInterface::n_dofs_at_node(const FEType & fe_t,
     484             :                             const Elem * elem,
     485             :                             const unsigned int n,
     486             :                             const bool add_p_level)
     487             : {
     488             :   // dim is required by the fe_with_vec_switch macro
     489   187023041 :   auto dim = elem->dim();
     490             : 
     491             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     492             : 
     493    30001805 :   if (is_InfFE_elem(elem->type()))
     494       99078 :     return ifem_n_dofs_at_node(fe_t, elem, n);
     495             : 
     496             : #endif
     497             : 
     498             :   // Account for Elem::p_level() when computing total_order
     499   199041256 :   auto total_order = fe_t.order + add_p_level*elem->p_level();
     500             : 
     501   186923963 :   fe_with_vec_switch(n_dofs_at_node(*elem, total_order, n));
     502             : }
     503             : 
     504             : 
     505             : 
     506             : unsigned int
     507      159644 : FEInterface::n_dofs_at_node(const FEType & fe_t,
     508             :                             const int extra_order,
     509             :                             const Elem * elem,
     510             :                             const unsigned int n)
     511             : {
     512             :   // dim is required by the fe_with_vec_switch macro
     513      159644 :   auto dim = elem->dim();
     514             : 
     515             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     516             : 
     517      158348 :   if (is_InfFE_elem(elem->type()))
     518      157916 :     return ifem_n_dofs_at_node(fe_t, elem, n);
     519             : 
     520             : #endif
     521             : 
     522             :   // Ignore Elem::p_level() and instead use extra_order to compute total_order.
     523         288 :   auto total_order = fe_t.order + extra_order;
     524             : 
     525        1728 :   fe_with_vec_switch(n_dofs_at_node(*elem, total_order, n));
     526             : }
     527             : 
     528             : 
     529             : 
     530             : #ifdef LIBMESH_ENABLE_DEPRECATED
     531           0 : unsigned int FEInterface::n_dofs_per_elem(const unsigned int dim,
     532             :                                           const FEType & fe_t,
     533             :                                           const ElemType t)
     534             : {
     535             :   libmesh_deprecated();
     536             : 
     537             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     538             : 
     539           0 :   if (is_InfFE_elem(t))
     540           0 :     return ifem_n_dofs_per_elem(dim, fe_t, t);
     541             : 
     542             : #endif
     543             : 
     544           0 :   const Order o = fe_t.order;
     545             : 
     546           0 :   fe_with_vec_switch(n_dofs_per_elem(t, o));
     547             : }
     548             : #endif // LIBMESH_ENABLE_DEPRECATED
     549             : 
     550             : 
     551             : 
     552             : unsigned int
     553    23573502 : FEInterface::n_dofs_per_elem(const FEType & fe_t,
     554             :                              const Elem * elem,
     555             :                              const bool add_p_level)
     556             : {
     557             :   // dim is required by the fe_with_vec_switch macro
     558    23573502 :   auto dim = elem->dim();
     559             : 
     560             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     561             : 
     562     4560889 :   if (is_InfFE_elem(elem->type()))
     563        7932 :     return ifem_n_dofs_per_elem(fe_t, elem);
     564             : 
     565             : #endif
     566             : 
     567             :   // Account for Elem::p_level() when computing total_order
     568    25306227 :   auto total_order = fe_t.order + add_p_level*elem->p_level();
     569             : 
     570    23565570 :   fe_with_vec_switch(n_dofs_per_elem(*elem, total_order));
     571             : }
     572             : 
     573             : 
     574             : 
     575             : unsigned int
     576   308269153 : FEInterface::n_dofs_per_elem(const FEType & fe_t,
     577             :                              const int extra_order,
     578             :                              const Elem * elem)
     579             : {
     580             :   // dim is required by the fe_with_vec_switch macro
     581   308269153 :   auto dim = elem->dim();
     582             : 
     583             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     584             : 
     585    57814130 :   if (is_InfFE_elem(elem->type()))
     586       14818 :     return ifem_n_dofs_per_elem(fe_t, elem);
     587             : 
     588             : #endif
     589             : 
     590             :   // Ignore Elem::p_level() and instead use extra_order to compute total_order.
     591    49938084 :   auto total_order = fe_t.order + extra_order;
     592             : 
     593   308254335 :   fe_with_vec_switch(n_dofs_per_elem(*elem, total_order));
     594             : }
     595             : 
     596             : 
     597             : 
     598      910339 : void FEInterface::dofs_on_side(const Elem * const elem,
     599             :                                const unsigned int dim,
     600             :                                const FEType & fe_t,
     601             :                                unsigned int s,
     602             :                                std::vector<unsigned int> & di,
     603             :                                const bool add_p_level)
     604             : {
     605      153998 :   const Order o = fe_t.order;
     606             : 
     607      910339 :   void_fe_with_vec_switch(dofs_on_side(elem, o, s, di, add_p_level));
     608             : }
     609             : 
     610             : 
     611             : 
     612      119562 : void FEInterface::dofs_on_edge(const Elem * const elem,
     613             :                                const unsigned int dim,
     614             :                                const FEType & fe_t,
     615             :                                unsigned int e,
     616             :                                std::vector<unsigned int> & di,
     617             :                                const bool add_p_level)
     618             : {
     619       17418 :   const Order o = fe_t.order;
     620             : 
     621      119562 :   void_fe_with_vec_switch(dofs_on_edge(elem, o, e, di, add_p_level));
     622             : }
     623             : 
     624             : 
     625             : 
     626    15868637 : void FEInterface::nodal_soln(const unsigned int dim,
     627             :                              const FEType & fe_t,
     628             :                              const Elem * elem,
     629             :                              const std::vector<Number> & elem_soln,
     630             :                              std::vector<Number> &       nodal_soln,
     631             :                              const bool add_p_level,
     632             :                              const unsigned int vdim)
     633             : {
     634             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     635             : 
     636     3466089 :   if (is_InfFE_elem(elem->type()))
     637             :     {
     638           0 :       ifem_nodal_soln(dim, fe_t, elem, elem_soln, nodal_soln);
     639           0 :       return;
     640             :     }
     641             : 
     642             : #endif
     643             : 
     644     2881336 :   const Order order = fe_t.order;
     645             : 
     646    15868637 :   void_fe_with_vec_switch(nodal_soln(elem, order, elem_soln, nodal_soln, add_p_level, vdim));
     647             : }
     648             : 
     649             : 
     650             : 
     651       10512 : void FEInterface::side_nodal_soln(const FEType & fe_t,
     652             :                                   const Elem * elem,
     653             :                                   const unsigned int side,
     654             :                                   const std::vector<Number> & elem_soln,
     655             :                                   std::vector<Number> &       nodal_soln,
     656             :                                   const bool add_p_level,
     657             :                                   const unsigned int vdim)
     658             : {
     659             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     660             : 
     661        2628 :   if (is_InfFE_elem(elem->type()))
     662             :     {
     663           0 :       libmesh_not_implemented();
     664             :       return;
     665             :     }
     666             : 
     667             : #endif
     668             : 
     669        1752 :   const Order order = fe_t.order;
     670       10512 :   const unsigned int dim = elem->dim();
     671             : 
     672       10512 :   void_fe_with_vec_switch(side_nodal_soln(elem, order, side, elem_soln, nodal_soln, add_p_level, vdim));
     673             : }
     674             : 
     675             : 
     676             : 
     677             : #ifdef LIBMESH_ENABLE_DEPRECATED
     678           0 : Point FEInterface::map(unsigned int dim,
     679             :                        const FEType & fe_t,
     680             :                        const Elem * elem,
     681             :                        const Point & p)
     682             : {
     683             :   libmesh_deprecated();
     684             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     685           0 :   if (is_InfFE_elem(elem->type()))
     686           0 :     return ifem_map(dim, fe_t, elem, p);
     687             : #endif
     688           0 :   fe_with_vec_switch(map(elem, p));
     689             : }
     690             : 
     691             : 
     692             : 
     693           0 : Point FEInterface::inverse_map (const unsigned int dim,
     694             :                                 const FEType & fe_t,
     695             :                                 const Elem * elem,
     696             :                                 const Point & p,
     697             :                                 const Real tolerance,
     698             :                                 const bool secure)
     699             : {
     700             :   libmesh_deprecated();
     701             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     702             : 
     703           0 :   if (is_InfFE_elem(elem->type()))
     704           0 :     return ifem_inverse_map(dim, fe_t, elem, p,tolerance, secure);
     705             : 
     706             : #endif
     707             : 
     708           0 :   fe_with_vec_switch(inverse_map(elem, p, tolerance, secure));
     709             : }
     710             : 
     711             : 
     712             : 
     713           0 : void FEInterface::inverse_map (const unsigned int dim,
     714             :                                const FEType & fe_t,
     715             :                                const Elem * elem,
     716             :                                const std::vector<Point> & physical_points,
     717             :                                std::vector<Point> &       reference_points,
     718             :                                const Real tolerance,
     719             :                                const bool secure)
     720             : {
     721             :   libmesh_deprecated();
     722             : 
     723           0 :   const std::size_t n_pts = physical_points.size();
     724             : 
     725             :   // Resize the vector
     726           0 :   reference_points.resize(n_pts);
     727             : 
     728           0 :   if (n_pts == 0)
     729             :     {
     730           0 :       libMesh::err << "WARNING: empty vector physical_points!"
     731           0 :                    << std::endl;
     732           0 :       libmesh_here();
     733           0 :       return;
     734             :     }
     735             : 
     736             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     737             : 
     738           0 :   if (is_InfFE_elem(elem->type()))
     739             :     {
     740           0 :       ifem_inverse_map(dim, fe_t, elem, physical_points, reference_points, tolerance, secure);
     741           0 :       return;
     742             :       // libmesh_not_implemented();
     743             :     }
     744             : 
     745             : #endif
     746             : 
     747           0 :   void_fe_with_vec_switch(inverse_map(elem, physical_points, reference_points, tolerance, secure));
     748             : }
     749             : 
     750             : 
     751             : 
     752           0 : bool FEInterface::on_reference_element(const Point & p,
     753             :                                        const ElemType t,
     754             :                                        const Real eps)
     755             : {
     756           0 :   return FEBase::on_reference_element(p,t,eps);
     757             : }
     758             : 
     759             : 
     760             : 
     761           0 : Real FEInterface::shape(const unsigned int dim,
     762             :                         const FEType & fe_t,
     763             :                         const ElemType t,
     764             :                         const unsigned int i,
     765             :                         const Point & p)
     766             : {
     767             :   libmesh_deprecated();
     768             : 
     769             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     770             : 
     771           0 :   if (is_InfFE_elem(t))
     772           0 :     return ifem_shape(dim, fe_t, t, i, p);
     773             : 
     774             : #endif
     775             : 
     776           0 :   const Order o = fe_t.order;
     777             : 
     778           0 :   fe_switch(shape(t,o,i,p));
     779             : }
     780             : 
     781           0 : Real FEInterface::shape(const unsigned int dim,
     782             :                         const FEType & fe_t,
     783             :                         const Elem * elem,
     784             :                         const unsigned int i,
     785             :                         const Point & p)
     786             : {
     787             :   libmesh_deprecated();
     788             : 
     789             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     790             : 
     791           0 :   if (elem && is_InfFE_elem(elem->type()))
     792           0 :     return ifem_shape(fe_t, elem, i, p);
     793             : 
     794             : #endif
     795             : 
     796           0 :   const Order o = fe_t.order;
     797             : 
     798           0 :   fe_switch(shape(elem,o,i,p));
     799             : }
     800             : #endif // LIBMESH_ENABLE_DEPRECATED
     801             : 
     802             : 
     803             : 
     804             : Real
     805   117577815 : FEInterface::shape(const FEType & fe_t,
     806             :                    const Elem * elem,
     807             :                    const unsigned int i,
     808             :                    const Point & p,
     809             :                    const bool add_p_level)
     810             : {
     811             :   // dim is required by the fe_switch macro
     812   117577815 :   auto dim = elem->dim();
     813             : 
     814             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     815             : 
     816    25334597 :   if (elem && is_InfFE_elem(elem->type()))
     817           0 :     return ifem_shape(fe_t, elem, i, p);
     818             : 
     819             : #endif
     820             : 
     821             :   // We are calling
     822             :   //
     823             :   // FE<X,Y>::shape(Elem *, Order, unsigned, Point, true)
     824             :   //
     825             :   // See fe.h for more details.
     826   117577815 :   fe_switch(shape(elem, fe_t.order, i, p, add_p_level));
     827             : }
     828             : 
     829             : 
     830             : 
     831             : Real
     832  1299482881 : FEInterface::shape(const FEType & fe_t,
     833             :                    int extra_order,
     834             :                    const Elem * elem,
     835             :                    const unsigned int i,
     836             :                    const Point & p)
     837             : {
     838             :   // dim is required by the fe_switch macro
     839  1299482881 :   auto dim = elem->dim();
     840             : 
     841             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     842             : 
     843   297568867 :   if (elem && is_InfFE_elem(elem->type()))
     844           0 :     return ifem_shape(fe_t, elem, i, p);
     845             : 
     846             : #endif
     847             : 
     848             :   // We are calling
     849             :   //
     850             :   // FE<X,Y>::shape(Elem *, Order, unsigned, Point, false)
     851             :   //
     852             :   // with the last parameter set to "false" so that the
     853             :   // Elem::p_level() is not used internally and the "total_order" that
     854             :   // we compute is used instead. See fe.h for more details.
     855   212513378 :   auto total_order = fe_t.order + extra_order;
     856             : 
     857  1299482881 :   fe_switch(shape(elem, total_order, i, p, false));
     858             : }
     859             : 
     860             : 
     861             : 
     862             : #ifdef LIBMESH_ENABLE_DEPRECATED
     863             : template<>
     864           0 : void FEInterface::shape<Real>(const unsigned int dim,
     865             :                               const FEType & fe_t,
     866             :                               const ElemType t,
     867             :                               const unsigned int i,
     868             :                               const Point & p,
     869             :                               Real & phi)
     870             : {
     871             :   libmesh_deprecated();
     872             : 
     873             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     874             : 
     875           0 :   if (is_InfFE_elem(t))
     876             :     {
     877           0 :       phi = ifem_shape(dim, fe_t, t, i, p);
     878           0 :       return;
     879             :     }
     880             : 
     881             : #endif
     882             : 
     883           0 :   const Order o = fe_t.order;
     884             : 
     885           0 :   switch(dim)
     886             :     {
     887           0 :     case 0:
     888           0 :       fe_scalar_vec_error_switch(0, shape(t,o,i,p), phi = , ; break;);
     889           0 :       break;
     890           0 :     case 1:
     891           0 :       fe_scalar_vec_error_switch(1, shape(t,o,i,p), phi = , ; break;);
     892           0 :       break;
     893           0 :     case 2:
     894           0 :       fe_scalar_vec_error_switch(2, shape(t,o,i,p), phi = , ; break;);
     895           0 :       break;
     896           0 :     case 3:
     897           0 :       fe_scalar_vec_error_switch(3, shape(t,o,i,p), phi = , ; break;);
     898           0 :       break;
     899           0 :     default:
     900           0 :       libmesh_error_msg("Invalid dimension = " << dim);
     901             :     }
     902             : 
     903           0 :   return;
     904             : }
     905             : 
     906             : 
     907             : 
     908             : template<>
     909           0 : void FEInterface::shape<Real>(const unsigned int dim,
     910             :                               const FEType & fe_t,
     911             :                               const Elem * elem,
     912             :                               const unsigned int i,
     913             :                               const Point & p,
     914             :                               Real & phi)
     915             : {
     916             :   libmesh_deprecated();
     917             : 
     918             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     919             : 
     920           0 :   if (elem && is_InfFE_elem(elem->type()))
     921             :     {
     922           0 :       phi = ifem_shape(fe_t, elem, i, p);
     923           0 :       return;
     924             :     }
     925             : #endif
     926             : 
     927           0 :   const Order o = fe_t.order;
     928             : 
     929           0 :   switch(dim)
     930             :     {
     931           0 :     case 0:
     932           0 :       fe_scalar_vec_error_switch(0, shape(elem,o,i,p), phi = , ; break;);
     933           0 :       break;
     934           0 :     case 1:
     935           0 :       fe_scalar_vec_error_switch(1, shape(elem,o,i,p), phi = , ; break;);
     936           0 :       break;
     937           0 :     case 2:
     938           0 :       fe_scalar_vec_error_switch(2, shape(elem,o,i,p), phi = , ; break;);
     939           0 :       break;
     940           0 :     case 3:
     941           0 :       fe_scalar_vec_error_switch(3, shape(elem,o,i,p), phi = , ; break;);
     942           0 :       break;
     943           0 :     default:
     944           0 :       libmesh_error_msg("Invalid dimension = " << dim);
     945             :     }
     946             : 
     947           0 :   return;
     948             : }
     949             : #endif // LIBMESH_ENABLE_DEPRECATED
     950             : 
     951             : 
     952             : 
     953             : template<>
     954           0 : void FEInterface::shape<Real>(const FEType & fe_t,
     955             :                               const Elem * elem,
     956             :                               const unsigned int i,
     957             :                               const Point & p,
     958             :                               Real & phi)
     959             : {
     960             :   // dim is required by the fe_switch macro
     961           0 :   auto dim = elem->dim();
     962             : 
     963             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     964             : 
     965           0 :   if (is_InfFE_elem(elem->type()))
     966             :     {
     967           0 :       phi = ifem_shape(fe_t, elem, i, p);
     968           0 :       return;
     969             :     }
     970             : 
     971             : #endif
     972             : 
     973             :   // Below we call FE<X,Y>::shape(Elem *, Order, unsigned, Point, true)
     974             :   // so that the Elem::p_level() is accounted for internally.
     975           0 :   switch(dim)
     976             :     {
     977           0 :     case 0:
     978           0 :       fe_scalar_vec_error_switch(0, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
     979           0 :       break;
     980           0 :     case 1:
     981           0 :       fe_scalar_vec_error_switch(1, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
     982           0 :       break;
     983           0 :     case 2:
     984           0 :       fe_scalar_vec_error_switch(2, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
     985           0 :       break;
     986           0 :     case 3:
     987           0 :       fe_scalar_vec_error_switch(3, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
     988           0 :       break;
     989           0 :     default:
     990           0 :       libmesh_error_msg("Invalid dimension = " << dim);
     991             :     }
     992           0 : }
     993             : 
     994             : 
     995             : 
     996             : template<>
     997           0 : void FEInterface::shape<Real>(const FEType & fe_t,
     998             :                               int extra_order,
     999             :                               const Elem * elem,
    1000             :                               const unsigned int i,
    1001             :                               const Point & p,
    1002             :                               Real & phi)
    1003             : {
    1004             :   // dim is required by the fe_switch macro
    1005           0 :   auto dim = elem->dim();
    1006             : 
    1007             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1008             : 
    1009           0 :   if (is_InfFE_elem(elem->type()))
    1010             :     {
    1011           0 :       phi = ifem_shape(fe_t, elem, i, p);
    1012           0 :       return;
    1013             :     }
    1014             : 
    1015             : #endif
    1016             : 
    1017             :   // Ignore Elem::p_level() and instead use extra_order to compute total_order
    1018           0 :   auto total_order = fe_t.order + extra_order;
    1019             : 
    1020             :   // Below we call
    1021             :   //
    1022             :   // FE<X,Y>::shape(Elem *, Order, unsigned, Point, false)
    1023             :   //
    1024             :   // so that the Elem::p_level() is ignored and the total_order that
    1025             :   // we compute is used instead.
    1026           0 :   switch(dim)
    1027             :     {
    1028           0 :     case 0:
    1029           0 :       fe_scalar_vec_error_switch(0, shape(elem, total_order, i, p, false), phi = , ; break;);
    1030           0 :       break;
    1031           0 :     case 1:
    1032           0 :       fe_scalar_vec_error_switch(1, shape(elem, total_order, i, p, false), phi = , ; break;);
    1033           0 :       break;
    1034           0 :     case 2:
    1035           0 :       fe_scalar_vec_error_switch(2, shape(elem, total_order, i, p, false), phi = , ; break;);
    1036           0 :       break;
    1037           0 :     case 3:
    1038           0 :       fe_scalar_vec_error_switch(3, shape(elem, total_order, i, p, false), phi = , ; break;);
    1039           0 :       break;
    1040           0 :     default:
    1041           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1042             :     }
    1043           0 : }
    1044             : 
    1045             : 
    1046             : 
    1047             : template<>
    1048     5259436 : void FEInterface::shapes<Real>(const unsigned int dim,
    1049             :                                const FEType & fe_t,
    1050             :                                const Elem * elem,
    1051             :                                const unsigned int i,
    1052             :                                const std::vector<Point> & p,
    1053             :                                std::vector<Real> & phi,
    1054             :                                const bool add_p_level)
    1055             : {
    1056             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1057             : 
    1058     1266664 :   if (elem && is_InfFE_elem(elem->type()))
    1059             :     {
    1060           0 :       FEType elevated = fe_t;
    1061           0 :       elevated.order = fe_t.order + add_p_level * elem->p_level();
    1062           0 :       for (auto qpi : index_range(p))
    1063           0 :         phi[qpi] = ifem_shape(elevated, elem, i, p[qpi]);
    1064           0 :       return;
    1065             :     }
    1066             : #endif
    1067             : 
    1068      902706 :   const Order o = fe_t.order;
    1069             : 
    1070     5259436 :   switch(dim)
    1071             :     {
    1072           0 :     case 0:
    1073           0 :       fe_scalar_vec_error_switch(0, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1074             :       break;
    1075        3564 :     case 1:
    1076        3564 :       fe_scalar_vec_error_switch(1, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1077             :       break;
    1078     2476152 :     case 2:
    1079     2476152 :       fe_scalar_vec_error_switch(2, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1080             :       break;
    1081     2779720 :     case 3:
    1082     2779720 :       fe_scalar_vec_error_switch(3, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1083             :       break;
    1084           0 :     default:
    1085           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1086             :     }
    1087             : 
    1088             :   return;
    1089             : }
    1090             : 
    1091             : 
    1092             : template<>
    1093   133072564 : void FEInterface::all_shapes<Real>(const unsigned int dim,
    1094             :                                    const FEType & fe_t,
    1095             :                                    const Elem * elem,
    1096             :                                    const std::vector<Point> & p,
    1097             :                                    std::vector<std::vector<Real>> & phi,
    1098             :                                    const bool add_p_level)
    1099             : {
    1100             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1101             : 
    1102    30330899 :   if (elem && is_InfFE_elem(elem->type()))
    1103             :     {
    1104           0 :       for (auto i : index_range(phi))
    1105           0 :         FEInterface::shapes<Real>(dim, fe_t, elem, i, p, phi[i], add_p_level);
    1106           0 :       return;
    1107             :     }
    1108             : #endif
    1109             : 
    1110    23964736 :   const Order o = fe_t.order;
    1111             : 
    1112   133072564 :   switch(dim)
    1113             :     {
    1114      198780 :     case 0:
    1115      198780 :       fe_scalar_vec_error_switch(0, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1116             :       break;
    1117     2803562 :     case 1:
    1118     2803562 :       fe_scalar_vec_error_switch(1, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1119             :       break;
    1120    98148973 :     case 2:
    1121    98148973 :       fe_scalar_vec_error_switch(2, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1122             :       break;
    1123    31921249 :     case 3:
    1124    31921249 :       fe_scalar_vec_error_switch(3, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1125             :       break;
    1126           0 :     default:
    1127           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1128             :     }
    1129             : 
    1130             :   return;
    1131             : }
    1132             : 
    1133             : 
    1134             : 
    1135             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1136             : template<>
    1137           0 : void FEInterface::shape<RealGradient>(const unsigned int dim,
    1138             :                                       const FEType & fe_t,
    1139             :                                       const ElemType t,
    1140             :                                       const unsigned int i,
    1141             :                                       const Point & p,
    1142             :                                       RealGradient & phi)
    1143             : {
    1144             :   libmesh_deprecated();
    1145             : 
    1146             :   // This API does not currently support infinite elements.
    1147             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1148           0 :   if (is_InfFE_elem(t))
    1149             :   {
    1150           0 :      libmesh_not_implemented();
    1151             :   }
    1152             : #endif
    1153           0 :   const Order o = fe_t.order;
    1154             : 
    1155           0 :   switch(dim)
    1156             :     {
    1157           0 :     case 0:
    1158           0 :       fe_vector_scalar_error_switch(0, shape(t,o,i,p), phi = , ; break;);
    1159           0 :       break;
    1160           0 :     case 1:
    1161           0 :       fe_vector_scalar_error_switch(1, shape(t,o,i,p), phi = , ; break;);
    1162           0 :       break;
    1163           0 :     case 2:
    1164           0 :       fe_vector_scalar_error_switch(2, shape(t,o,i,p), phi = , ; break;);
    1165           0 :       break;
    1166           0 :     case 3:
    1167           0 :       fe_vector_scalar_error_switch(3, shape(t,o,i,p), phi = , ; break;);
    1168           0 :       break;
    1169           0 :     default:
    1170           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1171             :     }
    1172           0 : }
    1173             : #endif // LIBMESH_ENABLE_DEPRECATED
    1174             : 
    1175             : 
    1176             : 
    1177             : template<>
    1178           0 : void FEInterface::shape<RealGradient>(const FEType & fe_t,
    1179             :                                       const Elem * elem,
    1180             :                                       const unsigned int i,
    1181             :                                       const Point & p,
    1182             :                                       RealGradient & phi)
    1183             : {
    1184             :   // This API does not currently support infinite elements.
    1185             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1186           0 :   if (is_InfFE_elem(elem->type()))
    1187             :   {
    1188           0 :      libmesh_not_implemented();
    1189             :   }
    1190             : #endif
    1191             : 
    1192           0 :   auto dim = elem->dim();
    1193             : 
    1194             :   // We are calling
    1195             :   //
    1196             :   // FE<X,Y>::shape(Elem *, Order, unsigned, Point, true)
    1197             :   //
    1198             :   // with the last parameter set to "true" so that the Elem::p_level()
    1199             :   // is accounted for internally. See fe.h for more details.
    1200             : 
    1201           0 :   switch(dim)
    1202             :     {
    1203           0 :     case 0:
    1204           0 :       fe_vector_scalar_error_switch(0, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
    1205           0 :       break;
    1206           0 :     case 1:
    1207           0 :       fe_vector_scalar_error_switch(1, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
    1208           0 :       break;
    1209           0 :     case 2:
    1210           0 :       fe_vector_scalar_error_switch(2, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
    1211           0 :       break;
    1212           0 :     case 3:
    1213           0 :       fe_vector_scalar_error_switch(3, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
    1214           0 :       break;
    1215           0 :     default:
    1216           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1217             :     }
    1218           0 : }
    1219             : 
    1220             : 
    1221             : 
    1222             : template<>
    1223   127666572 : void FEInterface::shape<RealGradient>(const FEType & fe_t,
    1224             :                                       int extra_order,
    1225             :                                       const Elem * elem,
    1226             :                                       const unsigned int i,
    1227             :                                       const Point & p,
    1228             :                                       RealGradient & phi)
    1229             : {
    1230             :   // This API does not currently support infinite elements.
    1231             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1232    25307726 :   if (is_InfFE_elem(elem->type()))
    1233             :   {
    1234           0 :      libmesh_not_implemented();
    1235             :   }
    1236             : #endif
    1237             : 
    1238   127666572 :   auto dim = elem->dim();
    1239             : 
    1240             :   // We are calling
    1241             :   //
    1242             :   // FE<X,Y>::shape(Elem *, Order, unsigned, Point, false)
    1243             :   //
    1244             :   // with the last parameter set to "false" so that the
    1245             :   // Elem::p_level() is not used internally and the "total_order" that
    1246             :   // we compute is used instead. See fe.h for more details.
    1247    17098092 :   auto total_order = fe_t.order + extra_order;
    1248             : 
    1249   127666572 :   switch(dim)
    1250             :     {
    1251           0 :     case 0:
    1252           0 :       fe_vector_scalar_error_switch(0, shape(elem, total_order, i, p, false), phi = , ; break;);
    1253           0 :       break;
    1254           0 :     case 1:
    1255           0 :       fe_vector_scalar_error_switch(1, shape(elem, total_order, i, p, false), phi = , ; break;);
    1256           0 :       break;
    1257    36033678 :     case 2:
    1258    36033678 :       fe_vector_scalar_error_switch(2, shape(elem, total_order, i, p, false), phi = , ; break;);
    1259     2809122 :       break;
    1260    91632894 :     case 3:
    1261    91632894 :       fe_vector_scalar_error_switch(3, shape(elem, total_order, i, p, false), phi = , ; break;);
    1262     5739924 :       break;
    1263           0 :     default:
    1264           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1265             :     }
    1266   127666572 : }
    1267             : 
    1268             : 
    1269             : 
    1270             : template<>
    1271           0 : void FEInterface::shapes<RealGradient>(const unsigned int dim,
    1272             :                                        const FEType & fe_t,
    1273             :                                        const Elem * elem,
    1274             :                                        const unsigned int i,
    1275             :                                        const std::vector<Point> & p,
    1276             :                                        std::vector<RealGradient> & phi,
    1277             :                                        const bool add_p_level)
    1278             : {
    1279             :   // This is actually an issue for infinite elements: They require type 'Gradient'!
    1280           0 :   if (elem->infinite())
    1281           0 :     libmesh_not_implemented();
    1282             : 
    1283           0 :   const Order o = fe_t.order;
    1284             : 
    1285           0 :   switch(dim)
    1286             :     {
    1287           0 :     case 0:
    1288           0 :       fe_vector_scalar_error_switch(0, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1289             :       break;
    1290           0 :     case 1:
    1291           0 :       fe_vector_scalar_error_switch(1, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1292             :       break;
    1293           0 :     case 2:
    1294           0 :       fe_vector_scalar_error_switch(2, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1295             :       break;
    1296           0 :     case 3:
    1297           0 :       fe_vector_scalar_error_switch(3, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
    1298             :       break;
    1299           0 :     default:
    1300           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1301             :     }
    1302             : 
    1303             :   return;
    1304             : }
    1305             : 
    1306             : 
    1307             : 
    1308             : template<>
    1309     6445360 : void FEInterface::all_shapes<RealGradient>(const unsigned int dim,
    1310             :                                            const FEType & fe_t,
    1311             :                                            const Elem * elem,
    1312             :                                            const std::vector<Point> & p,
    1313             :                                            std::vector<std::vector<RealGradient>> & phi,
    1314             :                                            const bool add_p_level)
    1315             : {
    1316             :   // This is actually an issue for infinite elements: They require type 'Gradient'!
    1317     1597436 :   if (elem->infinite())
    1318           0 :     libmesh_not_implemented();
    1319             : 
    1320     1075052 :   const Order o = fe_t.order;
    1321             : 
    1322     6445360 :   switch(dim)
    1323             :     {
    1324           0 :     case 0:
    1325           0 :       fe_vector_scalar_error_switch(0, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1326             :       break;
    1327           0 :     case 1:
    1328           0 :       fe_vector_scalar_error_switch(1, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1329             :       break;
    1330     1994299 :     case 2:
    1331     1994299 :       fe_vector_scalar_error_switch(2, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1332             :       break;
    1333     4451061 :     case 3:
    1334     4451061 :       fe_vector_scalar_error_switch(3, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
    1335             :       break;
    1336           0 :     default:
    1337           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1338             :     }
    1339             : 
    1340             :   return;
    1341             : }
    1342             : 
    1343             : 
    1344             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1345             : FEInterface::shape_ptr
    1346           0 : FEInterface::shape_function(const unsigned int dim,
    1347             :                             const FEType & fe_t,
    1348             :                             const ElemType libmesh_inf_var(t))
    1349             : {
    1350             :   libmesh_deprecated();
    1351             : 
    1352             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1353           0 :   if (is_InfFE_elem(t))
    1354             :    {
    1355           0 :     inf_fe_switch(shape);
    1356             :    }
    1357             : #endif
    1358           0 :   fe_switch(shape);
    1359             : }
    1360             : #endif // LIBMESH_ENABLE_DEPRECATED
    1361             : 
    1362             : 
    1363             : 
    1364             : FEInterface::shape_ptr
    1365   346833459 : FEInterface::shape_function(const FEType & fe_t,
    1366             :                             const Elem * elem)
    1367             : {
    1368             :   // dim is needed by the fe_switch macros below
    1369   346833459 :   auto dim = elem->dim();
    1370             : 
    1371             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1372    64037862 :   if (is_InfFE_elem(elem->type()))
    1373           0 :     inf_fe_switch(shape);
    1374             : #endif
    1375   346833459 :   fe_switch(shape);
    1376             : }
    1377             : 
    1378             : 
    1379             : 
    1380             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1381           0 : Real FEInterface::shape_deriv(const unsigned int dim,
    1382             :                               const FEType & fe_t,
    1383             :                               const ElemType t,
    1384             :                               const unsigned int i,
    1385             :                               const unsigned int j,
    1386             :                               const Point & p)
    1387             : {
    1388             :   libmesh_deprecated();
    1389             : 
    1390           0 :   libmesh_assert_greater (dim,j);
    1391             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1392             : 
    1393           0 :   if (is_InfFE_elem(t)){
    1394           0 :     return ifem_shape_deriv(dim, fe_t, t, i, j, p);
    1395             :   }
    1396             : 
    1397             : #endif
    1398             : 
    1399           0 :   const Order o = fe_t.order;
    1400           0 :   fe_switch(shape_deriv(t,o,i,j,p));
    1401             :   return 0;
    1402             : }
    1403             : 
    1404             : 
    1405           0 : Real FEInterface::shape_deriv(const unsigned int dim,
    1406             :                               const FEType & fe_t,
    1407             :                               const Elem * elem,
    1408             :                               const unsigned int i,
    1409             :                               const unsigned int j,
    1410             :                               const Point & p)
    1411             : {
    1412             :   libmesh_deprecated();
    1413             : 
    1414           0 :   libmesh_assert_greater (dim,j);
    1415             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1416             : 
    1417           0 :   if (elem->infinite()){
    1418           0 :     return ifem_shape_deriv(fe_t, elem, i, j, p);
    1419             :   }
    1420             : 
    1421             : #endif
    1422             : 
    1423           0 :   const Order o = fe_t.order;
    1424             : 
    1425           0 :   switch(dim)
    1426             :     {
    1427           0 :     case 0:
    1428           0 :       fe_family_switch (0, shape_deriv(elem, o, i, j, p), return , ;);
    1429           0 :     case 1:
    1430           0 :       fe_family_switch (1, shape_deriv(elem, o, i, j, p), return , ;);
    1431           0 :     case 2:
    1432           0 :       fe_family_switch (2, shape_deriv(elem, o, i, j, p), return , ;);
    1433           0 :     case 3:
    1434           0 :       fe_family_switch (3, shape_deriv(elem, o, i, j, p), return , ;);
    1435           0 :     default:
    1436           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1437             :     }
    1438             :   return 0;
    1439             : }
    1440             : #endif // LIBMESH_ENABLE_DEPRECATED
    1441             : 
    1442             : 
    1443             : 
    1444           0 : Real FEInterface::shape_deriv(const FEType & fe_t,
    1445             :                               const Elem * elem,
    1446             :                               const unsigned int i,
    1447             :                               const unsigned int j,
    1448             :                               const Point & p)
    1449             : {
    1450           0 :   auto dim = elem->dim();
    1451             : 
    1452           0 :   libmesh_assert_greater (dim, j);
    1453             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1454             : 
    1455           0 :   if (is_InfFE_elem(elem->type())){
    1456           0 :     return ifem_shape_deriv(fe_t, elem, i, j, p);
    1457             :   }
    1458             : 
    1459             : #endif
    1460             : 
    1461             :   // Account for Elem::p_level() when computing total order. Note: we are calling
    1462             :   // FE::shape_deriv() with the final argument == true so that the Elem::p_level()
    1463             :   // is accounted for automatically internally.
    1464           0 :   fe_switch(shape_deriv(elem, fe_t.order, i, j, p, true));
    1465             : 
    1466             :   // We'll never get here
    1467             :   return 0;
    1468             : }
    1469             : 
    1470             : 
    1471             : 
    1472  1147292040 : Real FEInterface::shape_deriv(const FEType & fe_t,
    1473             :                               int extra_order,
    1474             :                               const Elem * elem,
    1475             :                               const unsigned int i,
    1476             :                               const unsigned int j,
    1477             :                               const Point & p)
    1478             : {
    1479  1147292040 :   auto dim = elem->dim();
    1480             : 
    1481    93142120 :   libmesh_assert_greater (dim, j);
    1482             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1483             : 
    1484   266200734 :   if (elem->infinite()){
    1485           0 :     return ifem_shape_deriv(fe_t, elem, i, j, p);
    1486             :   }
    1487             : 
    1488             : #endif
    1489             : 
    1490             :   // Ignore Elem::p_level() when computing total order, use
    1491             :   // extra_order instead.
    1492   186284240 :   auto total_order = fe_t.order + extra_order;
    1493             : 
    1494             :   // We call shape_deriv() with the final argument == false so that
    1495             :   // the Elem::p_level() is ignored internally.
    1496  1147292040 :   switch(dim)
    1497             :     {
    1498           0 :     case 0:
    1499           0 :       fe_family_switch (0, shape_deriv(elem, total_order, i, j, p, false), return , ;);
    1500     1367970 :     case 1:
    1501     1367970 :       fe_family_switch (1, shape_deriv(elem, total_order, i, j, p, false), return , ;);
    1502   294515286 :     case 2:
    1503   294515286 :       fe_family_switch (2, shape_deriv(elem, total_order, i, j, p, false), return , ;);
    1504   851408784 :     case 3:
    1505   851408784 :       fe_family_switch (3, shape_deriv(elem, total_order, i, j, p, false), return , ;);
    1506           0 :     default:
    1507           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1508             :     }
    1509             : 
    1510             :   // We'll never get here
    1511             :   return 0;
    1512             : }
    1513             : 
    1514             : 
    1515             : 
    1516             : template<>
    1517    15491514 : void FEInterface::shape_derivs<Real>(const FEType & fe_t,
    1518             :                                      const Elem * elem,
    1519             :                                      const unsigned int i,
    1520             :                                      const unsigned int j,
    1521             :                                      const std::vector<Point> & p,
    1522             :                                      std::vector<Real> & dphi,
    1523             :                                      const bool add_p_level)
    1524             : {
    1525     2667244 :   const Order o = fe_t.order;
    1526             : 
    1527    15491514 :   switch(elem->dim())
    1528             :     {
    1529           0 :     case 0:
    1530           0 :       fe_scalar_vec_error_switch(0, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1531           0 :       break;
    1532        4320 :     case 1:
    1533        4320 :       fe_scalar_vec_error_switch(1, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1534         361 :       break;
    1535     7094340 :     case 2:
    1536     7094340 :       fe_scalar_vec_error_switch(2, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1537      669556 :       break;
    1538     8392854 :     case 3:
    1539     8392854 :       fe_scalar_vec_error_switch(3, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1540      663705 :       break;
    1541           0 :     default:
    1542           0 :       libmesh_error_msg("Invalid dimension = " << elem->dim());
    1543             :     }
    1544             : 
    1545    15491514 :   return;
    1546             : }
    1547             : 
    1548             : 
    1549             : 
    1550             : // Only instantiating Real because we don't expect vector-valued
    1551             : // mapping functions, and that's what's using this interface.
    1552             : template<>
    1553    37291440 : void FEInterface::all_shape_derivs<Real>(const unsigned int dim,
    1554             :                                          const FEType & fe_t,
    1555             :                                          const Elem * elem,
    1556             :                                          const std::vector<Point> & p,
    1557             :                                          std::vector<std::vector<Real>> * comps[3],
    1558             :                                          const bool add_p_level)
    1559             : {
    1560             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1561             : 
    1562     9533938 :   if (elem && is_InfFE_elem(elem->type()))
    1563             :     {
    1564           0 :       for (auto j : make_range(dim))
    1565           0 :         for (auto i : index_range(*comps[j]))
    1566           0 :           FEInterface::shape_derivs<Real>(fe_t, elem, i, j, p, (*comps[j])[i], add_p_level);
    1567           0 :       return;
    1568             :     }
    1569             : #endif
    1570             : 
    1571     6595272 :   const Order o = fe_t.order;
    1572             : 
    1573    37291440 :   switch(dim)
    1574             :     {
    1575           0 :     case 0:
    1576           0 :       fe_scalar_vec_error_switch(0, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
    1577             :       break;
    1578      134740 :     case 1:
    1579      134740 :       fe_scalar_vec_error_switch(1, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
    1580             :       break;
    1581    14423626 :     case 2:
    1582    14423626 :       fe_scalar_vec_error_switch(2, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
    1583             :       break;
    1584    22733074 :     case 3:
    1585    22733074 :       fe_scalar_vec_error_switch(3, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
    1586             :       break;
    1587           0 :     default:
    1588           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1589             :     }
    1590             : 
    1591             :   return;
    1592             : }
    1593             : 
    1594             : 
    1595             : 
    1596             : template<>
    1597           0 : void FEInterface::shape_derivs<RealGradient>(const FEType & fe_t,
    1598             :                                              const Elem * elem,
    1599             :                                              const unsigned int i,
    1600             :                                              const unsigned int j,
    1601             :                                              const std::vector<Point> & p,
    1602             :                                              std::vector<RealGradient> & dphi,
    1603             :                                              const bool add_p_level)
    1604             : {
    1605           0 :   const Order o = fe_t.order;
    1606             : 
    1607           0 :   switch(elem->dim())
    1608             :     {
    1609           0 :     case 0:
    1610           0 :       fe_vector_scalar_error_switch(0, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1611           0 :       break;
    1612           0 :     case 1:
    1613           0 :       fe_vector_scalar_error_switch(1, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1614           0 :       break;
    1615           0 :     case 2:
    1616           0 :       fe_vector_scalar_error_switch(2, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1617           0 :       break;
    1618           0 :     case 3:
    1619           0 :       fe_vector_scalar_error_switch(3, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
    1620           0 :       break;
    1621           0 :     default:
    1622           0 :       libmesh_error_msg("Invalid dimension = " << elem->dim());
    1623             :     }
    1624             : 
    1625           0 :   return;
    1626             : }
    1627             : 
    1628             : 
    1629             : 
    1630             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1631             : FEInterface::shape_deriv_ptr
    1632           0 : FEInterface::shape_deriv_function(const unsigned int dim,
    1633             :                                   const FEType & fe_t,
    1634             :                                   const ElemType libmesh_inf_var(t))
    1635             : {
    1636             :   libmesh_deprecated();
    1637             : 
    1638             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1639           0 :   if (is_InfFE_elem(t))
    1640             :   {
    1641           0 :     inf_fe_switch(shape_deriv);
    1642             :   }
    1643             : #endif
    1644           0 :   fe_switch(shape_deriv);
    1645             : }
    1646             : #endif // LIBMESH_ENABLE_DEPRECATED
    1647             : 
    1648             : 
    1649             : 
    1650             : FEInterface::shape_deriv_ptr
    1651  1173153407 : FEInterface::shape_deriv_function(const FEType & fe_t,
    1652             :                                   const Elem * elem)
    1653             : {
    1654             :   // dim is needed by the fe_switch macros below
    1655  1173153407 :   auto dim = elem->dim();
    1656             : 
    1657             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1658   209190311 :   if (is_InfFE_elem(elem->type()))
    1659             :   {
    1660           0 :     inf_fe_switch(shape_deriv);
    1661             :   }
    1662             : #endif
    1663  1173153407 :   fe_switch(shape_deriv);
    1664             : }
    1665             : 
    1666             : 
    1667             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1668             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1669           0 : Real FEInterface::shape_second_deriv(const unsigned int dim,
    1670             :                                      const FEType & fe_t,
    1671             :                                      const ElemType t,
    1672             :                                      const unsigned int i,
    1673             :                                      const unsigned int j,
    1674             :                                      const Point & p)
    1675             : {
    1676             :   libmesh_deprecated();
    1677             : 
    1678           0 :   libmesh_assert_greater_equal (dim*(dim-1),j);
    1679             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1680           0 :   if (is_InfFE_elem(t))
    1681           0 :     libmesh_not_implemented();
    1682             : #endif
    1683             : 
    1684           0 :   const Order o = fe_t.order;
    1685             : 
    1686           0 :   switch(dim)
    1687             :     {
    1688           0 :     case 0:
    1689           0 :       fe_family_switch (0, shape_second_deriv(t, o, i, j, p), return , ;);
    1690           0 :     case 1:
    1691           0 :       fe_family_switch (1, shape_second_deriv(t, o, i, j, p), return , ;);
    1692           0 :     case 2:
    1693           0 :       fe_family_switch (2, shape_second_deriv(t, o, i, j, p), return  , ;);
    1694           0 :     case 3:
    1695           0 :       fe_family_switch (3, shape_second_deriv(t, o, i, j, p), return , ;);
    1696           0 :     default:
    1697           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1698             :     }
    1699             :   return 0;
    1700             : }
    1701             : 
    1702             : 
    1703           0 : Real FEInterface::shape_second_deriv(const unsigned int dim,
    1704             :                                      const FEType & fe_t,
    1705             :                                      const Elem * elem,
    1706             :                                      const unsigned int i,
    1707             :                                      const unsigned int j,
    1708             :                                      const Point & p)
    1709             : {
    1710             :   libmesh_deprecated();
    1711             : 
    1712           0 :   libmesh_assert_greater_equal (dim*(dim-1),j);
    1713             : 
    1714           0 :   if (elem->infinite())
    1715           0 :     libmesh_not_implemented();
    1716             : 
    1717           0 :   const Order o = fe_t.order;
    1718             : 
    1719           0 :   switch(dim)
    1720             :     {
    1721           0 :     case 0:
    1722           0 :       fe_family_switch (0, shape_second_deriv(elem, o, i, j, p), return , ;);
    1723           0 :     case 1:
    1724           0 :       fe_family_switch (1, shape_second_deriv(elem, o, i, j, p), return , ;);
    1725           0 :     case 2:
    1726           0 :       fe_family_switch (2, shape_second_deriv(elem, o, i, j, p), return , ;);
    1727           0 :     case 3:
    1728           0 :       fe_family_switch (3, shape_second_deriv(elem, o, i, j, p), return , ;);
    1729           0 :     default:
    1730           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1731             :     }
    1732             :   return 0;
    1733             : }
    1734             : #endif // LIBMESH_ENABLE_DEPRECATED
    1735             : 
    1736             : 
    1737             : 
    1738           0 : Real FEInterface::shape_second_deriv(const FEType & fe_t,
    1739             :                                      const Elem * elem,
    1740             :                                      const unsigned int i,
    1741             :                                      const unsigned int j,
    1742             :                                      const Point & p)
    1743             : {
    1744           0 :   auto dim = elem->dim();
    1745             : 
    1746           0 :   libmesh_assert_greater_equal (dim*(dim-1),j);
    1747             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1748           0 :   if (is_InfFE_elem(elem->type()))
    1749           0 :     libmesh_not_implemented();
    1750             : #endif
    1751             : 
    1752             :   // We are calling FE::shape_second_deriv() with the final argument
    1753             :   // == true so that the Elem::p_level() is accounted for
    1754             :   // automatically internally.
    1755           0 :   switch(dim)
    1756             :     {
    1757           0 :     case 0:
    1758           0 :       fe_family_switch (0, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
    1759           0 :     case 1:
    1760           0 :       fe_family_switch (1, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
    1761           0 :     case 2:
    1762           0 :       fe_family_switch (2, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
    1763           0 :     case 3:
    1764           0 :       fe_family_switch (3, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
    1765           0 :     default:
    1766           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1767             :     }
    1768             : 
    1769             :   // We'll never get here
    1770             :   return 0;
    1771             : }
    1772             : 
    1773             : 
    1774             : 
    1775   294333942 : Real FEInterface::shape_second_deriv(const FEType & fe_t,
    1776             :                                      int extra_order,
    1777             :                                      const Elem * elem,
    1778             :                                      const unsigned int i,
    1779             :                                      const unsigned int j,
    1780             :                                      const Point & p)
    1781             : {
    1782   294333942 :   auto dim = elem->dim();
    1783             : 
    1784    24406880 :   libmesh_assert_greater_equal (dim*(dim-1),j);
    1785             : 
    1786    73173051 :   if (elem->infinite())
    1787           0 :     libmesh_not_implemented();
    1788             : 
    1789             :   // Ignore Elem::p_level() when computing total order, use
    1790             :   // extra_order instead.
    1791    48813760 :   auto total_order = fe_t.order + extra_order;
    1792             : 
    1793             :   // We are calling FE::shape_second_deriv() with the final argument
    1794             :   // == false so that the Elem::p_level() is ignored and the
    1795             :   // total_order we compute is used instead.
    1796   294333942 :   switch(dim)
    1797             :     {
    1798           0 :     case 0:
    1799           0 :       fe_family_switch (0, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
    1800        9060 :     case 1:
    1801        9060 :       fe_family_switch (1, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
    1802     2002122 :     case 2:
    1803     2002122 :       fe_family_switch (2, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
    1804   292322760 :     case 3:
    1805   292322760 :       fe_family_switch (3, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
    1806           0 :     default:
    1807           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1808             :     }
    1809             : 
    1810             :   // We'll never get here
    1811             :   return 0;
    1812             : }
    1813             : 
    1814             : 
    1815             : 
    1816             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1817             : FEInterface::shape_second_deriv_ptr
    1818           0 : FEInterface::shape_second_deriv_function(const unsigned int dim,
    1819             :                                          const FEType & fe_t,
    1820             :                                          const ElemType libmesh_inf_var(t))
    1821             : {
    1822             :   libmesh_deprecated();
    1823             : 
    1824             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1825           0 :   if (is_InfFE_elem(t))
    1826           0 :     libmesh_not_implemented();
    1827             : #endif
    1828           0 :   fe_switch(shape_second_deriv);
    1829             : }
    1830             : #endif // LIBMESH_ENABLE_DEPRECATED
    1831             : 
    1832             : 
    1833             : 
    1834             : FEInterface::shape_second_deriv_ptr
    1835    69316904 : FEInterface::shape_second_deriv_function(const FEType & fe_t,
    1836             :                                          const Elem * elem)
    1837             : {
    1838    69316904 :   auto dim = elem->dim();
    1839             : 
    1840             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1841    16780786 :   if (is_InfFE_elem(elem->type()))
    1842           0 :     libmesh_not_implemented();
    1843             : #endif
    1844    69316904 :   fe_switch(shape_second_deriv);
    1845             : }
    1846             : 
    1847             : #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES
    1848             : 
    1849             : 
    1850             : #ifdef LIBMESH_ENABLE_DEPRECATED
    1851             : template<>
    1852           0 : void FEInterface::shape<RealGradient>(const unsigned int dim,
    1853             :                                       const FEType & fe_t,
    1854             :                                       const Elem * elem,
    1855             :                                       const unsigned int i,
    1856             :                                       const Point & p,
    1857             :                                       RealGradient & phi)
    1858             : {
    1859             :   libmesh_deprecated();
    1860             : 
    1861             :   // This is actually an issue for infinite elements: They require type 'Gradient'!
    1862           0 :   if (elem->infinite())
    1863           0 :     libmesh_not_implemented();
    1864             : 
    1865           0 :   const Order o = fe_t.order;
    1866             : 
    1867           0 :   switch(dim)
    1868             :     {
    1869           0 :     case 0:
    1870           0 :       fe_vector_scalar_error_switch(0, shape(elem,o,i,p), phi = , ; break;);
    1871           0 :       break;
    1872           0 :     case 1:
    1873           0 :       fe_vector_scalar_error_switch(1, shape(elem,o,i,p), phi = , ; break;);
    1874           0 :       break;
    1875           0 :     case 2:
    1876           0 :       fe_vector_scalar_error_switch(2, shape(elem,o,i,p), phi = , ; break;);
    1877           0 :       break;
    1878           0 :     case 3:
    1879           0 :       fe_vector_scalar_error_switch(3, shape(elem,o,i,p), phi = , ; break;);
    1880           0 :       break;
    1881           0 :     default:
    1882           0 :       libmesh_error_msg("Invalid dimension = " << dim);
    1883             :     }
    1884             : 
    1885           0 :   return;
    1886             : }
    1887             : #endif // LIBMESH_ENABLE_DEPRECATED
    1888             : 
    1889             : 
    1890     7788610 : void FEInterface::compute_data(const unsigned int dim,
    1891             :                                const FEType & fe_t,
    1892             :                                const Elem * elem,
    1893             :                                FEComputeData & data)
    1894             : {
    1895             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
    1896             : 
    1897      720622 :   if (elem && is_InfFE_elem(elem->type()))
    1898             :     {
    1899           0 :       data.init();
    1900           0 :       ifem_compute_data(dim, fe_t, elem, data);
    1901           0 :       return;
    1902             :     }
    1903             : 
    1904             : #endif
    1905             : 
    1906     7788610 :   const unsigned int n_dof = n_dofs (fe_t, elem);
    1907     7788610 :   const Point & p = data.p;
    1908     7788610 :   data.shape.resize(n_dof);
    1909             : 
    1910     7788610 :   if (data.need_derivative())
    1911             :     {
    1912           0 :       data.dshape.resize(n_dof);
    1913           0 :       data.local_transform.resize(dim);
    1914             : 
    1915           0 :       for (unsigned int d=0; d<dim; d++)
    1916           0 :         data.local_transform[d].resize(dim);
    1917             : 
    1918           0 :       auto fe = FEBase::build(dim, fe_t);
    1919           0 :       std::vector<Point> pt = {p};
    1920           0 :       fe->get_dphideta(); // to compute the map
    1921           0 :       fe->reinit(elem, &pt);
    1922             : 
    1923             :       // compute the reference->physical map.
    1924           0 :       data.local_transform[0][0] = fe->get_dxidx()[0];
    1925           0 :       if (dim > 1)
    1926             :         {
    1927           0 :           data.local_transform[1][0] = fe->get_detadx()[0];
    1928           0 :           data.local_transform[1][1] = fe->get_detady()[0];
    1929           0 :           data.local_transform[0][1] = fe->get_dxidy()[0];
    1930           0 :           if (dim > 2)
    1931             :             {
    1932           0 :               data.local_transform[2][0] = fe->get_dzetadx()[0];
    1933           0 :               data.local_transform[2][1] = fe->get_dzetady()[0];
    1934           0 :               data.local_transform[2][2] = fe->get_dzetadz()[0];
    1935           0 :               data.local_transform[1][2] = fe->get_detadz()[0];
    1936           0 :               data.local_transform[0][2] = fe->get_dxidz()[0];
    1937             :             }
    1938             :         }
    1939           0 :     }
    1940             : 
    1941             :   // set default values for all the output fields
    1942     7788610 :   data.init();
    1943             : 
    1944    49178902 :   for (unsigned int n=0; n<n_dof; n++)
    1945             :     {
    1946             :       // Here we pass the original fe_t object. Additional p-levels
    1947             :       // (if any) are handled internally by the shape() and
    1948             :       // shape_deriv() functions since they have access to the elem
    1949             :       // pointer. Note that we are already using the n_dof value
    1950             :       // appropriate to the elevated p-level.
    1951    41390292 :       data.shape[n] = shape(fe_t, elem, n, p);
    1952    41390292 :       if (data.need_derivative())
    1953             :         {
    1954           0 :           for (unsigned int j=0; j<dim; j++)
    1955           0 :             data.dshape[n](j) = shape_deriv(fe_t, elem, n, j, p);
    1956             :         }
    1957             :     }
    1958     7067988 : }
    1959             : 
    1960             : 
    1961             : 
    1962             : #ifdef LIBMESH_ENABLE_AMR
    1963             : 
    1964     7785463 : void FEInterface::compute_constraints (DofConstraints & constraints,
    1965             :                                        DofMap & dof_map,
    1966             :                                        const unsigned int variable_number,
    1967             :                                        const Elem * elem)
    1968             : {
    1969      691980 :   libmesh_assert(elem);
    1970             : 
    1971      691980 :   const FEType & fe_t = dof_map.variable_type(variable_number);
    1972             : 
    1973     7785463 :   switch (elem->dim())
    1974             :     {
    1975       13356 :     case 0:
    1976             :     case 1:
    1977             :       {
    1978             :         // No constraints in 0D/1D.
    1979       13356 :         return;
    1980             :       }
    1981             : 
    1982             : 
    1983     4271029 :     case 2:
    1984             :       {
    1985     4271029 :         switch (fe_t.family)
    1986             :           {
    1987       38464 :           case CLOUGH:
    1988       38464 :             FE<2,CLOUGH>::compute_constraints (constraints,
    1989             :                                                dof_map,
    1990             :                                                variable_number,
    1991       38464 :                                                elem); return;
    1992             : 
    1993       18144 :           case HERMITE:
    1994       18144 :             FE<2,HERMITE>::compute_constraints (constraints,
    1995             :                                                 dof_map,
    1996             :                                                 variable_number,
    1997       18144 :                                                 elem); return;
    1998             : 
    1999     3203935 :           case LAGRANGE:
    2000     3203935 :             FE<2,LAGRANGE>::compute_constraints (constraints,
    2001             :                                                  dof_map,
    2002             :                                                  variable_number,
    2003     3203935 :                                                  elem); return;
    2004             : 
    2005      291404 :           case HIERARCHIC:
    2006      291404 :             FE<2,HIERARCHIC>::compute_constraints (constraints,
    2007             :                                                    dof_map,
    2008             :                                                    variable_number,
    2009      291404 :                                                    elem); return;
    2010             : 
    2011        7860 :           case HIERARCHIC_VEC:
    2012        7860 :             FE<2,HIERARCHIC_VEC>::compute_constraints (constraints,
    2013             :                                                        dof_map,
    2014             :                                                        variable_number,
    2015        7860 :                                                        elem); return;
    2016             : 
    2017       65168 :           case SIDE_HIERARCHIC:
    2018       65168 :             FE<2,SIDE_HIERARCHIC>::compute_constraints (constraints,
    2019             :                                                         dof_map,
    2020             :                                                         variable_number,
    2021       65168 :                                                         elem); return;
    2022             : 
    2023        7256 :           case LAGRANGE_VEC:
    2024        7256 :             FE<2,LAGRANGE_VEC>::compute_constraints (constraints,
    2025             :                                                      dof_map,
    2026             :                                                      variable_number,
    2027        7256 :                                                      elem); return;
    2028             : 
    2029       56806 :           fe_family_horder_case_func(2, compute_constraints (constraints,
    2030             :                                                              dof_map,
    2031             :                                                              variable_number,
    2032             :                                                              elem), , ; return;)
    2033       48402 :           default:
    2034       48402 :             return;
    2035             :           }
    2036             :       }
    2037             : 
    2038             : 
    2039     3358630 :     case 3:
    2040             :       {
    2041     3358630 :         switch (fe_t.family)
    2042             :           {
    2043         108 :           case HERMITE:
    2044         108 :             FE<3,HERMITE>::compute_constraints (constraints,
    2045             :                                                 dof_map,
    2046             :                                                 variable_number,
    2047         108 :                                                 elem); return;
    2048             : 
    2049     1302461 :           case LAGRANGE:
    2050     1302461 :             FE<3,LAGRANGE>::compute_constraints (constraints,
    2051             :                                                  dof_map,
    2052             :                                                  variable_number,
    2053     1302461 :                                                  elem); return;
    2054             : 
    2055       18972 :           case HIERARCHIC:
    2056       18972 :             FE<3,HIERARCHIC>::compute_constraints (constraints,
    2057             :                                                    dof_map,
    2058             :                                                    variable_number,
    2059       18972 :                                                    elem); return;
    2060             : 
    2061      145056 :           case SIDE_HIERARCHIC:
    2062      145056 :             FE<3,SIDE_HIERARCHIC>::compute_constraints (constraints,
    2063             :                                                         dof_map,
    2064             :                                                         variable_number,
    2065      145056 :                                                         elem); return;
    2066             : 
    2067       11400 :           case LAGRANGE_VEC:
    2068       11400 :             FE<3,LAGRANGE_VEC>::compute_constraints (constraints,
    2069             :                                                      dof_map,
    2070             :                                                      variable_number,
    2071       11400 :                                                      elem); return;
    2072             : 
    2073           0 :           case HIERARCHIC_VEC:
    2074           0 :             FE<3,HIERARCHIC_VEC>::compute_constraints (constraints,
    2075             :                                                        dof_map,
    2076             :                                                        variable_number,
    2077           0 :                                                        elem); return;
    2078             : 
    2079       11224 :           fe_family_horder_case_func(3, compute_constraints (constraints,
    2080             :                                                              dof_map,
    2081             :                                                              variable_number,
    2082             :                                                              elem), , ; return;)
    2083      152358 :           default:
    2084      152358 :             return;
    2085             :           }
    2086             :       }
    2087             : 
    2088             : 
    2089           0 :     default:
    2090           0 :       libmesh_error_msg("Invalid dimension = " << elem->dim());
    2091             :     }
    2092             : }
    2093             : 
    2094             : #endif // #ifdef LIBMESH_ENABLE_AMR
    2095             : 
    2096             : 
    2097             : 
    2098             : #ifdef LIBMESH_ENABLE_PERIODIC
    2099             : 
    2100      264164 : void FEInterface::compute_periodic_constraints (DofConstraints & constraints,
    2101             :                                                 DofMap & dof_map,
    2102             :                                                 const PeriodicBoundaries & boundaries,
    2103             :                                                 const MeshBase & mesh,
    2104             :                                                 const PointLocatorBase * point_locator,
    2105             :                                                 const unsigned int variable_number,
    2106             :                                                 const Elem * elem)
    2107             : {
    2108       67082 :   const FEType & fe_t = dof_map.variable_type(variable_number);
    2109             :   // No element-specific optimizations currently exist, although
    2110             :   // we do have to select the right compute_periodic_constraints
    2111             :   // for the OutputType of this FEType.
    2112      264164 :   switch (field_type(fe_t))
    2113             :   {
    2114      264164 :     case TYPE_SCALAR:
    2115      264164 :       FEBase::compute_periodic_constraints(
    2116             :           constraints, dof_map, boundaries, mesh, point_locator, variable_number, elem);
    2117      264164 :       break;
    2118           0 :     case TYPE_VECTOR:
    2119           0 :       FEVectorBase::compute_periodic_constraints(
    2120             :           constraints, dof_map, boundaries, mesh, point_locator, variable_number, elem);
    2121           0 :       break;
    2122           0 :     default:
    2123           0 :       libmesh_error_msg(
    2124             :           "compute_periodic_constraints only set up for vector or scalar FEFieldTypes");
    2125             :   }
    2126      264164 : }
    2127             : 
    2128             : #endif // #ifdef LIBMESH_ENABLE_PERIODIC
    2129             : 
    2130             : 
    2131             : 
    2132    30703620 : unsigned int FEInterface::max_order(const FEType & fe_t,
    2133             :                                     const ElemType & el_t)
    2134             : {
    2135             :   // Yeah, I know, infinity is much larger than 11, but our
    2136             :   // solvers don't seem to like high degree polynomials, and our
    2137             :   // quadrature rules and number_lookups tables
    2138             :   // need to go up higher.
    2139     1891074 :   const unsigned int unlimited = 11;
    2140             : 
    2141             :   // If we used 0 as a default, then elements missing from this
    2142             :   // table (e.g. infinite elements) would be considered broken.
    2143     1891074 :   const unsigned int unknown = unlimited;
    2144             : 
    2145    30703620 :   switch (fe_t.family)
    2146             :     {
    2147    18640514 :     case LAGRANGE:
    2148             :     case LAGRANGE_VEC:
    2149    18640514 :       switch (el_t)
    2150             :         {
    2151      121774 :         case EDGE2:
    2152             :         case EDGE3:
    2153             :         case EDGE4:
    2154      121774 :           return 3;
    2155      229732 :         case TRI3:
    2156             :         case TRISHELL3:
    2157             :         case C0POLYGON:
    2158      229732 :           return 1;
    2159        7832 :         case TRI6:
    2160        7832 :           return 2;
    2161         760 :         case TRI7:
    2162         760 :           return 3;
    2163      458096 :         case QUAD4:
    2164             :         case QUADSHELL4:
    2165      458096 :           return 1;
    2166      158832 :         case QUAD8:
    2167             :         case QUADSHELL8:
    2168             :         case QUAD9:
    2169             :         case QUADSHELL9:
    2170      158832 :           return 2;
    2171       77660 :         case TET4:
    2172       77660 :           return 1;
    2173        2592 :         case TET10:
    2174        2592 :           return 2;
    2175        2880 :         case TET14:
    2176        2880 :           return 3;
    2177      129832 :         case HEX8:
    2178      129832 :           return 1;
    2179        8420 :         case HEX20:
    2180             :         case HEX27:
    2181        8420 :           return 2;
    2182        4296 :         case PRISM6:
    2183        4296 :           return 1;
    2184        4608 :         case PRISM15:
    2185             :         case PRISM18:
    2186        4608 :           return 2;
    2187        2248 :         case PRISM20:
    2188             :         case PRISM21:
    2189        2248 :           return 3;
    2190        1752 :         case PYRAMID5:
    2191        1752 :           return 1;
    2192         816 :         case PYRAMID13:
    2193             :         case PYRAMID14:
    2194         816 :           return 2;
    2195         264 :         case PYRAMID18:
    2196         264 :           return 3;
    2197          36 :         case C0POLYHEDRON:
    2198          36 :           return 1;
    2199        4716 :         default:
    2200        4716 :           return unknown;
    2201             :         }
    2202             :       break;
    2203      639664 :     case MONOMIAL:
    2204             :     case L2_LAGRANGE:
    2205             :     case L2_LAGRANGE_VEC:
    2206             :     case L2_HIERARCHIC:
    2207             :     case L2_HIERARCHIC_VEC:
    2208             :     case MONOMIAL_VEC:
    2209      319832 :       switch (el_t)
    2210             :         {
    2211      319824 :         case EDGE2:
    2212             :         case EDGE3:
    2213             :         case EDGE4:
    2214             :         case C0POLYGON:
    2215             :         case TRI3:
    2216             :         case TRISHELL3:
    2217             :         case TRI6:
    2218             :         case TRI7:
    2219             :         case QUAD4:
    2220             :         case QUADSHELL4:
    2221             :         case QUAD8:
    2222             :         case QUADSHELL8:
    2223             :         case QUAD9:
    2224             :         case QUADSHELL9:
    2225             :         case TET4:
    2226             :         case TET10:
    2227             :         case TET14:
    2228             :         case HEX8:
    2229             :         case HEX20:
    2230             :         case HEX27:
    2231             :         case PRISM6:
    2232             :         case PRISM15:
    2233             :         case PRISM18:
    2234             :         case PRISM20:
    2235             :         case PRISM21:
    2236             :         case PYRAMID5:
    2237             :         case PYRAMID13:
    2238             :         case PYRAMID14:
    2239             :         case PYRAMID18:
    2240             :         case C0POLYHEDRON:
    2241      319824 :           return unlimited;
    2242           8 :         default:
    2243           8 :           return unknown;
    2244             :         }
    2245             :       break;
    2246             : #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
    2247      327044 :     case BERNSTEIN:
    2248             :     case RATIONAL_BERNSTEIN:
    2249      327044 :       switch (el_t)
    2250             :         {
    2251         216 :         case EDGE2:
    2252             :         case EDGE3:
    2253             :         case EDGE4:
    2254         216 :           return unlimited;
    2255         144 :         case TRI3:
    2256             :         case TRISHELL3:
    2257         144 :           return 1;
    2258         432 :         case TRI6:
    2259             :         case TRI7:
    2260         432 :           return 6;
    2261          72 :         case QUAD4:
    2262             :         case QUADSHELL4:
    2263          72 :           return 1;
    2264        7328 :         case QUAD8:
    2265             :         case QUADSHELL8:
    2266             :         case QUAD9:
    2267             :         case QUADSHELL9:
    2268        7328 :           return unlimited;
    2269        1728 :         case TET4:
    2270        1728 :           return 1;
    2271        1728 :         case TET10:
    2272             :         case TET14:
    2273        1728 :           return 2;
    2274          72 :         case HEX8:
    2275          72 :           return 1;
    2276           0 :         case HEX20:
    2277           0 :           return 2;
    2278        2504 :         case HEX27:
    2279        2504 :           return 4;
    2280           0 :         case C0POLYGON:
    2281             :         case PRISM6:
    2282             :         case PRISM15:
    2283             :         case PRISM18:
    2284             :         case PRISM20:
    2285             :         case PRISM21:
    2286             :         case PYRAMID5:
    2287             :         case PYRAMID13:
    2288             :         case PYRAMID14:
    2289             :         case PYRAMID18:
    2290             :         case C0POLYHEDRON:
    2291           0 :           return 0;
    2292        9668 :         default:
    2293        9668 :           return unknown;
    2294             :         }
    2295             :       break;
    2296        9164 :     case SZABAB:
    2297        9164 :       switch (el_t)
    2298             :         {
    2299          36 :         case EDGE2:
    2300          36 :           return 1;
    2301         108 :         case EDGE3:
    2302             :         case EDGE4:
    2303         108 :           return 7;
    2304          72 :         case TRI3:
    2305             :         case TRISHELL3:
    2306          72 :           return 1;
    2307         496 :         case TRI6:
    2308             :         case TRI7:
    2309         496 :           return 7;
    2310          36 :         case QUAD4:
    2311             :         case QUADSHELL4:
    2312          36 :           return 1;
    2313         108 :         case QUAD8:
    2314             :         case QUADSHELL8:
    2315             :         case QUAD9:
    2316             :         case QUADSHELL9:
    2317         108 :           return 7;
    2318           0 :         case C0POLYGON:
    2319             :         case TET4:
    2320             :         case TET10:
    2321             :         case TET14:
    2322             :         case HEX8:
    2323             :         case HEX20:
    2324             :         case HEX27:
    2325             :         case PRISM6:
    2326             :         case PRISM15:
    2327             :         case PRISM18:
    2328             :         case PRISM20:
    2329             :         case PRISM21:
    2330             :         case PYRAMID5:
    2331             :         case PYRAMID13:
    2332             :         case PYRAMID14:
    2333             :         case PYRAMID18:
    2334             :         case C0POLYHEDRON:
    2335           0 :           return 0;
    2336           0 :         default:
    2337           0 :           return unknown;
    2338             :         }
    2339             :       break;
    2340             : #endif
    2341       44448 :     case XYZ:
    2342       22224 :       switch (el_t)
    2343             :         {
    2344       22224 :         case EDGE2:
    2345             :         case EDGE3:
    2346             :         case EDGE4:
    2347             :         case C0POLYGON:
    2348             :         case TRI3:
    2349             :         case TRISHELL3:
    2350             :         case TRI6:
    2351             :         case TRI7:
    2352             :         case QUAD4:
    2353             :         case QUADSHELL4:
    2354             :         case QUAD8:
    2355             :         case QUADSHELL8:
    2356             :         case QUAD9:
    2357             :         case QUADSHELL9:
    2358             :         case TET4:
    2359             :         case TET10:
    2360             :         case TET14:
    2361             :         case HEX8:
    2362             :         case HEX20:
    2363             :         case HEX27:
    2364             :         case PRISM6:
    2365             :         case PRISM15:
    2366             :         case PRISM18:
    2367             :         case PRISM20:
    2368             :         case PRISM21:
    2369             :         case PYRAMID5:
    2370             :         case PYRAMID13:
    2371             :         case PYRAMID14:
    2372             :         case PYRAMID18:
    2373             :         case C0POLYHEDRON:
    2374       22224 :           return unlimited;
    2375           0 :         default:
    2376           0 :           return unknown;
    2377             :         }
    2378             :       break;
    2379      111862 :     case CLOUGH:
    2380      111862 :       switch (el_t)
    2381             :         {
    2382           0 :         case EDGE2:
    2383             :         case EDGE3:
    2384           0 :           return 3;
    2385           0 :         case EDGE4:
    2386             :         case TRI3:
    2387             :         case TRISHELL3:
    2388           0 :           return 0;
    2389        9836 :         case TRI6:
    2390             :         case TRI7:
    2391        9836 :           return 3;
    2392           0 :         case C0POLYGON:
    2393             :         case QUAD4:
    2394             :         case QUADSHELL4:
    2395             :         case QUAD8:
    2396             :         case QUADSHELL8:
    2397             :         case QUAD9:
    2398             :         case QUADSHELL9:
    2399             :         case TET4:
    2400             :         case TET10:
    2401             :         case TET14:
    2402             :         case HEX8:
    2403             :         case HEX20:
    2404             :         case HEX27:
    2405             :         case PRISM6:
    2406             :         case PRISM15:
    2407             :         case PRISM18:
    2408             :         case PRISM20:
    2409             :         case PRISM21:
    2410             :         case PYRAMID5:
    2411             :         case PYRAMID13:
    2412             :         case PYRAMID14:
    2413             :         case PYRAMID18:
    2414             :         case C0POLYHEDRON:
    2415           0 :           return 0;
    2416           0 :         default:
    2417           0 :           return unknown;
    2418             :         }
    2419             :       break;
    2420      666632 :     case HERMITE:
    2421      666632 :       switch (el_t)
    2422             :         {
    2423       21120 :         case EDGE2:
    2424             :         case EDGE3:
    2425       21120 :           return unlimited;
    2426           0 :         case EDGE4:
    2427             :         case TRI3:
    2428             :         case TRISHELL3:
    2429             :         case TRI6:
    2430             :         case TRI7:
    2431           0 :           return 0;
    2432           0 :         case QUAD4:
    2433             :         case QUADSHELL4:
    2434           0 :           return 3;
    2435        4564 :         case QUAD8:
    2436             :         case QUADSHELL8:
    2437             :         case QUAD9:
    2438             :         case QUADSHELL9:
    2439        4564 :           return unlimited;
    2440           0 :         case TET4:
    2441             :         case TET10:
    2442             :         case TET14:
    2443           0 :           return 0;
    2444           0 :         case HEX8:
    2445           0 :           return 3;
    2446          36 :         case HEX20:
    2447             :         case HEX27:
    2448          36 :           return unlimited;
    2449           0 :         case C0POLYGON:
    2450             :         case PRISM6:
    2451             :         case PRISM15:
    2452             :         case PRISM18:
    2453             :         case PRISM20:
    2454             :         case PRISM21:
    2455             :         case PYRAMID5:
    2456             :         case PYRAMID13:
    2457             :         case PYRAMID14:
    2458             :         case PYRAMID18:
    2459             :         case C0POLYHEDRON:
    2460           0 :           return 0;
    2461           0 :         default:
    2462           0 :           return unknown;
    2463             :         }
    2464             :       break;
    2465     2742464 :     case HIERARCHIC:
    2466             :     case HIERARCHIC_VEC:
    2467     2742464 :       switch (el_t)
    2468             :         {
    2469         792 :         case EDGE2:
    2470             :         case EDGE3:
    2471             :         case EDGE4:
    2472         792 :           return unlimited;
    2473          72 :         case TRI3:
    2474             :         case TRISHELL3:
    2475          72 :           return 1;
    2476       27352 :         case TRI6:
    2477             :         case TRI7:
    2478       27352 :           return unlimited;
    2479          36 :         case QUAD4:
    2480             :         case QUADSHELL4:
    2481          36 :           return 1;
    2482       42004 :         case QUAD8:
    2483             :         case QUADSHELL8:
    2484             :         case QUAD9:
    2485             :         case QUADSHELL9:
    2486       42004 :           return unlimited;
    2487         864 :         case TET4:
    2488         864 :           return 1;
    2489         864 :         case TET10:
    2490         864 :           return 2;
    2491        1728 :         case TET14:
    2492        1728 :           return unlimited;
    2493          36 :         case HEX8:
    2494             :         case HEX20:
    2495          36 :           return 1;
    2496        2156 :         case HEX27:
    2497        2156 :           return unlimited;
    2498         648 :         case PRISM6:
    2499             :         case PRISM15:
    2500             :         case PRISM18:
    2501             :         case PRISM20:
    2502             :         case PRISM21:
    2503         648 :           return unlimited;
    2504           0 :         case C0POLYGON:
    2505             :         case PYRAMID5:
    2506             :         case PYRAMID13:
    2507             :         case PYRAMID14:
    2508             :         case PYRAMID18:
    2509             :         case C0POLYHEDRON:
    2510           0 :           return 0;
    2511           0 :         default:
    2512           0 :           return unknown;
    2513             :         }
    2514             :       break;
    2515     1155836 :     case SIDE_HIERARCHIC:
    2516     1155836 :       switch (el_t)
    2517             :         {
    2518         264 :         case EDGE2:
    2519             :         case EDGE3:
    2520             :         case EDGE4:
    2521         264 :           return unlimited; // although it's all the same as 0...
    2522           0 :         case TRI3:
    2523             :         case TRISHELL3:
    2524           0 :           return 0;
    2525       18568 :         case TRI6:
    2526             :         case TRI7:
    2527       18568 :           return unlimited;
    2528           0 :         case C0POLYGON:
    2529             :         case QUAD4:
    2530             :         case QUADSHELL4:
    2531           0 :           return 0;
    2532        2728 :         case QUAD8:
    2533             :         case QUADSHELL8:
    2534             :         case QUAD9:
    2535             :         case QUADSHELL9:
    2536        2728 :           return unlimited;
    2537           0 :         case TET4:
    2538             :         case TET10:
    2539           0 :           return 0;
    2540       43776 :         case TET14:
    2541       43776 :           return unlimited;
    2542           0 :         case HEX8:
    2543             :         case HEX20:
    2544           0 :           return 0;
    2545        1376 :         case HEX27:
    2546        1376 :           return unlimited;
    2547           0 :         case PRISM6:
    2548             :         case PRISM15:
    2549             :         case PRISM18:
    2550           0 :           return 0;
    2551        3200 :         case PRISM20:
    2552             :         case PRISM21:
    2553        3200 :           return unlimited;
    2554           0 :         case PYRAMID5:
    2555             :         case PYRAMID13:
    2556             :         case PYRAMID14:
    2557             :         case PYRAMID18:
    2558             :         case C0POLYHEDRON:
    2559           0 :           return 0;
    2560           0 :         default:
    2561           0 :           return unknown;
    2562             :         }
    2563             :       break;
    2564        2592 :     case SUBDIVISION:
    2565        1296 :       switch (el_t)
    2566             :         {
    2567        1296 :         case TRI3SUBDIVISION:
    2568        1296 :           return unlimited;
    2569           0 :         default:
    2570           0 :           return unknown;
    2571             :         }
    2572             :       break;
    2573      386618 :     case NEDELEC_ONE:
    2574      386618 :       switch (el_t)
    2575             :         {
    2576       11632 :         case TRI6:
    2577             :         case TRI7:
    2578             :         case QUAD8:
    2579             :         case QUAD9:
    2580       11632 :           return 5;
    2581        6400 :         case TET10:
    2582             :         case TET14:
    2583             :         case HEX20:
    2584             :         case HEX27:
    2585        6400 :           return 1;
    2586           0 :         default:
    2587           0 :           return 0;
    2588             :         }
    2589             :       break;
    2590     1514630 :     case RAVIART_THOMAS:
    2591             :     case L2_RAVIART_THOMAS:
    2592     1514630 :       switch (el_t)
    2593             :         {
    2594       33200 :         case TRI6:
    2595             :         case TRI7:
    2596             :         case QUAD8:
    2597             :         case QUAD9:
    2598       33200 :           return 5;
    2599       74872 :         case TET14:
    2600             :         case HEX27:
    2601       74872 :           return 1;
    2602           0 :         default:
    2603           0 :           return 0;
    2604             :         }
    2605             :       break;
    2606           0 :     default:
    2607           0 :       return 0;
    2608             :       break;
    2609             :     }
    2610             : }
    2611             : 
    2612             : 
    2613             : 
    2614   319119051 : bool FEInterface::extra_hanging_dofs(const FEType & fe_t)
    2615             : {
    2616   319119051 :   switch (fe_t.family)
    2617             :     {
    2618    19600450 :     case LAGRANGE:
    2619             :     case L2_LAGRANGE:
    2620             :     case MONOMIAL:
    2621             :     case MONOMIAL_VEC:
    2622             :     case L2_HIERARCHIC:
    2623             :     case SIDE_HIERARCHIC:
    2624             :     case XYZ:
    2625             :     case SUBDIVISION:
    2626             :     case LAGRANGE_VEC:
    2627             :     case L2_LAGRANGE_VEC:
    2628             :     case NEDELEC_ONE:
    2629             :     case RAVIART_THOMAS:
    2630             :     case L2_RAVIART_THOMAS:
    2631    19600450 :       return false;
    2632    91722383 :     case CLOUGH:
    2633             :     case HERMITE:
    2634             :     case HIERARCHIC:
    2635             :     case HIERARCHIC_VEC:
    2636             :     case L2_HIERARCHIC_VEC:
    2637             :     fe_family_horder_case()
    2638             :     default:
    2639    91722383 :       return true;
    2640             :     }
    2641             : }
    2642             : 
    2643     2744016 : FEFieldType FEInterface::field_type(const FEType & fe_type)
    2644             : {
    2645     2744016 :   return FEInterface::field_type(fe_type.family);
    2646             : }
    2647             : 
    2648    33901137 : FEFieldType FEInterface::field_type (const FEFamily & fe_family)
    2649             : {
    2650    33901137 :   switch (fe_family)
    2651             :     {
    2652        8252 :     fe_family_vector_case()
    2653        8252 :       return TYPE_VECTOR;
    2654    33617257 :     default:
    2655    33617257 :       return TYPE_SCALAR;
    2656             :     }
    2657             : }
    2658             : 
    2659   123853334 : bool FEInterface::orientation_dependent (const FEFamily & fe_family)
    2660             : {
    2661   123853334 :   switch (fe_family)
    2662             :     {
    2663      602922 :     case HIERARCHIC:
    2664             :     case L2_HIERARCHIC:
    2665             :     case HIERARCHIC_VEC:
    2666             :     case L2_HIERARCHIC_VEC:
    2667             :     case BERNSTEIN:
    2668             :     case RATIONAL_BERNSTEIN:
    2669             :     case SZABAB:
    2670             :     case NEDELEC_ONE:
    2671             :     case RAVIART_THOMAS:
    2672      602922 :       return true;
    2673   106627118 :     default:
    2674   106627118 :       return false;
    2675             :     }
    2676             : }
    2677             : 
    2678    30984266 : unsigned int FEInterface::n_vec_dim (const MeshBase & mesh,
    2679             :                                      const FEType & fe_type)
    2680             : {
    2681             :   // We assume the number of vector components is the mesh spatial dimension.
    2682    30984266 :   return field_type(fe_type.family) == TYPE_VECTOR ? mesh.spatial_dimension() : 1;
    2683             : }
    2684             : 
    2685             : 
    2686             : 
    2687             : 
    2688             : bool
    2689        6372 : FEInterface::is_hierarchic (const FEType & fe_type)
    2690             : {
    2691        6372 :   switch (fe_type.family)
    2692             :     {
    2693         284 :     case HERMITE:
    2694             :     case HIERARCHIC:
    2695             :     case HIERARCHIC_VEC:
    2696             :     case L2_HIERARCHIC:
    2697             :     case L2_HIERARCHIC_VEC:
    2698             :     case MONOMIAL:
    2699             :     case MONOMIAL_VEC:
    2700             :     case SIDE_HIERARCHIC:
    2701             :     case SZABAB:
    2702             :     case XYZ:
    2703         284 :       return true;
    2704             : 
    2705        2248 :     case BERNSTEIN:
    2706             :     case CLOUGH:  // maybe some day?
    2707             :     case LAGRANGE:
    2708             :     case LAGRANGE_VEC:
    2709             :     case L2_LAGRANGE:
    2710             :     case L2_LAGRANGE_VEC:
    2711             :     case NEDELEC_ONE:
    2712             :     case RATIONAL_BERNSTEIN:
    2713             :     case RAVIART_THOMAS:
    2714             :     case L2_RAVIART_THOMAS:
    2715             :     case SCALAR:
    2716             :     case SUBDIVISION:
    2717        2248 :       return false;
    2718             : 
    2719           0 :     default:
    2720           0 :       libmesh_error_msg("Unknown FE Family " << Utility::enum_to_string(fe_type.family));
    2721             :     }
    2722             : }
    2723             : 
    2724             : 
    2725             : 
    2726    14875954 : FEContinuity FEInterface::get_continuity(const FEType & fe_type)
    2727             : {
    2728    14875954 :   switch (fe_type.family)
    2729             :     {
    2730             :       // Discontinuous elements
    2731        8098 :     case MONOMIAL:
    2732             :     case MONOMIAL_VEC:
    2733             :     case L2_HIERARCHIC:
    2734             :     case L2_LAGRANGE:
    2735             :     case XYZ:
    2736             :     case SCALAR:
    2737             :     case L2_RAVIART_THOMAS:
    2738             :     case L2_HIERARCHIC_VEC:
    2739             :     case L2_LAGRANGE_VEC:
    2740        8098 :       return DISCONTINUOUS;
    2741             : 
    2742             :       // C0 elements
    2743    14513904 :     case LAGRANGE:
    2744             :     case HIERARCHIC:
    2745             :     case BERNSTEIN:
    2746             :     case SZABAB:
    2747             :     case RATIONAL_BERNSTEIN:
    2748             :     case INFINITE_MAP:
    2749             :     case JACOBI_20_00:
    2750             :     case JACOBI_30_00:
    2751             :     case LEGENDRE:
    2752             :     case LAGRANGE_VEC:
    2753             :     case HIERARCHIC_VEC:
    2754    14513904 :       return C_ZERO;
    2755             : 
    2756             :       // C1 elements
    2757       28012 :     case CLOUGH:
    2758             :     case HERMITE:
    2759             :     case SUBDIVISION:
    2760       28012 :       return C_ONE;
    2761             : 
    2762        3536 :     case NEDELEC_ONE:
    2763        3536 :       return H_CURL;
    2764             : 
    2765        6720 :     case RAVIART_THOMAS:
    2766        6720 :       return H_DIV;
    2767             : 
    2768             :       // Side elements
    2769       47194 :     case SIDE_HIERARCHIC:
    2770       47194 :       return SIDE_DISCONTINUOUS;
    2771             : 
    2772           0 :     default:
    2773           0 :       libmesh_error_msg("Unknown FE Family " << Utility::enum_to_string(fe_type.family));
    2774             :     }
    2775             : }
    2776             : 
    2777             : 
    2778             : } // namespace libMesh

Generated by: LCOV version 1.14