LCOV - code coverage report
Current view: top level - src/fe - fe_interface.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 447 931 48.0 %
Date: 2025-08-19 19:27:09 Functions: 40 71 56.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14