LCOV - code coverage report
Current view: top level - include/fe - fe.h (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 48 64 75.0 %
Date: 2025-08-19 19:27:09 Functions: 145 895 16.2 %
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             : #ifndef LIBMESH_FE_H
      21             : #define LIBMESH_FE_H
      22             : 
      23             : // Local includes
      24             : #include "libmesh/fe_base.h"
      25             : #include "libmesh/int_range.h"
      26             : #include "libmesh/libmesh.h"
      27             : 
      28             : // C++ includes
      29             : #include <cstddef>
      30             : 
      31             : namespace libMesh
      32             : {
      33             : 
      34             : // forward declarations
      35             : class DofConstraints;
      36             : class DofMap;
      37             : class QGauss;
      38             : 
      39             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
      40             : 
      41             : template <unsigned int friend_Dim, FEFamily friend_T_radial, InfMapType friend_T_map>
      42             : class InfFE;
      43             : 
      44             : #endif
      45             : 
      46             : 
      47             : /**
      48             :  * Most finite element types in libMesh are scalar-valued
      49             :  */
      50             : template <FEFamily T>
      51             : struct FEOutputType
      52             : {
      53             :   typedef Real type;
      54             : };
      55             : 
      56             : 
      57             : /**
      58             :  * Specialize for non-scalar-valued elements
      59             :  */
      60             : template<>
      61             : struct FEOutputType<LAGRANGE_VEC>
      62             : {
      63             :   typedef RealVectorValue type;
      64             : };
      65             : 
      66             : template<>
      67             : struct FEOutputType<L2_LAGRANGE_VEC>
      68             : {
      69             :   typedef RealVectorValue type;
      70             : };
      71             : 
      72             : template<>
      73             : struct FEOutputType<HIERARCHIC_VEC>
      74             : {
      75             :   typedef RealVectorValue type;
      76             : };
      77             : 
      78             : template<>
      79             : struct FEOutputType<L2_HIERARCHIC_VEC>
      80             : {
      81             :   typedef RealVectorValue type;
      82             : };
      83             : 
      84             : template<>
      85             : struct FEOutputType<NEDELEC_ONE>
      86             : {
      87             :   typedef RealVectorValue type;
      88             : };
      89             : 
      90             : template<>
      91             : struct FEOutputType<MONOMIAL_VEC>
      92             : {
      93             :   typedef RealVectorValue type;
      94             : };
      95             : 
      96             : template<>
      97             : struct FEOutputType<RAVIART_THOMAS>
      98             : {
      99             :   typedef RealVectorValue type;
     100             : };
     101             : 
     102             : template<>
     103             : struct FEOutputType<L2_RAVIART_THOMAS>
     104             : {
     105             :   typedef RealVectorValue type;
     106             : };
     107             : 
     108             : 
     109             : /**
     110             :  * A specific instantiation of the \p FEBase class. This
     111             :  * class is templated, and specific template instantiations
     112             :  * will result in different Finite Element families. Full specialization
     113             :  * of the template for specific dimensions(\p Dim) and families
     114             :  * (\p T) provide support for specific finite element types.
     115             :  * The use of templates allows for compile-time optimization,
     116             :  * however it requires that the specific finite element family
     117             :  * and dimension is also known at compile time.  If this is
     118             :  * too restricting for your application you can use the
     119             :  * \p FEBase::build() member to create abstract (but still optimized)
     120             :  * finite elements.
     121             :  *
     122             :  * \author Benjamin S. Kirk
     123             :  * \date 2002-2007
     124             :  * \brief Template class which generates the different FE families and orders.
     125             :  */
     126             : template <unsigned int Dim, FEFamily T>
     127             : class FE : public FEGenericBase<typename FEOutputType<T>::type>
     128             : {
     129             : public:
     130             : 
     131             :   /**
     132             :    * Constructor.
     133             :    */
     134             :   explicit
     135             :   FE(const FEType & fet);
     136             : 
     137             :   typedef typename
     138             :   FEGenericBase<typename FEOutputType<T>::type>::OutputShape
     139             :   OutputShape;
     140             : 
     141             :   /**
     142             :    * \returns The value of the \f$ i^{th} \f$ shape function at
     143             :    * point \p p.  This method allows you to specify the dimension,
     144             :    * element type, and order directly.  This allows the method to
     145             :    * be static.
     146             :    *
     147             :    * On a p-refined element, \p o should be the total order of the element.
     148             :    */
     149             :   static OutputShape shape(const ElemType t,
     150             :                            const Order o,
     151             :                            const unsigned int i,
     152             :                            const Point & p);
     153             : 
     154             :   /**
     155             :    * \returns The value of the \f$ i^{th} \f$ shape function at
     156             :    * point \p p.  This method allows you to specify the dimension,
     157             :    * element type, and order directly.  This allows the method to
     158             :    * be static.
     159             :    *
     160             :    * On a p-refined element, \p o should be the base order of the
     161             :    * element if \p add_p_level is left \p true, or can be the base
     162             :    * order of the element if \p add_p_level is set to \p false.
     163             :    */
     164             :   static OutputShape shape(const Elem * elem,
     165             :                            const Order o,
     166             :                            const unsigned int i,
     167             :                            const Point & p,
     168             :                            const bool add_p_level = true);
     169             : 
     170             :   /**
     171             :    * \returns The value of the \f$ i^{th} \f$ shape function at
     172             :    * point \p p.  This method allows you to specify the dimension and
     173             :    * element type directly. The order is given by the FEType.
     174             :    * This allows the method to be static.
     175             :    *
     176             :    * On a p-refined element, \p o should be the base order of the
     177             :    * element if \p add_p_level is left \p true, or can be the base
     178             :    * order of the element if \p add_p_level is set to \p false.
     179             :    */
     180             :    static OutputShape shape(const FEType fet,
     181             :                             const Elem * elem,
     182             :                             const unsigned int i,
     183             :                             const Point & p,
     184             :                             const bool add_p_level = true);
     185             : 
     186             :   /**
     187             :    * Fills \p v with the values of the \f$ i^{th} \f$
     188             :    * shape function, evaluated at all points p.  You must specify
     189             :    * element order directly.  \p v should already be the appropriate
     190             :    * size.
     191             :    *
     192             :    * On a p-refined element, \p o should be the base order of the
     193             :    * element if \p add_p_level is left \p true, or can be the base
     194             :    * order of the element if \p add_p_level is set to \p false.
     195             :    */
     196             :   static void shapes(const Elem * elem,
     197             :                      const Order o,
     198             :                      const unsigned int i,
     199             :                      const std::vector<Point> & p,
     200             :                      std::vector<OutputShape> & v,
     201             :                      const bool add_p_level = true);
     202             : 
     203             : 
     204             :   /**
     205             :    * Fills \p v[i][qp] with the values of the \f$ i^{th} \f$
     206             :    * shape functions, evaluated at all points in p.  You must specify
     207             :    * element order directly.  \p v should already be the appropriate
     208             :    * size.
     209             :    *
     210             :    * On a p-refined element, \p o should be the base order of the
     211             :    * element if \p add_p_level is left \p true, or can be the base
     212             :    * order of the element if \p add_p_level is set to \p false.
     213             :    */
     214             :   static void all_shapes(const Elem * elem,
     215             :                          const Order o,
     216             :                          const std::vector<Point> & p,
     217             :                          std::vector<std::vector<OutputShape> > & v,
     218             :                          const bool add_p_level = true);
     219             : 
     220             :   /**
     221             :    * \returns The \f$ j^{th} \f$ derivative of the \f$ i^{th} \f$
     222             :    * shape function at point \p p.  This method allows you to
     223             :    * specify the dimension, element type, and order directly.
     224             :    *
     225             :    * On a p-refined element, \p o should be the total order of the element.
     226             :    */
     227             :   static OutputShape shape_deriv(const ElemType t,
     228             :                                  const Order o,
     229             :                                  const unsigned int i,
     230             :                                  const unsigned int j,
     231             :                                  const Point & p);
     232             : 
     233             :   /**
     234             :    * \returns The \f$ j^{th} \f$ derivative of the \f$ i^{th} \f$
     235             :    * shape function.  You must specify element type, and order directly.
     236             :    *
     237             :    * On a p-refined element, \p o should be the base order of the
     238             :    * element if \p add_p_level is left \p true, or can be the base
     239             :    * order of the element if \p add_p_level is set to \p false.
     240             :    */
     241             :   static OutputShape shape_deriv(const Elem * elem,
     242             :                                  const Order o,
     243             :                                  const unsigned int i,
     244             :                                  const unsigned int j,
     245             :                                  const Point & p,
     246             :                                  const bool add_p_level = true);
     247             : 
     248             :   /**
     249             :    * \returns The \f$ j^{th} \f$ derivative of the \f$ i^{th} \f$
     250             :    * shape function.  You must specify element type, and order (via
     251             :    * FEType) directly.
     252             :    *
     253             :    * On a p-refined element, \p o should be the base order of the
     254             :    * element if \p add_p_level is left \p true, or can be the base
     255             :    * order of the element if \p add_p_level is set to \p false.
     256             :    */
     257             :   static OutputShape shape_deriv(const FEType fet,
     258             :                                  const Elem * elem,
     259             :                                  const unsigned int i,
     260             :                                  const unsigned int j,
     261             :                                  const Point & p,
     262             :                                  const bool add_p_level = true);
     263             : 
     264             :   /**
     265             :    * Fills \p v with the \f$ j^{th} \f$ derivative of the \f$ i^{th} \f$
     266             :    * shape function, evaluated at all points p.  You must specify
     267             :    * element order directly.  \p v should already be the appropriate
     268             :    * size.
     269             :    *
     270             :    * On a p-refined element, \p o should be the base order of the
     271             :    * element if \p add_p_level is left \p true, or can be the base
     272             :    * order of the element if \p add_p_level is set to \p false.
     273             :    */
     274             :   static void shape_derivs(const Elem * elem,
     275             :                            const Order o,
     276             :                            const unsigned int i,
     277             :                            const unsigned int j,
     278             :                            const std::vector<Point> & p,
     279             :                            std::vector<OutputShape> & v,
     280             :                            const bool add_p_level = true);
     281             : 
     282             :   /**
     283             :    * Fills \p comps with dphidxi (and in higher dimensions, eta/zeta)
     284             :    * derivative component values for all shape functions, evaluated at
     285             :    * all points in p.  You must specify element order directly.
     286             :    * Output component arrays in \p comps should already be the
     287             :    * appropriate size.
     288             :    *
     289             :    * On a p-refined element, \p o should be the base order of the
     290             :    * element if \p add_p_level is left \p true, or can be the base
     291             :    * order of the element if \p add_p_level is set to \p false.
     292             :    */
     293             :   static void all_shape_derivs(const Elem * elem,
     294             :                                const Order o,
     295             :                                const std::vector<Point> & p,
     296             :                                std::vector<std::vector<OutputShape>> * comps[3],
     297             :                                const bool add_p_level = true);
     298             : 
     299             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     300             :   /**
     301             :    * \returns The second \f$ j^{th} \f$ derivative of the \f$ i^{th} \f$
     302             :    * shape function at the point \p p.
     303             :    *
     304             :    * \note Cross-derivatives are indexed according to:
     305             :    * j = 0 ==> d^2 phi / dxi^2
     306             :    * j = 1 ==> d^2 phi / dxi deta
     307             :    * j = 2 ==> d^2 phi / deta^2
     308             :    * j = 3 ==> d^2 phi / dxi dzeta
     309             :    * j = 4 ==> d^2 phi / deta dzeta
     310             :    * j = 5 ==> d^2 phi / dzeta^2
     311             :    *
     312             :    * \note Computing second derivatives is not currently supported for
     313             :    * all element types: \f$ C^1 \f$ (Clough, Hermite and Subdivision),
     314             :    * Lagrange, Hierarchic, L2_Hierarchic, and Monomial are supported.
     315             :    * All other element types return an error when asked for second
     316             :    * derivatives.
     317             :    *
     318             :    * On a p-refined element, \p o should be the total order of the element.
     319             :    */
     320             :   static OutputShape shape_second_deriv(const ElemType t,
     321             :                                         const Order o,
     322             :                                         const unsigned int i,
     323             :                                         const unsigned int j,
     324             :                                         const Point & p);
     325             : 
     326             :   /**
     327             :    * \returns The second \f$ j^{th} \f$ derivative of the \f$ i^{th} \f$
     328             :    * shape function at the point \p p.
     329             :    *
     330             :    * \note Cross-derivatives are indexed according to:
     331             :    * j = 0 ==> d^2 phi / dxi^2
     332             :    * j = 1 ==> d^2 phi / dxi deta
     333             :    * j = 2 ==> d^2 phi / deta^2
     334             :    * j = 3 ==> d^2 phi / dxi dzeta
     335             :    * j = 4 ==> d^2 phi / deta dzeta
     336             :    * j = 5 ==> d^2 phi / dzeta^2
     337             :    *
     338             :    * \note Computing second derivatives is not currently supported for
     339             :    * all element types: \f$ C^1 \f$ (Clough, Hermite and Subdivision),
     340             :    * Lagrange, Hierarchic, L2_Hierarchic, and Monomial are supported.
     341             :    * All other element types return an error when asked for second
     342             :    * derivatives.
     343             :    *
     344             :    * On a p-refined element, \p o should be the base order of the
     345             :    * element if \p add_p_level is left \p true, or can be the base
     346             :    * order of the element if \p add_p_level is set to \p false.
     347             :    */
     348             :   static OutputShape shape_second_deriv(const Elem * elem,
     349             :                                         const Order o,
     350             :                                         const unsigned int i,
     351             :                                         const unsigned int j,
     352             :                                         const Point & p,
     353             :                                         const bool add_p_level = true);
     354             : 
     355             :   /**
     356             :    * \returns The second \f$ j^{th} \f$ derivative of the \f$ i^{th} \f$
     357             :    * shape function at the point \p p.
     358             :    *
     359             :    * \note Cross-derivatives are indexed according to:
     360             :    * j = 0 ==> d^2 phi / dxi^2
     361             :    * j = 1 ==> d^2 phi / dxi deta
     362             :    * j = 2 ==> d^2 phi / deta^2
     363             :    * j = 3 ==> d^2 phi / dxi dzeta
     364             :    * j = 4 ==> d^2 phi / deta dzeta
     365             :    * j = 5 ==> d^2 phi / dzeta^2
     366             :    *
     367             :    * \note Computing second derivatives is not currently supported for
     368             :    * all element types: \f$ C^1 \f$ (Clough, Hermite and Subdivision),
     369             :    * Lagrange, Hierarchic, L2_Hierarchic, and Monomial are supported.
     370             :    * All other element types return an error when asked for second
     371             :    * derivatives.
     372             :    *
     373             :    * On a p-refined element, \p o should be the total order of the element.
     374             :    */
     375             :   static OutputShape shape_second_deriv(const FEType fet,
     376             :                                         const Elem * elem,
     377             :                                         const unsigned int i,
     378             :                                         const unsigned int j,
     379             :                                         const Point & p,
     380             :                                         const bool add_p_level = true);
     381             : 
     382             : #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES
     383             :   /**
     384             :    * Build the nodal soln from the element soln.
     385             :    * This is the solution that will be plotted.
     386             :    *
     387             :    * On a p-refined element, \p o should be the base order of the element.
     388             :    */
     389             :   static void nodal_soln(const Elem * elem, const Order o,
     390             :                          const std::vector<Number> & elem_soln,
     391             :                          std::vector<Number> & nodal_soln,
     392             :                          bool add_p_level = true,
     393             :                          const unsigned vdim = 1);
     394             : 
     395             :   /**
     396             :    * Build the nodal soln on one side from the (full) element soln.
     397             :    * This is the solution that will be plotted on side-elements.
     398             :    *
     399             :    * On a p-refined element, \p o should be the base order of the element.
     400             :    */
     401             :   static void side_nodal_soln(const Elem * elem, const Order o,
     402             :                               const unsigned int side,
     403             :                               const std::vector<Number> & elem_soln,
     404             :                               std::vector<Number> & nodal_soln_on_side,
     405             :                               bool add_p_level = true,
     406             :                               const unsigned vdim = 1);
     407             : 
     408             :   /**
     409             :    * \returns The number of shape functions associated with
     410             :    * this finite element.
     411             :    */
     412             :   virtual unsigned int n_shape_functions () const override;
     413             : 
     414             :   /**
     415             :    * \returns The number of shape functions associated with
     416             :    * a finite element of type \p t and approximation order \p o.
     417             :    *
     418             :    * On a p-refined element, \p o should be the total order of the element.
     419             :    *
     420             :    * This method does not support all finite element types; e.g. for an
     421             :    * arbitrary polygon or polyhedron type the number of shape
     422             :    * functions may depend on an individual element and not just its
     423             :    * type.
     424             :    */
     425           0 :   static unsigned int n_shape_functions (const ElemType t,
     426             :                                          const Order o)
     427        1390 :   { return FE<Dim,T>::n_dofs (t,o); }
     428             : 
     429             :   /**
     430             :    * \returns The number of shape functions associated with this
     431             :    * finite element.
     432             :    *
     433             :    * On a p-refined element, \p o should be the total order of the element.
     434             :    *
     435             :    * This method does not support all finite element types; e.g. for an
     436             :    * arbitrary polygon or polyhedron type the number of shape
     437             :    * functions may depend on an individual element and not just its
     438             :    * type.
     439             :    */
     440             :   static unsigned int n_dofs(const ElemType t,
     441             :                              const Order o);
     442             : 
     443             :   /**
     444             :    * \returns The number of shape functions associated with this
     445             :    * finite element.
     446             :    *
     447             :    * On a p-refined element, \p o should be the total order of the element.
     448             :    *
     449             :    * \p e should only be a null pointer if using a FE family like
     450             :    * SCALAR that has degrees of freedom independent of any element.
     451             :    */
     452             :   static unsigned int n_dofs(const Elem * e,
     453             :                              const Order o);
     454             : 
     455             :   /**
     456             :    * \returns The number of dofs at node \p n for a finite element
     457             :    * of type \p t and order \p o.
     458             :    *
     459             :    * On a p-refined element, \p o should be the total order of the element.
     460             :    *
     461             :    * This method does not support all finite element types; e.g. for an
     462             :    * arbitrary polygon or polyhedron type the meaning of a node index
     463             :    * \p n may depend on an individual element and not just its type.
     464             :    */
     465             :   static unsigned int n_dofs_at_node(const ElemType t,
     466             :                                      const Order o,
     467             :                                      const unsigned int n);
     468             : 
     469             :   /**
     470             :    * \returns The number of dofs at node \p n for a finite element
     471             :    * of type \p t and order \p o.
     472             :    *
     473             :    * On a p-refined element, \p o should be the total order of the element.
     474             :    */
     475             :   static unsigned int n_dofs_at_node(const Elem & e,
     476             :                                      const Order o,
     477             :                                      const unsigned int n);
     478             : 
     479             :   /**
     480             :    * \returns The number of dofs interior to the element,
     481             :    * not associated with any interior nodes.
     482             :    *
     483             :    * On a p-refined element, \p o should be the total order of the element.
     484             :    *
     485             :    * This method may not support all finite element types, e.g. higher
     486             :    * order polygons or polyhedra may differ from element to element.
     487             :    */
     488             :   static unsigned int n_dofs_per_elem(const ElemType t,
     489             :                                       const Order o);
     490             : 
     491             :   /**
     492             :    * \returns The number of dofs interior to the element,
     493             :    * not associated with any interior nodes.
     494             :    *
     495             :    * On a p-refined element, \p o should be the total order of the element.
     496             :    */
     497             :   static unsigned int n_dofs_per_elem(const Elem & e,
     498             :                                       const Order o);
     499             : 
     500             :   /**
     501             :    * \returns The continuity level of the finite element.
     502             :    */
     503             :   virtual FEContinuity get_continuity() const override;
     504             : 
     505             :   /**
     506             :    * \returns \p true if the finite element's higher order shape functions are
     507             :    * hierarchic
     508             :    */
     509             :   virtual bool is_hierarchic() const override;
     510             : 
     511             :   /**
     512             :    * Fills the vector di with the local degree of freedom indices
     513             :    * associated with side \p s of element \p elem
     514             :    *
     515             :    * On a p-refined element, \p o should be the base order of the element.
     516             :    */
     517             :   static void dofs_on_side(const Elem * const elem,
     518             :                            const Order o,
     519             :                            unsigned int s,
     520             :                            std::vector<unsigned int> & di,
     521             :                            bool add_p_level=true);
     522             :   /**
     523             :    * Fills the vector di with the local degree of freedom indices
     524             :    * associated with edge \p e of element \p elem
     525             :    *
     526             :    * On a p-refined element, \p o should be the base order of the element.
     527             :    */
     528             :   static void dofs_on_edge(const Elem * const elem,
     529             :                            const Order o,
     530             :                            unsigned int e,
     531             :                            std::vector<unsigned int> & di,
     532             :                            bool add_p_level=true);
     533             : 
     534           0 :   static Point inverse_map (const Elem * elem,
     535             :                             const Point & p,
     536             :                             const Real tolerance = TOLERANCE,
     537             :                             const bool secure = true)
     538             :   {
     539             :     // libmesh_deprecated(); // soon
     540           0 :     return FEMap::inverse_map(Dim, elem, p, tolerance, secure, secure);
     541             :   }
     542             : 
     543           0 :   static void inverse_map (const Elem * elem,
     544             :                            const std::vector<Point> & physical_points,
     545             :                            std::vector<Point> &       reference_points,
     546             :                            const Real tolerance = TOLERANCE,
     547             :                            const bool secure = true)
     548             :   {
     549             :     // libmesh_deprecated(); // soon
     550           0 :     FEMap::inverse_map(Dim, elem, physical_points, reference_points,
     551             :                        tolerance, secure, secure);
     552           0 :   }
     553             : 
     554             :   /**
     555             :    * This is at the core of this class. Use this for each
     556             :    * new element in the mesh.  Reinitializes all the physical
     557             :    * element-dependent data based on the current element
     558             :    * \p elem.  By default the shape functions and associated
     559             :    * data are computed at the quadrature points specified
     560             :    * by the quadrature rule \p qrule, but may be any points
     561             :    * specified on the reference element specified in the optional
     562             :    * argument \p pts.
     563             :    */
     564             :   virtual void reinit (const Elem * elem,
     565             :                        const std::vector<Point> * const pts = nullptr,
     566             :                        const std::vector<Real> * const weights = nullptr) override;
     567             : 
     568             :   /**
     569             :   * This re-computes the dual shape function coefficients.
     570             :   * The dual shape coefficients are utilized when calculating dual shape functions.
     571             :   */
     572             :   virtual void reinit_dual_shape_coeffs (const Elem * elem,
     573             :                                          const std::vector<Point> & pts,
     574             :                                          const std::vector<Real> & JxW) override;
     575             : 
     576             :   /**
     577             :    * This computes the default dual shape function coefficients.
     578             :    * The dual shape coefficients are utilized when calculating dual shape functions.
     579             :    */
     580             :    virtual void reinit_default_dual_shape_coeffs (const Elem * elem) override;
     581             : 
     582             :   /**
     583             :    * Reinitializes all the physical element-dependent data based on
     584             :    * the \p side of \p face.  The \p tolerance parameter is passed to
     585             :    * the involved call to \p inverse_map().  By default the shape
     586             :    * functions and associated data are computed at the quadrature
     587             :    * points specified by the quadrature rule \p qrule, but may be any
     588             :    * points specified on the reference \em side element specified in
     589             :    * the optional argument \p pts.
     590             :    */
     591             :   virtual void reinit (const Elem * elem,
     592             :                        const unsigned int side,
     593             :                        const Real tolerance = TOLERANCE,
     594             :                        const std::vector<Point> * const pts = nullptr,
     595             :                        const std::vector<Real> * const weights = nullptr) override;
     596             : 
     597             :   /**
     598             :    * Reinitializes all the physical element-dependent data based on
     599             :    * the \p edge.  The \p tolerance parameter is passed to the
     600             :    * involved call to \p inverse_map().  By default the shape
     601             :    * functions and associated data are computed at the quadrature
     602             :    * points specified by the quadrature rule \p qrule, but may be any
     603             :    * points specified on the reference \em side element specified in
     604             :    * the optional argument \p pts.
     605             :    */
     606             :   virtual void edge_reinit (const Elem * elem,
     607             :                             const unsigned int edge,
     608             :                             const Real tolerance = TOLERANCE,
     609             :                             const std::vector<Point> * const pts = nullptr,
     610             :                             const std::vector<Real> * const weights = nullptr) override;
     611             : 
     612             :   /**
     613             :    * Computes the reference space quadrature points on the side of
     614             :    * an element based on the side quadrature points.
     615             :    */
     616             :   virtual void side_map (const Elem * elem,
     617             :                          const Elem * side,
     618             :                          const unsigned int s,
     619             :                          const std::vector<Point> & reference_side_points,
     620             :                          std::vector<Point> &       reference_points) override;
     621             : 
     622             :   /**
     623             :    * Computes the reference space quadrature points on the side of
     624             :    * an element based on the edge quadrature points.
     625             :    */
     626             :   virtual void edge_map (const Elem * elem,
     627             :                          const Elem * edge,
     628             :                          const unsigned int e,
     629             :                          const std::vector<Point> & reference_edge_points,
     630             :                          std::vector<Point> &       reference_points);
     631             : 
     632             :   /**
     633             :    * Provides the class with the quadrature rule, which provides the
     634             :    * locations (on a reference element) where the shape functions are
     635             :    * to be calculated.
     636             :    */
     637             :   virtual void attach_quadrature_rule (QBase * q) override;
     638             : 
     639             : #ifdef LIBMESH_ENABLE_AMR
     640             :   /**
     641             :    * Computes the constraint matrix contributions (for
     642             :    * non-conforming adapted meshes) corresponding to
     643             :    * variable number \p var_number, using element-specific
     644             :    * optimizations if possible.
     645             :    */
     646             :   static void compute_constraints (DofConstraints & constraints,
     647             :                                    DofMap & dof_map,
     648             :                                    const unsigned int variable_number,
     649             :                                    const Elem * elem);
     650             : #endif // #ifdef LIBMESH_ENABLE_AMR
     651             : 
     652             :   /**
     653             :    * \returns \p true when the shape functions (for
     654             :    * this \p FEFamily) depend on the particular
     655             :    * element, and therefore needs to be re-initialized
     656             :    * for each new element.  \p false otherwise.
     657             :    */
     658             :   virtual bool shapes_need_reinit() const override;
     659             : 
     660           0 :   static Point map (const Elem * elem,
     661             :                     const Point & reference_point)
     662             :   {
     663             :     // libmesh_deprecated(); // soon
     664           0 :     return FEMap::map(Dim, elem, reference_point);
     665             :   }
     666             : 
     667           0 :   static Point map_xi (const Elem * elem,
     668             :                        const Point & reference_point)
     669             :   {
     670             :     // libmesh_deprecated(); // soon
     671           0 :     return FEMap::map_deriv(Dim, elem, 0, reference_point);
     672             :   }
     673             : 
     674           0 :   static Point map_eta (const Elem * elem,
     675             :                         const Point & reference_point)
     676             :   {
     677             :     // libmesh_deprecated(); // soon
     678           0 :     return FEMap::map_deriv(Dim, elem, 1, reference_point);
     679             :   }
     680             : 
     681           0 :   static Point map_zeta (const Elem * elem,
     682             :                          const Point & reference_point)
     683             :   {
     684             :     // libmesh_deprecated(); // soon
     685           0 :     return FEMap::map_deriv(Dim, elem, 2, reference_point);
     686             :   }
     687             : 
     688             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     689             :   /**
     690             :    * make InfFE classes friends, so that these may access
     691             :    * the private \p map, map_xyz methods
     692             :    */
     693             :   template <unsigned int friend_Dim, FEFamily friend_T_radial, InfMapType friend_T_map>
     694             :   friend class InfFE;
     695             : #endif
     696             : 
     697             : protected:
     698             : 
     699             :   /**
     700             :    * Update the various member data fields \p phi,
     701             :    * \p dphidxi, \p dphideta, \p dphidzeta, etc.
     702             :    * for the current element.  These data will be computed
     703             :    * at the points \p qp, which are generally (but need not be)
     704             :    * the quadrature points.
     705             :    */
     706             :   virtual void init_shape_functions(const std::vector<Point> & qp,
     707             :                                     const Elem * e);
     708             : 
     709             :   /**
     710             :    * A default implementation for all_shape_derivs
     711             :    */
     712             :   static void default_all_shape_derivs (const Elem * elem,
     713             :                                         const Order o,
     714             :                                         const std::vector<Point> & p,
     715             :                                         std::vector<std::vector<OutputShape>> * comps[3],
     716             :                                         const bool add_p_level = true);
     717             : 
     718             : 
     719             :   /**
     720             :    * Init \p dual_phi and potentially \p dual_dphi, \p dual_d2phi
     721             :    */
     722             :   void init_dual_shape_functions(unsigned int n_shapes, unsigned int n_qp);
     723             : 
     724             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     725             : 
     726             :   /**
     727             :    * Initialize the data fields for the base of an
     728             :    * an infinite element.
     729             :    */
     730             :   virtual void init_base_shape_functions(const std::vector<Point> & qp,
     731             :                                          const Elem * e) override;
     732             : 
     733             : #endif
     734             : 
     735             :   /**
     736             :    * A default implementation for shapes
     737             :    */
     738   935745350 :   static void default_shapes (const Elem * elem,
     739             :                               const Order o,
     740             :                               const unsigned int i,
     741             :                               const std::vector<Point> & p,
     742             :                               std::vector<OutputShape> & v,
     743             :                               const bool add_p_level = true)
     744             :     {
     745    82454994 :       libmesh_assert_equal_to(p.size(), v.size());
     746  5029776224 :       for (auto vi : index_range(v))
     747  4448181371 :         v[vi] = FE<Dim,T>::shape (elem, o, i, p[vi], add_p_level);
     748   935745350 :     }
     749             : 
     750             :   /**
     751             :    * A default implementation for all_shapes
     752             :    */
     753   128338200 :   static void default_all_shapes (const Elem * elem,
     754             :                                   const Order o,
     755             :                                   const std::vector<Point> & p,
     756             :                                   std::vector<std::vector<OutputShape>> & v,
     757             :                                   const bool add_p_level = true)
     758             :     {
     759  1058914942 :       for (auto i : index_range(v))
     760             :         {
     761    82007637 :           libmesh_assert_equal_to ( p.size(), v[i].size() );
     762  1011695621 :           FE<Dim,T>::shapes (elem, o, i, p, v[i], add_p_level);
     763             :         }
     764   128338200 :     }
     765             : 
     766             :   /**
     767             :    * A default implementation for shape_derivs
     768             :    */
     769  1331512258 :   static void default_shape_derivs (const Elem * elem,
     770             :                                     const Order o,
     771             :                                     const unsigned int i,
     772             :                                     const unsigned int j,
     773             :                                     const std::vector<Point> & p,
     774             :                                     std::vector<OutputShape> & v,
     775             :                                     const bool add_p_level = true)
     776             :     {
     777   115312661 :       libmesh_assert_equal_to(p.size(), v.size());
     778  6517312484 :       for (auto vi : index_range(v))
     779  5626124095 :         v[vi] = FE<Dim,T>::shape_deriv (elem, o, i, j, p[vi], add_p_level);
     780  1331512258 :     }
     781             : 
     782             :   /**
     783             :    * A default implementation for side_nodal_soln
     784             :    */
     785             :   static void default_side_nodal_soln(const Elem * elem, const Order o,
     786             :                                       const unsigned int side,
     787             :                                       const std::vector<Number> & elem_soln,
     788             :                                       std::vector<Number> & nodal_soln_on_side,
     789             :                                       bool add_p_level = true,
     790             :                                       const unsigned vdim = 1);
     791             : 
     792             :   /**
     793             :    * Vectors holding the node locations, edge and
     794             :    * face orientations of the last element we cached.
     795             :    */
     796             :   std::vector<Point> cached_nodes;
     797             :   std::vector<bool> cached_edges, cached_faces;
     798             : 
     799             :   /**
     800             :    * Repopulate the element cache with the node locations,
     801             :    * edge and face orientations of the element \p elem.
     802             :    */
     803             :   void cache(const Elem * elem);
     804             : 
     805             :   /**
     806             :    * Check if the node locations, edge and face orientations
     807             :    * held in the element cache match those of element \p elem.
     808             :    */
     809             :   bool matches_cache(const Elem * elem);
     810             : 
     811             :   /**
     812             :    * The last side and last edge we did a reinit on
     813             :    */
     814             :   ElemType last_side;
     815             : 
     816             :   ElemType last_edge;
     817             : };
     818             : 
     819             : 
     820             : 
     821             : /**
     822             :  * Clough-Tocher finite elements.  Still templated on the dimension,
     823             :  * \p Dim.
     824             :  *
     825             :  * \author Roy Stogner
     826             :  * \date 2004
     827             :  */
     828             : template <unsigned int Dim>
     829             : class FEClough : public FE<Dim,CLOUGH>
     830             : {
     831             : public:
     832             : 
     833             :   /**
     834             :    * Constructor. Creates a hierarchic finite element
     835             :    * to be used in dimension \p Dim.
     836             :    */
     837             :   explicit
     838             :   FEClough(const FEType & fet) :
     839             :     FE<Dim,CLOUGH> (fet)
     840             :   {}
     841             : };
     842             : 
     843             : 
     844             : 
     845             : /**
     846             :  * Hermite finite elements.  Still templated on the dimension,
     847             :  * \p Dim.
     848             :  *
     849             :  * \author Roy Stogner
     850             :  * \date 2005
     851             :  */
     852             : template <unsigned int Dim>
     853             : class FEHermite : public FE<Dim,HERMITE>
     854             : {
     855             : public:
     856             : 
     857             :   /**
     858             :    * Constructor. Creates a hierarchic finite element
     859             :    * to be used in dimension \p Dim.
     860             :    */
     861             :   explicit
     862             :   FEHermite(const FEType & fet) :
     863             :     FE<Dim,HERMITE> (fet)
     864             :   {}
     865             : 
     866             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     867             :   /**
     868             :    * 1D hermite functions on unit interval
     869             :    */
     870             :   static Real hermite_raw_shape_second_deriv(const unsigned int basis_num,
     871             :                                              const Real xi);
     872             : #endif
     873             :   static Real hermite_raw_shape_deriv(const unsigned int basis_num,
     874             :                                       const Real xi);
     875             :   static Real hermite_raw_shape(const unsigned int basis_num,
     876             :                                 const Real xi);
     877             : };
     878             : 
     879             : 
     880             : 
     881             : /**
     882             :  * Subdivision finite elements.
     883             :  *
     884             :  * Template specialization prototypes are needed for calling from
     885             :  * inside FESubdivision::init_shape_functions
     886             :  */
     887             : template <>
     888             : Real FE<2,SUBDIVISION>::shape(const Elem * elem,
     889             :                               const Order order,
     890             :                               const unsigned int i,
     891             :                               const Point & p,
     892             :                               const bool add_p_level);
     893             : 
     894             : template <>
     895             : Real FE<2,SUBDIVISION>::shape_deriv(const Elem * elem,
     896             :                                     const Order order,
     897             :                                     const unsigned int i,
     898             :                                     const unsigned int j,
     899             :                                     const Point & p,
     900             :                                     const bool add_p_level);
     901             : 
     902             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     903             : template <>
     904             : Real FE<2,SUBDIVISION>::shape_second_deriv(const Elem * elem,
     905             :                                            const Order order,
     906             :                                            const unsigned int i,
     907             :                                            const unsigned int j,
     908             :                                            const Point & p,
     909             :                                            const bool add_p_level);
     910             : 
     911             : #endif
     912             : 
     913             : class FESubdivision : public FE<2,SUBDIVISION>
     914             : {
     915             : public:
     916             : 
     917             :   /**
     918             :    * Constructor. Creates a subdivision surface finite element.
     919             :    * Currently only supported for two-dimensional meshes in
     920             :    * three-dimensional space.
     921             :    */
     922             :   FESubdivision(const FEType & fet);
     923             : 
     924             :   /**
     925             :    * This is at the core of this class. Use this for each new
     926             :    * non-ghosted element in the mesh.  Reinitializes all the physical
     927             :    * element-dependent data based on the current element
     928             :    * \p elem.  By default the shape functions and associated
     929             :    * data are computed at the quadrature points specified
     930             :    * by the quadrature rule \p qrule, but may be any points
     931             :    * specified on the reference element specified in the optional
     932             :    * argument \p pts.
     933             :    */
     934             :   virtual void reinit (const Elem * elem,
     935             :                        const std::vector<Point> * const pts = nullptr,
     936             :                        const std::vector<Real> * const weights = nullptr) override;
     937             : 
     938             :   /**
     939             :    * This prevents some compilers being confused by partially
     940             :    * overriding this virtual function.
     941             :    */
     942           0 :   virtual void reinit (const Elem *,
     943             :                        const unsigned int,
     944             :                        const Real = TOLERANCE,
     945             :                        const std::vector<Point> * const = nullptr,
     946             :                        const std::vector<Real> * const = nullptr) override
     947           0 :   { libmesh_not_implemented(); }
     948             : 
     949             :   /**
     950             :    * Provides the class with the quadrature rule, which provides the
     951             :    * locations (on a reference element) where the shape functions are
     952             :    * to be calculated.
     953             :    */
     954             :   virtual void attach_quadrature_rule (QBase * q) override;
     955             : 
     956             :   /**
     957             :    * Update the various member data fields \p phi,
     958             :    * \p dphidxi, \p dphideta, \p dphidzeta, etc.
     959             :    * for the current element.  These data will be computed
     960             :    * at the points \p qp, which are generally (but need not be)
     961             :    * the quadrature points.
     962             :    */
     963             :   virtual void init_shape_functions(const std::vector<Point> & qp,
     964             :                                     const Elem * elem) override;
     965             : 
     966             :   /**
     967             :    * \returns The value of the \f$ i^{th} \f$ of the 12 quartic
     968             :    * box splines interpolating a regular Loop subdivision
     969             :    * element, evaluated at the barycentric coordinates \p v,
     970             :    * \p w.
     971             :    */
     972             :   static Real regular_shape(const unsigned int i,
     973             :                             const Real v,
     974             :                             const Real w);
     975             : 
     976             :   /**
     977             :    * \returns The \f$ j^{th} \f$ derivative of the \f$ i^{th}
     978             :    * \f$ of the 12 quartic box splines interpolating a regular
     979             :    * Loop subdivision element, evaluated at the barycentric
     980             :    * coordinates \p v, \p w.
     981             :    */
     982             :   static Real regular_shape_deriv(const unsigned int i,
     983             :                                   const unsigned int j,
     984             :                                   const Real v,
     985             :                                   const Real w);
     986             : 
     987             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     988             :   /**
     989             :    * \returns The second \f$ j^{th} \f$ derivative of the
     990             :    * \f$ i^{th} \f$ of the 12 quartic box splines interpolating
     991             :    * a regular Loop subdivision element, evaluated at the
     992             :    * barycentric coordinates \p v, \p w.
     993             :    */
     994             :   static Real regular_shape_second_deriv(const unsigned int i,
     995             :                                          const unsigned int j,
     996             :                                          const Real v,
     997             :                                          const Real w);
     998             : 
     999             : 
    1000             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVE
    1001             :   /**
    1002             :    * Fills the vector \p weights with the weight coefficients
    1003             :    * of the Loop subdivision mask for evaluating the limit surface
    1004             :    * at a node explicitly. The size of \p weights will be
    1005             :    * 1 + \p valence, where \p valence is the number of neighbor
    1006             :    * nodes of the node where the limit surface is to be
    1007             :    * evaluated. The weight for the node itself is the first
    1008             :    * element of \p weights.
    1009             :    */
    1010             :   static void loop_subdivision_mask(std::vector<Real> & weights,
    1011             :                                     const unsigned int valence);
    1012             : 
    1013             : 
    1014             :   /**
    1015             :    * Builds the subdivision matrix \p A for the Loop scheme. The
    1016             :    * size depends on the element's \p valence.
    1017             :    */
    1018             :   static void init_subdivision_matrix(DenseMatrix<Real> & A,
    1019             :                                       unsigned int valence);
    1020             : };
    1021             : 
    1022             : 
    1023             : 
    1024             : /**
    1025             :  * Hierarchic finite elements.  Still templated on the dimension,
    1026             :  * \p Dim.
    1027             :  *
    1028             :  * \author Benjamin S. Kirk
    1029             :  * \date 2002-2007
    1030             :  */
    1031             : template <unsigned int Dim>
    1032             : class FEHierarchic : public FE<Dim,HIERARCHIC>
    1033             : {
    1034             : public:
    1035             : 
    1036             :   /**
    1037             :    * Constructor. Creates a hierarchic finite element
    1038             :    * to be used in dimension \p Dim.
    1039             :    */
    1040             :   explicit
    1041             :   FEHierarchic(const FEType & fet) :
    1042             :     FE<Dim,HIERARCHIC> (fet)
    1043             :   {}
    1044             : };
    1045             : 
    1046             : 
    1047             : 
    1048             : /**
    1049             :  * Discontinuous Hierarchic finite elements.  Still templated on the dimension,
    1050             :  * \p Dim.
    1051             :  *
    1052             :  * \author Truman E. Ellis
    1053             :  * \date 2011
    1054             :  */
    1055             : template <unsigned int Dim>
    1056             : class FEL2Hierarchic : public FE<Dim,L2_HIERARCHIC>
    1057             : {
    1058             : public:
    1059             : 
    1060             :   /**
    1061             :    * Constructor. Creates a hierarchic finite element
    1062             :    * to be used in dimension \p Dim.
    1063             :    */
    1064             :   explicit
    1065             :   FEL2Hierarchic(const FEType & fet) :
    1066             :     FE<Dim,L2_HIERARCHIC> (fet)
    1067             :   {}
    1068             : };
    1069             : 
    1070             : 
    1071             : 
    1072             : /**
    1073             :  * Lagrange finite elements.  Still templated on the dimension,
    1074             :  * \p Dim.
    1075             :  *
    1076             :  * \author Benjamin S. Kirk
    1077             :  * \date 2002-2007
    1078             :  */
    1079             : template <unsigned int Dim>
    1080             : class FELagrange : public FE<Dim,LAGRANGE>
    1081             : {
    1082             : public:
    1083             : 
    1084             :   /**
    1085             :    * Constructor. Creates a Lagrange finite element
    1086             :    * to be used in dimension \p Dim.
    1087             :    */
    1088             :   explicit
    1089             :   FELagrange(const FEType & fet) :
    1090             :     FE<Dim,LAGRANGE> (fet)
    1091             :   {}
    1092             : };
    1093             : 
    1094             : 
    1095             : /**
    1096             :  * Discontinuous Lagrange finite elements.
    1097             :  */
    1098             : template <unsigned int Dim>
    1099             : class FEL2Lagrange : public FE<Dim,L2_LAGRANGE>
    1100             : {
    1101             : public:
    1102             : 
    1103             :   /**
    1104             :    * Constructor. Creates a discontinuous Lagrange finite element
    1105             :    * to be used in dimension \p Dim.
    1106             :    */
    1107             :   explicit
    1108             :   FEL2Lagrange(const FEType & fet) :
    1109             :     FE<Dim,L2_LAGRANGE> (fet)
    1110             :   {}
    1111             : };
    1112             : 
    1113             : 
    1114             : /**
    1115             :  * Monomial finite elements.  Still templated on the dimension,
    1116             :  * \p Dim.
    1117             :  *
    1118             :  * \author Benjamin S. Kirk
    1119             :  * \date 2002-2007
    1120             :  */
    1121             : template <unsigned int Dim>
    1122             : class FEMonomial : public FE<Dim,MONOMIAL>
    1123             : {
    1124             : public:
    1125             : 
    1126             :   /**
    1127             :    * Constructor. Creates a monomial finite element
    1128             :    * to be used in dimension \p Dim.
    1129             :    */
    1130             :   explicit
    1131             :   FEMonomial(const FEType & fet) :
    1132             :     FE<Dim,MONOMIAL> (fet)
    1133             :   {}
    1134             : };
    1135             : 
    1136             : 
    1137             : /**
    1138             :  * The FEScalar class is used for working with SCALAR variables.
    1139             :  */
    1140             : template <unsigned int Dim>
    1141             : class FEScalar : public FE<Dim,SCALAR>
    1142             : {
    1143             : public:
    1144             : 
    1145             :   /**
    1146             :    * Constructor. Creates a SCALAR finite element
    1147             :    * which simply represents one or more
    1148             :    * extra DOFs coupled to all other DOFs in
    1149             :    * the system.
    1150             :    */
    1151             :   explicit
    1152       16520 :   FEScalar(const FEType & fet) :
    1153       16520 :     FE<Dim,SCALAR> (fet)
    1154         496 :   {}
    1155             : };
    1156             : 
    1157             : 
    1158             : /**
    1159             :  * XYZ finite elements.  These require specialization
    1160             :  * because the shape functions are defined in terms of
    1161             :  * physical XYZ coordinates rather than local coordinates.
    1162             :  *
    1163             :  * \author Benjamin S. Kirk
    1164             :  * \date 2002-2007
    1165             :  */
    1166             : template <unsigned int Dim>
    1167             : class FEXYZ : public FE<Dim,XYZ>
    1168             : {
    1169             : public:
    1170             : 
    1171             :   /**
    1172             :    * Constructor. Creates a monomial finite element
    1173             :    * to be used in dimension \p Dim.
    1174             :    */
    1175             :   explicit
    1176      859376 :   FEXYZ(const FEType & fet) :
    1177      859376 :     FE<Dim,XYZ> (fet)
    1178       31754 :   {}
    1179             : 
    1180             :   /**
    1181             :    * Explicitly call base class method.  This prevents some
    1182             :    * compilers being confused by partially overriding this virtual function.
    1183             :    * \note: pts need to be in reference space coordinates, not physical ones.
    1184             :    */
    1185     1364081 :   virtual void reinit (const Elem * elem,
    1186             :                        const std::vector<Point> * const pts = nullptr,
    1187             :                        const std::vector<Real> * const weights = nullptr) override
    1188     1364081 :   { FE<Dim,XYZ>::reinit (elem, pts, weights); }
    1189             : 
    1190             :   /**
    1191             :    * Reinitializes all the physical element-dependent data based on
    1192             :    * the \p side of \p face.
    1193             :    */
    1194             :   virtual void reinit (const Elem * elem,
    1195             :                        const unsigned int side,
    1196             :                        const Real tolerance = TOLERANCE,
    1197             :                        const std::vector<Point> * const pts = nullptr,
    1198             :                        const std::vector<Real> * const weights = nullptr) override;
    1199             : 
    1200             : 
    1201             : protected:
    1202             : 
    1203             :   /**
    1204             :    * Update the various member data fields \p phi,
    1205             :    * \p dphidxi, \p dphideta, \p dphidzeta, etc.
    1206             :    * for the current element.  These data will be computed
    1207             :    * at the points \p qp, which are generally (but need not be)
    1208             :    * the quadrature points.
    1209             :    */
    1210             :   virtual void init_shape_functions(const std::vector<Point> & qp,
    1211             :                                     const Elem * e) override;
    1212             : 
    1213             :   /**
    1214             :    * After having updated the jacobian and the transformation
    1215             :    * from local to global coordinates in \p FEAbstract::compute_map(),
    1216             :    * the first derivatives of the shape functions are
    1217             :    * transformed to global coordinates, giving \p dphi,
    1218             :    * \p dphidx, \p dphidy, and \p dphidz. This method
    1219             :    * should rarely be re-defined in derived classes, but
    1220             :    * still should be usable for children. Therefore, keep
    1221             :    * it protected.
    1222             :    */
    1223             :   virtual void compute_shape_functions(const Elem * elem, const std::vector<Point> & qp) override;
    1224             : 
    1225             :   /**
    1226             :    * Compute the map & shape functions for this face.
    1227             :    */
    1228             :   void compute_face_values (const Elem * elem,
    1229             :                             const Elem * side,
    1230             :                             const std::vector<Real> & weights);
    1231             : };
    1232             : 
    1233             : 
    1234             : 
    1235             : /**
    1236             :  * FELagrangeVec objects are used for working with vector-valued
    1237             :  * finite elements
    1238             :  *
    1239             :  * \author Paul T. Bauman
    1240             :  * \date 2013
    1241             :  */
    1242             : template <unsigned int Dim>
    1243             : class FELagrangeVec : public FE<Dim,LAGRANGE_VEC>
    1244             : {
    1245             : public:
    1246             : 
    1247             :   /**
    1248             :    * Constructor. Creates a vector Lagrange finite element
    1249             :    * to be used in dimension \p Dim.
    1250             :    */
    1251             :   explicit
    1252       39214 :   FELagrangeVec(const FEType & fet) :
    1253       39214 :     FE<Dim,LAGRANGE_VEC> (fet)
    1254        3196 :   {}
    1255             : };
    1256             : 
    1257             : 
    1258             : /**
    1259             :  * FEL2LagrangeVec objects are used for working with vector-valued
    1260             :  * finite elements
    1261             :  *
    1262             :  * \author Alexander Lindsay
    1263             :  * \date 2023
    1264             :  */
    1265             : template <unsigned int Dim>
    1266             : class FEL2LagrangeVec : public FE<Dim,L2_LAGRANGE_VEC>
    1267             : {
    1268             : public:
    1269             : 
    1270             :   /**
    1271             :    * Constructor. Creates a vector Lagrange finite element
    1272             :    * to be used in dimension \p Dim.
    1273             :    */
    1274             :   explicit
    1275        4670 :   FEL2LagrangeVec(const FEType & fet) :
    1276        4670 :     FE<Dim,L2_LAGRANGE_VEC> (fet)
    1277         132 :   {}
    1278             : };
    1279             : 
    1280             : 
    1281             : 
    1282             : /**
    1283             :  * FEHierarchicVec objects are used for working with vector-valued
    1284             :  * high-order finite elements
    1285             :  *
    1286             :  * \author Roy H. Stogner
    1287             :  * \date 2023
    1288             :  */
    1289             : template <unsigned int Dim>
    1290             : class FEHierarchicVec : public FE<Dim,HIERARCHIC_VEC>
    1291             : {
    1292             : public:
    1293             : 
    1294             :   /**
    1295             :    * Constructor. Creates a vector Hierarchic finite element
    1296             :    * to be used in dimension \p Dim.
    1297             :    */
    1298             :   explicit
    1299       16572 :   FEHierarchicVec(const FEType & fet) :
    1300       16572 :     FE<Dim,HIERARCHIC_VEC> (fet)
    1301        1334 :   {}
    1302             : };
    1303             : 
    1304             : 
    1305             : /**
    1306             :  * FEHierarchicVec objects are used for working with vector-valued
    1307             :  * high-order piecewise-continuous finite elements
    1308             :  *
    1309             :  * \author Roy H. Stogner
    1310             :  * \date 2023
    1311             :  */
    1312             : template <unsigned int Dim>
    1313             : class FEL2HierarchicVec : public FE<Dim,L2_HIERARCHIC_VEC>
    1314             : {
    1315             : public:
    1316             : 
    1317             :   /**
    1318             :    * Constructor. Creates a vector Hierarchic finite element
    1319             :    * to be used in dimension \p Dim.
    1320             :    */
    1321             :   explicit
    1322        3550 :   FEL2HierarchicVec(const FEType & fet) :
    1323        3550 :     FE<Dim,L2_HIERARCHIC_VEC> (fet)
    1324         100 :   {}
    1325             : };
    1326             : 
    1327             : 
    1328             : /**
    1329             :  * FENedelecOne objects are used for working with vector-valued
    1330             :  * Nedelec finite elements of the first kind.
    1331             :  *
    1332             :  * \author Paul T. Bauman
    1333             :  * \date 2013
    1334             :  */
    1335             : template <unsigned int Dim>
    1336             : class FENedelecOne : public FE<Dim,NEDELEC_ONE>
    1337             : {
    1338             : public:
    1339             :   /**
    1340             :    * Constructor. Creates a Nedelec finite element of the first kind
    1341             :    * to be used in dimension \p Dim.
    1342             :    */
    1343             :   explicit
    1344       97360 :   FENedelecOne(const FEType & fet) :
    1345       97360 :     FE<Dim,NEDELEC_ONE> (fet)
    1346        7290 :   {}
    1347             : };
    1348             : 
    1349             : /**
    1350             :  * FEMonomialVec objects are used for working with vector-valued
    1351             :  * discontinuous finite elements
    1352             :  *
    1353             :  * \author Alex D. Lindsay
    1354             :  * \date 2019
    1355             :  */
    1356             : template <unsigned int Dim>
    1357             : class FEMonomialVec : public FE<Dim,MONOMIAL_VEC>
    1358             : {
    1359             : public:
    1360             : 
    1361             :   /**
    1362             :    * Constructor. Creates a vector Monomial finite element
    1363             :    * to be used in dimension \p Dim.
    1364             :    */
    1365             :   explicit
    1366        1470 :   FEMonomialVec(const FEType & fet) :
    1367        1470 :     FE<Dim,MONOMIAL_VEC> (fet)
    1368          42 :   {}
    1369             : };
    1370             : 
    1371             : /**
    1372             :  * FERaviartThomas objects are used for working with vector-valued
    1373             :  * Raviart-Thomas finite elements.
    1374             :  *
    1375             :  * \author Nuno Nobre & Karthikeyan Chockalingam
    1376             :  * \date 2023
    1377             :  */
    1378             : template <unsigned int Dim>
    1379             : class FERaviartThomas : public FE<Dim,RAVIART_THOMAS>
    1380             : {
    1381             : public:
    1382             : 
    1383             :   /**
    1384             :    * Constructor. Creates a Raviart-Thomas finite element
    1385             :    * to be used in dimension \p Dim.
    1386             :    */
    1387             :   explicit
    1388      468554 :   FERaviartThomas(const FEType & fet) :
    1389      468554 :     FE<Dim,RAVIART_THOMAS> (fet)
    1390       37511 :   {}
    1391             : };
    1392             : 
    1393             : /**
    1394             :  * FEL2RaviartThomas objects are used for working with vector-valued
    1395             :  * discontinuous Raviart-Thomas finite elements, e.g. when constructing
    1396             :  * hybridized methods
    1397             :  *
    1398             :  * \author Alex D. Lindsay
    1399             :  * \date 2023
    1400             :  */
    1401             : template <unsigned int Dim>
    1402             : class FEL2RaviartThomas : public FE<Dim,L2_RAVIART_THOMAS>
    1403             : {
    1404             : public:
    1405             : 
    1406             :   /**
    1407             :    * Constructor. Creates a Raviart-Thomas finite element
    1408             :    * to be used in dimension \p Dim.
    1409             :    */
    1410             :   explicit
    1411        8080 :   FEL2RaviartThomas(const FEType & fet) :
    1412        8080 :     FE<Dim,L2_RAVIART_THOMAS> (fet)
    1413         228 :   {}
    1414             : };
    1415             : 
    1416             : /**
    1417             :  * Provide Typedefs for various element types.
    1418             :  */
    1419             : namespace FiniteElements
    1420             : {
    1421             : /**
    1422             :  * Convenient definition for a 2D
    1423             :  * Clough-Tocher finite element.
    1424             :  */
    1425             : typedef FEClough<2> FEClough2D;
    1426             : 
    1427             : /**
    1428             :  * Convenient definition for a 1D
    1429             :  * Hierarchic finite element.
    1430             :  */
    1431             : typedef FE<1,HIERARCHIC> FEHierarchic1D;
    1432             : 
    1433             : /**
    1434             :  * Convenient definition for a 2D
    1435             :  * Hierarchic finite element.
    1436             :  */
    1437             : typedef FE<2,HIERARCHIC> FEHierarchic2D;
    1438             : 
    1439             : /**
    1440             :  * Convenient definition for a 3D
    1441             :  * Hierarchic finite element.
    1442             :  */
    1443             : typedef FE<3,HIERARCHIC> FEHierarchic3D;
    1444             : 
    1445             : 
    1446             : /**
    1447             :  * Convenient definition for a 1D
    1448             :  * Discontinuous Hierarchic finite element.
    1449             :  */
    1450             : typedef FE<1,L2_HIERARCHIC> FEL2Hierarchic1D;
    1451             : 
    1452             : /**
    1453             :  * Convenient definition for a 2D
    1454             :  * Discontinuous Hierarchic finite element.
    1455             :  */
    1456             : typedef FE<2,L2_HIERARCHIC> FEL2Hierarchic2D;
    1457             : 
    1458             : /**
    1459             :  * Convenient definition for a 3D
    1460             :  * Discontinuous Hierarchic finite element.
    1461             :  */
    1462             : typedef FE<3,L2_HIERARCHIC> FEL2Hierarchic3D;
    1463             : 
    1464             : 
    1465             : /**
    1466             :  * Convenient definition for a 1D
    1467             :  * Lagrange finite element.
    1468             :  */
    1469             : typedef FE<1,LAGRANGE> FELagrange1D;
    1470             : 
    1471             : /**
    1472             :  * Convenient definition for a 2D
    1473             :  * Lagrange finite element.
    1474             :  */
    1475             : typedef FE<2,LAGRANGE> FELagrange2D;
    1476             : 
    1477             : /**
    1478             :  * Convenient definition for a 3D
    1479             :  * Lagrange finite element.
    1480             :  */
    1481             : typedef FE<3,LAGRANGE> FELagrange3D;
    1482             : 
    1483             : 
    1484             : /**
    1485             :  * Convenient definition for a 1D
    1486             :  * Discontinuous Lagrange finite element.
    1487             :  */
    1488             : typedef FE<1,L2_LAGRANGE> FEL2Lagrange1D;
    1489             : 
    1490             : /**
    1491             :  * Convenient definition for a 2D
    1492             :  * Discontinuous Lagrange finite element.
    1493             :  */
    1494             : typedef FE<2,L2_LAGRANGE> FEL2Lagrange2D;
    1495             : 
    1496             : /**
    1497             :  * Convenient definition for a 3D
    1498             :  * Discontinuous Lagrange finite element.
    1499             :  */
    1500             : typedef FE<3,L2_LAGRANGE> FEL2Lagrange3D;
    1501             : 
    1502             : 
    1503             : /**
    1504             :  * Convenient definition for a 1D
    1505             :  * Monomial finite element.
    1506             :  */
    1507             : typedef FE<1,MONOMIAL> FEMonomial1D;
    1508             : 
    1509             : /**
    1510             :  * Convenient definition for a 2D
    1511             :  * Monomial finite element.
    1512             :  */
    1513             : typedef FE<2,MONOMIAL> FEMonomial2D;
    1514             : 
    1515             : /**
    1516             :  * Convenient definition for a 3D
    1517             :  * Monomial finite element.
    1518             :  */
    1519             : typedef FE<3,MONOMIAL> FEMonomial3D;
    1520             : 
    1521             : }
    1522             : 
    1523             : /**
    1524             :  * Helper functions for finite differenced derivatives in cases where
    1525             :  * analytical calculations haven't been done yet.
    1526             :  */
    1527             : template <typename OutputShape>
    1528             : OutputShape fe_fdm_deriv(const Elem * elem,
    1529             :                          const Order order,
    1530             :                          const unsigned int i,
    1531             :                          const unsigned int j,
    1532             :                          const Point & p,
    1533             :                          const bool add_p_level,
    1534             :                          OutputShape(*shape_func)
    1535             :                            (const Elem *, const Order,
    1536             :                             const unsigned int, const Point &,
    1537             :                             const bool));
    1538             : 
    1539             : template <typename OutputShape>
    1540             : OutputShape fe_fdm_deriv(const ElemType type,
    1541             :                          const Order order,
    1542             :                          const unsigned int i,
    1543             :                          const unsigned int j,
    1544             :                          const Point & p,
    1545             :                          OutputShape(*shape_func)
    1546             :                            (const ElemType, const Order,
    1547             :                             const unsigned int, const Point &));
    1548             : 
    1549             : template <typename OutputShape>
    1550             : OutputShape fe_fdm_deriv(const ElemType type,
    1551             :                          const Order order,
    1552             :                          const Elem * elem,
    1553             :                          const unsigned int i,
    1554             :                          const unsigned int j,
    1555             :                          const Point & p,
    1556             :                          OutputShape(*shape_func)
    1557             :                            (const ElemType type, const Order,
    1558             :                             const Elem *, const unsigned int,
    1559             :                             const Point &));
    1560             : 
    1561             : 
    1562             : template <typename OutputShape>
    1563             : OutputShape
    1564             : fe_fdm_second_deriv(const Elem * elem,
    1565             :                     const Order order,
    1566             :                     const unsigned int i,
    1567             :                     const unsigned int j,
    1568             :                     const Point & p,
    1569             :                     const bool add_p_level,
    1570             :                     OutputShape(*deriv_func)
    1571             :                       (const Elem *, const Order,
    1572             :                        const unsigned int, const unsigned int,
    1573             :                        const Point &, const bool));
    1574             : 
    1575             : template <typename OutputShape>
    1576             : OutputShape fe_fdm_second_deriv(const ElemType type,
    1577             :                                 const Order order,
    1578             :                                 const unsigned int i,
    1579             :                                 const unsigned int j,
    1580             :                                 const Point & p,
    1581             :                                 OutputShape(*deriv_func)
    1582             :                                   (const ElemType, const Order,
    1583             :                                    const unsigned int,
    1584             :                                    const unsigned int,
    1585             :                                    const Point &));
    1586             : 
    1587             : template <typename OutputShape>
    1588             : OutputShape fe_fdm_second_deriv(const ElemType type,
    1589             :                                 const Order order,
    1590             :                                 const Elem * elem,
    1591             :                                 const unsigned int i,
    1592             :                                 const unsigned int j,
    1593             :                                 const Point & p,
    1594             :                                 OutputShape(*deriv_func)
    1595             :                                   (const ElemType, const Order,
    1596             :                                    const Elem *,
    1597             :                                    const unsigned int,
    1598             :                                    const unsigned int,
    1599             :                                    const Point &));
    1600             : 
    1601             : /**
    1602             :  * Helper functions for Lagrange-based basis functions.
    1603             :  */
    1604             : void lagrange_nodal_soln(const Elem * elem,
    1605             :                          const Order order,
    1606             :                          const std::vector<Number> & elem_soln,
    1607             :                          std::vector<Number> &       nodal_soln,
    1608             :                          bool add_p_level = true);
    1609             : 
    1610             : /**
    1611             :  * Helper functions for Discontinuous-Pn type basis functions.
    1612             :  */
    1613             : unsigned int monomial_n_dofs(const ElemType t, const Order o);
    1614             : 
    1615             : unsigned int monomial_n_dofs(const Elem * e, const Order o);
    1616             : 
    1617             : /**
    1618             :  * Helper functions for rational basis functions.
    1619             :  */
    1620             : // shapes[i][j] is shape function phi_i at point p[j]
    1621             : void rational_fe_weighted_shapes(const Elem * elem,
    1622             :                                  const FEType underlying_fe_type,
    1623             :                                  std::vector<std::vector<Real>> & shapes,
    1624             :                                  const std::vector<Point> & p,
    1625             :                                  const bool add_p_level);
    1626             : 
    1627             : // shapes[i][q] is shape function phi_i at point p[q]
    1628             : // derivs[j][i][q] is dphi_i/dxi_j at p[q]
    1629             : void rational_fe_weighted_shapes_derivs(const Elem * elem,
    1630             :                                         const FEType fe_type,
    1631             :                                         std::vector<std::vector<Real>> & shapes,
    1632             :                                         std::vector<std::vector<std::vector<Real>>> & derivs,
    1633             :                                         const std::vector<Point> & p,
    1634             :                                         const bool add_p_level);
    1635             : 
    1636             : Real rational_fe_shape(const Elem & elem,
    1637             :                        const FEType underlying_fe_type,
    1638             :                        const unsigned int i,
    1639             :                        const Point & p,
    1640             :                        const bool add_p_level);
    1641             : 
    1642             : Real rational_fe_shape_deriv(const Elem & elem,
    1643             :                              const FEType underlying_fe_type,
    1644             :                              const unsigned int i,
    1645             :                              const unsigned int j,
    1646             :                              const Point & p,
    1647             :                              const bool add_p_level);
    1648             : 
    1649             : Real rational_fe_shape_second_deriv(const Elem & elem,
    1650             :                                     const FEType underlying_fe_type,
    1651             :                                     const unsigned int i,
    1652             :                                     const unsigned int j,
    1653             :                                     const Point & p,
    1654             :                                     const bool add_p_level);
    1655             : 
    1656             : void rational_all_shapes (const Elem & elem,
    1657             :                           const FEType underlying_fe_type,
    1658             :                           const std::vector<Point> & p,
    1659             :                           std::vector<std::vector<Real>> & v,
    1660             :                           const bool add_p_level);
    1661             : 
    1662             : template <typename OutputShape>
    1663             : void rational_all_shape_derivs (const Elem & elem,
    1664             :                                 const FEType underlying_fe_type,
    1665             :                                 const std::vector<Point> & p,
    1666             :                                 std::vector<std::vector<OutputShape>> * comps[3],
    1667             :                                 const bool add_p_level);
    1668             : 
    1669             : } // namespace libMesh
    1670             : 
    1671             : 
    1672             : // Full specialization of all n_dofs type functions, for every
    1673             : // dimension, with both original ElemType and new Elem signatures
    1674             : #define LIBMESH_DEFAULT_NDOFS(MyType) \
    1675             : template <> unsigned int FE<0,MyType>::n_dofs(const ElemType t, const Order o) { return MyType##_n_dofs(t, o); } \
    1676             : template <> unsigned int FE<1,MyType>::n_dofs(const ElemType t, const Order o) { return MyType##_n_dofs(t, o); } \
    1677             : template <> unsigned int FE<2,MyType>::n_dofs(const ElemType t, const Order o) { return MyType##_n_dofs(t, o); } \
    1678             : template <> unsigned int FE<3,MyType>::n_dofs(const ElemType t, const Order o) { return MyType##_n_dofs(t, o); } \
    1679             :  \
    1680             : template <> unsigned int FE<0,MyType>::n_dofs(const Elem * e, const Order o) { return MyType##_n_dofs(e, o); } \
    1681             : template <> unsigned int FE<1,MyType>::n_dofs(const Elem * e, const Order o) { return MyType##_n_dofs(e, o); } \
    1682             : template <> unsigned int FE<2,MyType>::n_dofs(const Elem * e, const Order o) { return MyType##_n_dofs(e, o); } \
    1683             : template <> unsigned int FE<3,MyType>::n_dofs(const Elem * e, const Order o) { return MyType##_n_dofs(e, o); } \
    1684             :  \
    1685             : template <> unsigned int FE<0,MyType>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(t, o, n); } \
    1686             : template <> unsigned int FE<1,MyType>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(t, o, n); } \
    1687             : template <> unsigned int FE<2,MyType>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(t, o, n); } \
    1688             : template <> unsigned int FE<3,MyType>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(t, o, n); } \
    1689             :  \
    1690             : template <> unsigned int FE<0,MyType>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(e, o, n); } \
    1691             : template <> unsigned int FE<1,MyType>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(e, o, n); } \
    1692             : template <> unsigned int FE<2,MyType>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(e, o, n); } \
    1693             : template <> unsigned int FE<3,MyType>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return MyType##_n_dofs_at_node(e, o, n); } \
    1694             :  \
    1695             : template <> unsigned int FE<0,MyType>::n_dofs_per_elem(const ElemType t, const Order o) { return MyType##_n_dofs_per_elem(t, o); } \
    1696             : template <> unsigned int FE<1,MyType>::n_dofs_per_elem(const ElemType t, const Order o) { return MyType##_n_dofs_per_elem(t, o); } \
    1697             : template <> unsigned int FE<2,MyType>::n_dofs_per_elem(const ElemType t, const Order o) { return MyType##_n_dofs_per_elem(t, o); } \
    1698             : template <> unsigned int FE<3,MyType>::n_dofs_per_elem(const ElemType t, const Order o) { return MyType##_n_dofs_per_elem(t, o); } \
    1699             :  \
    1700             : template <> unsigned int FE<0,MyType>::n_dofs_per_elem(const Elem & e, const Order o) { return MyType##_n_dofs_per_elem(e, o); } \
    1701             : template <> unsigned int FE<1,MyType>::n_dofs_per_elem(const Elem & e, const Order o) { return MyType##_n_dofs_per_elem(e, o); } \
    1702             : template <> unsigned int FE<2,MyType>::n_dofs_per_elem(const Elem & e, const Order o) { return MyType##_n_dofs_per_elem(e, o); } \
    1703             : template <> unsigned int FE<3,MyType>::n_dofs_per_elem(const Elem & e, const Order o) { return MyType##_n_dofs_per_elem(e, o); }
    1704             : 
    1705             : 
    1706             : #define LIBMESH_DEFAULT_VEC_NDOFS(MyType) \
    1707             : template <> unsigned int FE<0,MyType##_VEC>::n_dofs(const ElemType t, const Order o) { return FE<0,MyType>::n_dofs(t, o); } \
    1708             : template <> unsigned int FE<1,MyType##_VEC>::n_dofs(const ElemType t, const Order o) { return FE<1,MyType>::n_dofs(t, o); } \
    1709             : template <> unsigned int FE<2,MyType##_VEC>::n_dofs(const ElemType t, const Order o) { return 2*FE<2,MyType>::n_dofs(t, o); } \
    1710             : template <> unsigned int FE<3,MyType##_VEC>::n_dofs(const ElemType t, const Order o) { return 3*FE<3,MyType>::n_dofs(t, o); } \
    1711             :  \
    1712             : template <> unsigned int FE<0,MyType##_VEC>::n_dofs(const Elem * e, const Order o) { return FE<0,MyType>::n_dofs(e, o); } \
    1713             : template <> unsigned int FE<1,MyType##_VEC>::n_dofs(const Elem * e, const Order o) { return FE<1,MyType>::n_dofs(e, o); } \
    1714             : template <> unsigned int FE<2,MyType##_VEC>::n_dofs(const Elem * e, const Order o) { return 2*FE<2,MyType>::n_dofs(e, o); } \
    1715             : template <> unsigned int FE<3,MyType##_VEC>::n_dofs(const Elem * e, const Order o) { return 3*FE<3,MyType>::n_dofs(e, o); } \
    1716             :  \
    1717             : template <> unsigned int FE<0,MyType##_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return FE<0,MyType>::n_dofs_at_node(t, o, n); } \
    1718             : template <> unsigned int FE<1,MyType##_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return FE<1,MyType>::n_dofs_at_node(t, o, n); } \
    1719             : template <> unsigned int FE<2,MyType##_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return 2*FE<2,MyType>::n_dofs_at_node(t, o, n); } \
    1720             : template <> unsigned int FE<3,MyType##_VEC>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return 3*FE<3,MyType>::n_dofs_at_node(t, o, n); } \
    1721             :  \
    1722             : template <> unsigned int FE<0,MyType##_VEC>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return FE<0,MyType>::n_dofs_at_node(e.type(), o, n); } \
    1723             : template <> unsigned int FE<1,MyType##_VEC>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return FE<1,MyType>::n_dofs_at_node(e.type(), o, n); } \
    1724             : template <> unsigned int FE<2,MyType##_VEC>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return 2*FE<2,MyType>::n_dofs_at_node(e.type(), o, n); } \
    1725             : template <> unsigned int FE<3,MyType##_VEC>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return 3*FE<3,MyType>::n_dofs_at_node(e.type(), o, n); } \
    1726             :  \
    1727             : template <> unsigned int FE<0,MyType##_VEC>::n_dofs_per_elem(const ElemType t, const Order o) { return FE<0,MyType>::n_dofs_per_elem(t, o); } \
    1728             : template <> unsigned int FE<1,MyType##_VEC>::n_dofs_per_elem(const ElemType t, const Order o) { return FE<1,MyType>::n_dofs_per_elem(t, o); } \
    1729             : template <> unsigned int FE<2,MyType##_VEC>::n_dofs_per_elem(const ElemType t, const Order o) { return 2*FE<2,MyType>::n_dofs_per_elem(t, o); } \
    1730             : template <> unsigned int FE<3,MyType##_VEC>::n_dofs_per_elem(const ElemType t, const Order o) { return 3*FE<3,MyType>::n_dofs_per_elem(t, o); } \
    1731             :  \
    1732             : template <> unsigned int FE<0,MyType##_VEC>::n_dofs_per_elem(const Elem & e, const Order o) { return FE<0,MyType>::n_dofs_per_elem(e.type(), o); } \
    1733             : template <> unsigned int FE<1,MyType##_VEC>::n_dofs_per_elem(const Elem & e, const Order o) { return FE<1,MyType>::n_dofs_per_elem(e.type(), o); } \
    1734             : template <> unsigned int FE<2,MyType##_VEC>::n_dofs_per_elem(const Elem & e, const Order o) { return 2*FE<2,MyType>::n_dofs_per_elem(e.type(), o); } \
    1735             : template <> unsigned int FE<3,MyType##_VEC>::n_dofs_per_elem(const Elem & e, const Order o) { return 3*FE<3,MyType>::n_dofs_per_elem(e.type(), o); }
    1736             : 
    1737             : 
    1738             : #define LIBMESH_DEFAULT_VECTORIZED_FE(MyDim, MyType) \
    1739             : template<>                                           \
    1740             : void FE<MyDim,MyType>::all_shapes                    \
    1741             :   (const Elem * elem,                                \
    1742             :    const Order o,                                    \
    1743             :    const std::vector<Point> & p,                     \
    1744             :    std::vector<std::vector<OutputShape>> & v,        \
    1745             :    const bool add_p_level)                           \
    1746             : {                                                    \
    1747             :   FE<MyDim,MyType>::default_all_shapes               \
    1748             :     (elem,o,p,v,add_p_level);                        \
    1749             : }                                                    \
    1750             :                                                      \
    1751             : template<>                                           \
    1752             : void FE<MyDim,MyType>::shapes                        \
    1753             :   (const Elem * elem,                                \
    1754             :    const Order o,                                    \
    1755             :    const unsigned int i,                             \
    1756             :    const std::vector<Point> & p,                     \
    1757             :    std::vector<OutputShape> & v,                     \
    1758             :    const bool add_p_level)                           \
    1759             : {                                                    \
    1760             :   FE<MyDim,MyType>::default_shapes                   \
    1761             :     (elem,o,i,p,v,add_p_level);                      \
    1762             : }                                                    \
    1763             :                                                      \
    1764             : template<>                                           \
    1765             : void FE<MyDim,MyType>::shape_derivs                  \
    1766             :   (const Elem * elem,                                \
    1767             :    const Order o,                                    \
    1768             :    const unsigned int i,                             \
    1769             :    const unsigned int j,                             \
    1770             :    const std::vector<Point> & p,                     \
    1771             :    std::vector<OutputShape> & v,                     \
    1772             :    const bool add_p_level)                           \
    1773             : {                                                    \
    1774             :   FE<MyDim,MyType>::default_shape_derivs             \
    1775             :     (elem,o,i,j,p,v,add_p_level);                    \
    1776             : }                                                    \
    1777             :                                                      \
    1778             : template<>                                           \
    1779             : void FE<MyDim,MyType>::all_shape_derivs              \
    1780             :   (const Elem * elem,                                \
    1781             :    const Order o,                                    \
    1782             :    const std::vector<Point> & p,                     \
    1783             :    std::vector<std::vector<OutputShape>> * comps[3], \
    1784             :    const bool add_p_level)                           \
    1785             : {                                                    \
    1786             :   FE<MyDim,MyType>::default_all_shape_derivs         \
    1787             :     (elem,o,p,comps,add_p_level);                    \
    1788             : }
    1789             : 
    1790             : 
    1791             : #endif // LIBMESH_FE_H

Generated by: LCOV version 1.14