LCOV - code coverage report
Current view: top level - src/fe - fe_lagrange_shape_2D.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 576 686 84.0 %
Date: 2025-08-19 19:27:09 Functions: 26 32 81.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             : // Local includes
      20             : #include "libmesh/fe.h"
      21             : #include "libmesh/elem.h"
      22             : #include "libmesh/fe_lagrange_shape_1D.h"
      23             : #include "libmesh/enum_to_string.h"
      24             : #include "libmesh/face_c0polygon.h"
      25             : 
      26             : // Anonymous namespace for functions shared by LAGRANGE and
      27             : // L2_LAGRANGE implementations. Implementations appear at the bottom
      28             : // of this file.
      29             : namespace
      30             : {
      31             : using namespace libMesh;
      32             : 
      33             : template <FEFamily T>
      34             : Real fe_lagrange_2D_shape(const ElemType,
      35             :                           const Elem * elem,
      36             :                           const Order order,
      37             :                           const unsigned int i,
      38             :                           const Point & p);
      39             : 
      40             : template <FEFamily T>
      41             : Real fe_lagrange_2D_shape_deriv(const ElemType type,
      42             :                                 const Elem * elem,
      43             :                                 const Order order,
      44             :                                 const unsigned int i,
      45             :                                 const unsigned int j,
      46             :                                 const Point & p);
      47             : 
      48             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      49             : 
      50             : template <FEFamily T>
      51             : Real fe_lagrange_2D_shape_second_deriv(const ElemType type,
      52             :                                        const Elem * elem,
      53             :                                        const Order order,
      54             :                                        const unsigned int i,
      55             :                                        const unsigned int j,
      56             :                                        const Point & p);
      57             : 
      58             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
      59             : 
      60             : } // anonymous namespace
      61             : 
      62             : 
      63             : 
      64             : namespace libMesh
      65             : {
      66             : 
      67             : 
      68   692933346 : LIBMESH_DEFAULT_VECTORIZED_FE(2,LAGRANGE)
      69     4072422 : LIBMESH_DEFAULT_VECTORIZED_FE(2,L2_LAGRANGE)
      70             : 
      71             : 
      72             : template <>
      73   801607763 : Real FE<2,LAGRANGE>::shape(const ElemType type,
      74             :                            const Order order,
      75             :                            const unsigned int i,
      76             :                            const Point & p)
      77             : {
      78   801607763 :   return fe_lagrange_2D_shape<LAGRANGE>(type, nullptr, order, i, p);
      79             : }
      80             : 
      81             : 
      82             : 
      83             : template <>
      84           0 : Real FE<2,L2_LAGRANGE>::shape(const ElemType type,
      85             :                               const Order order,
      86             :                               const unsigned int i,
      87             :                               const Point & p)
      88             : {
      89           0 :   return fe_lagrange_2D_shape<L2_LAGRANGE>(type, nullptr, order, i, p);
      90             : }
      91             : 
      92             : 
      93             : template <>
      94  1704317561 : Real FE<2,LAGRANGE>::shape(const Elem * elem,
      95             :                            const Order order,
      96             :                            const unsigned int i,
      97             :                            const Point & p,
      98             :                            const bool add_p_level)
      99             : {
     100   166266064 :   libmesh_assert(elem);
     101             : 
     102             :   // call the orientation-independent shape functions
     103  2013986183 :   return fe_lagrange_2D_shape<LAGRANGE>(elem->type(), elem, order + add_p_level*elem->p_level(), i, p);
     104             : }
     105             : 
     106             : 
     107             : 
     108             : template <>
     109     7215116 : Real FE<2,L2_LAGRANGE>::shape(const Elem * elem,
     110             :                               const Order order,
     111             :                               const unsigned int i,
     112             :                               const Point & p,
     113             :                               const bool add_p_level)
     114             : {
     115      606904 :   libmesh_assert(elem);
     116             : 
     117             :   // call the orientation-independent shape functions
     118     8428924 :   return fe_lagrange_2D_shape<L2_LAGRANGE>(elem->type(), elem, order + add_p_level*elem->p_level(), i, p);
     119             : }
     120             : 
     121             : 
     122             : template <>
     123  1133853900 : Real FE<2,LAGRANGE>::shape(const FEType fet,
     124             :                            const Elem * elem,
     125             :                            const unsigned int i,
     126             :                            const Point & p,
     127             :                            const bool add_p_level)
     128             : {
     129   105345897 :   libmesh_assert(elem);
     130  1310318300 :   return fe_lagrange_2D_shape<LAGRANGE>(elem->type(), elem, fet.order + add_p_level*elem->p_level(), i, p);
     131             : }
     132             : 
     133             : 
     134             : 
     135             : template <>
     136           0 : Real FE<2,L2_LAGRANGE>::shape(const FEType fet,
     137             :                               const Elem * elem,
     138             :                               const unsigned int i,
     139             :                               const Point & p,
     140             :                               const bool add_p_level)
     141             : {
     142           0 :   libmesh_assert(elem);
     143           0 :   return fe_lagrange_2D_shape<L2_LAGRANGE>(elem->type(), elem, fet.order + add_p_level*elem->p_level(), i, p);
     144             : }
     145             : 
     146             : 
     147             : template <>
     148   851765168 : Real FE<2,LAGRANGE>::shape_deriv(const ElemType type,
     149             :                                  const Order order,
     150             :                                  const unsigned int i,
     151             :                                  const unsigned int j,
     152             :                                  const Point & p)
     153             : {
     154   851765168 :   return fe_lagrange_2D_shape_deriv<LAGRANGE>(type, nullptr, order, i, j, p);
     155             : }
     156             : 
     157             : 
     158             : 
     159             : template <>
     160           0 : Real FE<2,L2_LAGRANGE>::shape_deriv(const ElemType type,
     161             :                                     const Order order,
     162             :                                     const unsigned int i,
     163             :                                     const unsigned int j,
     164             :                                     const Point & p)
     165             : {
     166           0 :   return fe_lagrange_2D_shape_deriv<L2_LAGRANGE>(type, nullptr, order, i, j, p);
     167             : }
     168             : 
     169             : 
     170             : 
     171             : template <>
     172   679542334 : Real FE<2,LAGRANGE>::shape_deriv(const Elem * elem,
     173             :                                  const Order order,
     174             :                                  const unsigned int i,
     175             :                                  const unsigned int j,
     176             :                                  const Point & p,
     177             :                                  const bool add_p_level)
     178             : {
     179    62143074 :   libmesh_assert(elem);
     180             : 
     181             :   // call the orientation-independent shape functions
     182   803804958 :   return fe_lagrange_2D_shape_deriv<LAGRANGE>(elem->type(), elem, order + add_p_level*elem->p_level(), i, j, p);
     183             : }
     184             : 
     185             : 
     186             : 
     187             : template <>
     188     1719616 : Real FE<2,L2_LAGRANGE>::shape_deriv(const Elem * elem,
     189             :                                     const Order order,
     190             :                                     const unsigned int i,
     191             :                                     const unsigned int j,
     192             :                                     const Point & p,
     193             :                                     const bool add_p_level)
     194             : {
     195      140040 :   libmesh_assert(elem);
     196             : 
     197             :   // call the orientation-independent shape functions
     198     1999696 :   return fe_lagrange_2D_shape_deriv<L2_LAGRANGE>(elem->type(), elem, order + add_p_level*elem->p_level(), i, j, p);
     199             : }
     200             : 
     201             : 
     202             : template <>
     203 15335067878 : Real FE<2,LAGRANGE>::shape_deriv(const FEType fet,
     204             :                                  const Elem * elem,
     205             :                                  const unsigned int i,
     206             :                                  const unsigned int j,
     207             :                                  const Point & p,
     208             :                                  const bool add_p_level)
     209             : {
     210  1130308006 :   libmesh_assert(elem);
     211 17591582478 :   return fe_lagrange_2D_shape_deriv<LAGRANGE>(elem->type(), elem, fet.order + add_p_level*elem->p_level(), i, j, p);
     212             : }
     213             : 
     214             : 
     215             : 
     216             : template <>
     217           0 : Real FE<2,L2_LAGRANGE>::shape_deriv(const FEType fet,
     218             :                                     const Elem * elem,
     219             :                                     const unsigned int i,
     220             :                                     const unsigned int j,
     221             :                                     const Point & p,
     222             :                                     const bool add_p_level)
     223             : {
     224           0 :   libmesh_assert(elem);
     225           0 :   return fe_lagrange_2D_shape_deriv<L2_LAGRANGE>(elem->type(), elem, fet.order + add_p_level*elem->p_level(), i, j, p);
     226             : }
     227             : 
     228             : 
     229             : 
     230             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     231             : 
     232             : template <>
     233   150865560 : Real FE<2,LAGRANGE>::shape_second_deriv(const ElemType type,
     234             :                                         const Order order,
     235             :                                         const unsigned int i,
     236             :                                         const unsigned int j,
     237             :                                         const Point & p)
     238             : {
     239   150865560 :   return fe_lagrange_2D_shape_second_deriv<LAGRANGE>(type, nullptr, order, i, j, p);
     240             : }
     241             : 
     242             : 
     243             : 
     244             : template <>
     245           0 : Real FE<2,L2_LAGRANGE>::shape_second_deriv(const ElemType type,
     246             :                                            const Order order,
     247             :                                            const unsigned int i,
     248             :                                            const unsigned int j,
     249             :                                            const Point & p)
     250             : {
     251           0 :   return fe_lagrange_2D_shape_second_deriv<L2_LAGRANGE>(type, nullptr, order, i, j, p);
     252             : }
     253             : 
     254             : 
     255             : 
     256             : template <>
     257     3916107 : Real FE<2,LAGRANGE>::shape_second_deriv(const Elem * elem,
     258             :                                         const Order order,
     259             :                                         const unsigned int i,
     260             :                                         const unsigned int j,
     261             :                                         const Point & p,
     262             :                                         const bool add_p_level)
     263             : {
     264      336354 :   libmesh_assert(elem);
     265             : 
     266             :   // call the orientation-independent shape functions
     267     4588815 :   return fe_lagrange_2D_shape_second_deriv<LAGRANGE>(elem->type(), elem, order + add_p_level*elem->p_level(), i, j, p);
     268             : }
     269             : 
     270             : 
     271             : 
     272             : template <>
     273      974544 : Real FE<2,L2_LAGRANGE>::shape_second_deriv(const Elem * elem,
     274             :                                            const Order order,
     275             :                                            const unsigned int i,
     276             :                                            const unsigned int j,
     277             :                                            const Point & p,
     278             :                                            const bool add_p_level)
     279             : {
     280       78876 :   libmesh_assert(elem);
     281             : 
     282             :   // call the orientation-independent shape functions
     283     1132296 :   return fe_lagrange_2D_shape_second_deriv<L2_LAGRANGE>(elem->type(), elem, order + add_p_level*elem->p_level(), i, j, p);
     284             : }
     285             : 
     286             : 
     287             : template <>
     288   151963722 : Real FE<2,LAGRANGE>::shape_second_deriv(const FEType fet,
     289             :                                         const Elem * elem,
     290             :                                         const unsigned int i,
     291             :                                         const unsigned int j,
     292             :                                         const Point & p,
     293             :                                         const bool add_p_level)
     294             : {
     295    12044028 :   libmesh_assert(elem);
     296   176051778 :   return fe_lagrange_2D_shape_second_deriv<LAGRANGE>(elem->type(), elem, fet.order + add_p_level*elem->p_level(), i, j, p);
     297             : }
     298             : 
     299             : 
     300             : 
     301             : template <>
     302           0 : Real FE<2,L2_LAGRANGE>::shape_second_deriv(const FEType fet,
     303             :                                            const Elem * elem,
     304             :                                            const unsigned int i,
     305             :                                            const unsigned int j,
     306             :                                            const Point & p,
     307             :                                            const bool add_p_level)
     308             : {
     309           0 :   libmesh_assert(elem);
     310           0 :   return fe_lagrange_2D_shape_second_deriv<L2_LAGRANGE>(elem->type(), elem, fet.order + add_p_level*elem->p_level(), i, j, p);
     311             : }
     312             : 
     313             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
     314             : 
     315             : } // namespace libMesh
     316             : 
     317             : 
     318             : 
     319             : 
     320             : // Anonymous namespace function definitions
     321             : namespace
     322             : {
     323             : using namespace libMesh;
     324             : 
     325             : template <FEFamily T>
     326  3646994340 : Real fe_lagrange_2D_shape(const ElemType type,
     327             :                           const Elem * elem,
     328             :                           const Order order,
     329             :                           const unsigned int i,
     330             :                           const Point & p)
     331             : {
     332             : #if LIBMESH_DIM > 1
     333             : 
     334  3646994340 :   switch (order)
     335             :     {
     336             :       // linear Lagrange shape functions
     337  1236011793 :     case FIRST:
     338             :       {
     339  1121034684 :         switch (type)
     340             :           {
     341  1069182392 :           case QUAD4:
     342             :           case QUADSHELL4:
     343             :           case QUAD8:
     344             :           case QUADSHELL8:
     345             :           case QUAD9:
     346             :           case QUADSHELL9:
     347             :             {
     348             :               // Compute quad shape functions as a tensor-product
     349  1069182392 :               const Real xi  = p(0);
     350  1069182392 :               const Real eta = p(1);
     351             : 
     352   104683048 :               libmesh_assert_less (i, 4);
     353             : 
     354             :               //                                0  1  2  3
     355             :               static const unsigned int i0[] = {0, 1, 1, 0};
     356             :               static const unsigned int i1[] = {0, 0, 1, 1};
     357             : 
     358  1069182392 :               return (fe_lagrange_1D_linear_shape(i0[i], xi)*
     359  1069182392 :                       fe_lagrange_1D_linear_shape(i1[i], eta));
     360             :             }
     361             : 
     362   166125201 :           case TRI3:
     363             :           case TRISHELL3:
     364             :           case TRI6:
     365             :           case TRI7:
     366             :             {
     367   166125201 :               const Real zeta1 = p(0);
     368   166125201 :               const Real zeta2 = p(1);
     369   166125201 :               const Real zeta0 = 1. - zeta1 - zeta2;
     370             : 
     371    14899806 :               libmesh_assert_less (i, 3);
     372             : 
     373   166125201 :               switch(i)
     374             :                 {
     375     4966602 :                 case 0:
     376     4966602 :                   return zeta0;
     377             : 
     378    55375067 :                 case 1:
     379    55375067 :                   return zeta1;
     380             : 
     381    55375067 :                 case 2:
     382    55375067 :                   return zeta2;
     383             : 
     384           0 :                 default:
     385           0 :                   libmesh_error_msg("Invalid shape function index i = " << i);
     386             :                 }
     387             :             }
     388             : 
     389      704200 :           case C0POLYGON:
     390             :             {
     391             :               // C0Polygon requires using newer FE APIs
     392      704200 :               if (!elem)
     393           0 :                 libmesh_error_msg("Code (see stack trace) used an outdated FE function overload.\n"
     394             :                                   "Shape functions on a C0Polygon are not defined by its ElemType alone.");
     395             : 
     396       67025 :               libmesh_assert(elem->type() == C0POLYGON);
     397             : 
     398       67025 :               const C0Polygon & poly = *cast_ptr<const C0Polygon *>(elem);
     399             : 
     400             :               // We can't use a small tolerance here, because in
     401             :               // inverse_map() Newton might hand us intermediate
     402             :               // iterates outside the polygon.
     403      704200 :               const auto [s, a, b] = poly.subtriangle_coordinates(p, 100);
     404      704200 :               if (s == invalid_uint)
     405           0 :                 return 0;
     406       67025 :               libmesh_assert_less(s, poly.n_subtriangles());
     407             : 
     408      704200 :               const auto subtri = poly.subtriangle(s);
     409             : 
     410             :               // Avoid signed/unsigned comparison warnings
     411      704200 :               const int nodei = i;
     412      704200 :               if (nodei == subtri[0])
     413      140840 :                 return 1-a-b;
     414      563360 :               if (nodei == subtri[1])
     415      140840 :                 return a;
     416      422520 :               if (nodei == subtri[2])
     417      140840 :                 return b;
     418             : 
     419             :               // Basis function i is not supported on p's subtriangle
     420       26810 :               return 0;
     421             :             }
     422             : 
     423           0 :           default:
     424           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
     425             :           }
     426             :       }
     427             : 
     428             : 
     429             :       // quadratic Lagrange shape functions
     430  1418870298 :     case SECOND:
     431             :       {
     432  1302423609 :         switch (type)
     433             :           {
     434    31236744 :           case QUAD8:
     435             :           case QUADSHELL8:
     436             :             {
     437    31236744 :               const Real xi  = p(0);
     438    31236744 :               const Real eta = p(1);
     439             : 
     440     2687088 :               libmesh_assert_less (i, 8);
     441             : 
     442    31236744 :               switch (i)
     443             :                 {
     444     3904593 :                 case 0:
     445     3904593 :                   return .25*(1. - xi)*(1. - eta)*(-1. - xi - eta);
     446             : 
     447     3904593 :                 case 1:
     448     3904593 :                   return .25*(1. + xi)*(1. - eta)*(-1. + xi - eta);
     449             : 
     450     3904593 :                 case 2:
     451     3904593 :                   return .25*(1. + xi)*(1. + eta)*(-1. + xi + eta);
     452             : 
     453     3904593 :                 case 3:
     454     3904593 :                   return .25*(1. - xi)*(1. + eta)*(-1. - xi + eta);
     455             : 
     456     3904593 :                 case 4:
     457     3904593 :                   return .5*(1. - xi*xi)*(1. - eta);
     458             : 
     459     3904593 :                 case 5:
     460     3904593 :                   return .5*(1. + xi)*(1. - eta*eta);
     461             : 
     462     3904593 :                 case 6:
     463     3904593 :                   return .5*(1. - xi*xi)*(1. + eta);
     464             : 
     465     3904593 :                 case 7:
     466     3904593 :                   return .5*(1. - xi)*(1. - eta*eta);
     467             : 
     468           0 :                 default:
     469           0 :                   libmesh_error_msg("Invalid shape function index i = " << i);
     470             :                 }
     471             :             }
     472             : 
     473   748143342 :           case QUAD4:
     474        4743 :             libmesh_assert_msg(T == L2_LAGRANGE,
     475             :                                "High order on first order elements only supported for L2 families");
     476             :             libmesh_fallthrough();
     477    80335647 :           case QUAD9:
     478             :           case QUADSHELL9:
     479             :             {
     480             : 
     481             :               // Compute quad shape functions as a tensor-product
     482   828483732 :               const Real xi  = p(0);
     483   828483732 :               const Real eta = p(1);
     484             : 
     485    80345133 :               libmesh_assert_less (i, 9);
     486             : 
     487             :               //                                0  1  2  3  4  5  6  7  8
     488             :               static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2};
     489             :               static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2};
     490             : 
     491   828483732 :               return (fe_lagrange_1D_quadratic_shape(i0[i], xi)*
     492   828483732 :                       fe_lagrange_1D_quadratic_shape(i1[i], eta));
     493             :             }
     494             : 
     495   502500960 :           case TRI3:
     496        3582 :             libmesh_assert_msg(T == L2_LAGRANGE,
     497             :                                "High order on first order elements only supported for L2 families");
     498             :             libmesh_fallthrough();
     499    56404098 :           case TRI6:
     500             :           case TRI7:
     501             :             {
     502   559149822 :               const Real zeta1 = p(0);
     503   559149822 :               const Real zeta2 = p(1);
     504   559149822 :               const Real zeta0 = 1. - zeta1 - zeta2;
     505             : 
     506    56652444 :               libmesh_assert_less (i, 6);
     507             : 
     508   559149822 :               switch(i)
     509             :                 {
     510    93191637 :                 case 0:
     511    93191637 :                   return 2.*zeta0*(zeta0-0.5);
     512             : 
     513    93191637 :                 case 1:
     514    93191637 :                   return 2.*zeta1*(zeta1-0.5);
     515             : 
     516    93191637 :                 case 2:
     517    93191637 :                   return 2.*zeta2*(zeta2-0.5);
     518             : 
     519    93191637 :                 case 3:
     520    93191637 :                   return 4.*zeta0*zeta1;
     521             : 
     522    93191637 :                 case 4:
     523    93191637 :                   return 4.*zeta1*zeta2;
     524             : 
     525    93191637 :                 case 5:
     526    93191637 :                   return 4.*zeta2*zeta0;
     527             : 
     528           0 :                 default:
     529           0 :                   libmesh_error_msg("Invalid shape function index i = " << i);
     530             :                 }
     531             :             }
     532             : 
     533           0 :           default:
     534           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
     535             :           }
     536             :       }
     537             : 
     538             : 
     539             : 
     540             :       // "cubic" (one cubic bubble) Lagrange shape functions on TRI7
     541   992112249 :     case THIRD:
     542             :       {
     543   992112249 :         switch (type)
     544             :           {
     545   992112249 :           case TRI7:
     546             :             {
     547   992112249 :               const Real zeta1 = p(0);
     548   992112249 :               const Real zeta2 = p(1);
     549   992112249 :               const Real zeta0 = 1. - zeta1 - zeta2;
     550   992112249 :               const Real bubble_27th = zeta0*zeta1*zeta2;
     551             : 
     552    84155654 :               libmesh_assert_less (i, 7);
     553             : 
     554   992112249 :               switch(i)
     555             :                 {
     556   135393747 :                 case 0:
     557   135393747 :                   return 2.*zeta0*(zeta0-0.5) + 3.*bubble_27th;
     558             : 
     559   135393747 :                 case 1:
     560   135393747 :                   return 2.*zeta1*(zeta1-0.5) + 3.*bubble_27th;
     561             : 
     562   135393747 :                 case 2:
     563   135393747 :                   return 2.*zeta2*(zeta2-0.5) + 3.*bubble_27th;
     564             : 
     565   135393747 :                 case 3:
     566   135393747 :                   return 4.*zeta0*zeta1 - 12.*bubble_27th;
     567             : 
     568   135393747 :                 case 4:
     569   135393747 :                   return 4.*zeta1*zeta2 - 12.*bubble_27th;
     570             : 
     571   135393747 :                 case 5:
     572   135393747 :                   return 4.*zeta2*zeta0 - 12.*bubble_27th;
     573             : 
     574   179749767 :                 case 6:
     575   179749767 :                   return 27.*bubble_27th;
     576             : 
     577           0 :                 default:
     578           0 :                   libmesh_error_msg("Invalid shape function index i = " << i);
     579             :                 }
     580             :             }
     581             : 
     582           0 :           default:
     583           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
     584             :           }
     585             :       } // end case THIRD
     586             : 
     587             : 
     588             : 
     589             :       // unsupported order
     590           0 :     default:
     591           0 :       libmesh_error_msg("ERROR: Unsupported 2D FE order: " << order);
     592             :     }
     593             : #else // LIBMESH_DIM > 1
     594             :   libmesh_ignore(type, order, i, p);
     595             :   libmesh_not_implemented();
     596             : #endif
     597             : }
     598             : 
     599             : 
     600             : 
     601             : template <FEFamily T>
     602 16868094996 : Real fe_lagrange_2D_shape_deriv(const ElemType type,
     603             :                                 const Elem * elem,
     604             :                                 const Order order,
     605             :                                 const unsigned int i,
     606             :                                 const unsigned int j,
     607             :                                 const Point & p)
     608             : {
     609             : #if LIBMESH_DIM > 1
     610             : 
     611  1265045440 :   libmesh_assert_less (j, 2);
     612             : 
     613 16868094996 :   switch (order)
     614             :     {
     615             :       // linear Lagrange shape functions
     616   461591924 :     case FIRST:
     617             :       {
     618   411842878 :         switch (type)
     619             :           {
     620   326901376 :           case QUAD4:
     621             :           case QUADSHELL4:
     622             :           case QUAD8:
     623             :           case QUADSHELL8:
     624             :           case QUAD9:
     625             :           case QUADSHELL9:
     626             :             {
     627             :               // Compute quad shape functions as a tensor-product
     628   326901376 :               const Real xi  = p(0);
     629   326901376 :               const Real eta = p(1);
     630             : 
     631    38651416 :               libmesh_assert_less (i, 4);
     632             : 
     633             :               //                                0  1  2  3
     634             :               static const unsigned int i0[] = {0, 1, 1, 0};
     635             :               static const unsigned int i1[] = {0, 0, 1, 1};
     636             : 
     637   326901376 :               switch (j)
     638             :                 {
     639             :                   // d()/dxi
     640   163450688 :                 case 0:
     641   163450688 :                   return (fe_lagrange_1D_linear_shape_deriv(i0[i], 0, xi)*
     642   163450688 :                           fe_lagrange_1D_linear_shape      (i1[i], eta));
     643             : 
     644             :                   // d()/deta
     645   163450688 :                 case 1:
     646   163450688 :                   return (fe_lagrange_1D_linear_shape      (i0[i], xi)*
     647   163450688 :                           fe_lagrange_1D_linear_shape_deriv(i1[i], 0, eta));
     648             : 
     649           0 :                 default:
     650           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
     651             :                 }
     652             :             }
     653             : 
     654   133391748 :           case TRI3:
     655             :           case TRISHELL3:
     656             :           case TRI6:
     657             :           case TRI7:
     658             :             {
     659    11264616 :               libmesh_assert_less (i, 3);
     660             : 
     661    11264616 :               const Real dzeta0dxi  = -1.;
     662    11264616 :               const Real dzeta1dxi  = 1.;
     663    11264616 :               const Real dzeta2dxi  = 0.;
     664             : 
     665    11264616 :               const Real dzeta0deta = -1.;
     666    11264616 :               const Real dzeta1deta = 0.;
     667    11264616 :               const Real dzeta2deta = 1.;
     668             : 
     669   133391748 :               switch (j)
     670             :                 {
     671             :                   // d()/dxi
     672    66695874 :                 case 0:
     673             :                   {
     674    61063638 :                     switch(i)
     675             :                       {
     676     1877436 :                       case 0:
     677     1877436 :                         return dzeta0dxi;
     678             : 
     679     1877436 :                       case 1:
     680     1877436 :                         return dzeta1dxi;
     681             : 
     682     1877436 :                       case 2:
     683     1877436 :                         return dzeta2dxi;
     684             : 
     685           0 :                       default:
     686           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
     687             :                       }
     688             :                   }
     689             :                   // d()/deta
     690    66695874 :                 case 1:
     691             :                   {
     692    61063638 :                     switch(i)
     693             :                       {
     694     1877436 :                       case 0:
     695     1877436 :                         return dzeta0deta;
     696             : 
     697     1877436 :                       case 1:
     698     1877436 :                         return dzeta1deta;
     699             : 
     700     1877436 :                       case 2:
     701     1877436 :                         return dzeta2deta;
     702             : 
     703           0 :                       default:
     704           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
     705             :                       }
     706             :                   }
     707           0 :                 default:
     708           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
     709             :                 }
     710             :             }
     711             : 
     712     1298800 :           case C0POLYGON:
     713             :             {
     714             :               // C0Polygon requires using newer FE APIs
     715     1298800 :               if (!elem)
     716           0 :                 libmesh_error_msg("Code (see stack trace) used an outdated FE function overload.\n"
     717             :                                   "Shape functions on a C0Polygon are not defined by its ElemType alone.");
     718             : 
     719      106510 :               libmesh_assert(elem->type() == C0POLYGON);
     720             : 
     721      106510 :               const C0Polygon & poly = *cast_ptr<const C0Polygon *>(elem);
     722             : 
     723             :               // We can't use a small tolerance here, because in
     724             :               // inverse_map() Newton might hand us intermediate
     725             :               // iterates outside the polygon.
     726     1298800 :               const auto [s, a, b] = poly.subtriangle_coordinates(p, 100);
     727     1298800 :               if (s == invalid_uint)
     728           0 :                 return 0;
     729      106510 :               libmesh_assert_less(s, poly.n_subtriangles());
     730             : 
     731     1298800 :               const auto subtri = poly.subtriangle(s);
     732             : 
     733             :               // Find derivatives w.r.t. subtriangle barycentric
     734             :               // coordinates
     735      106510 :               Real du_da = 0, du_db = 0;
     736             : 
     737             :               // Avoid signed/unsigned comparison warnings
     738     1298800 :               const int nodei = i;
     739     1298800 :               if (nodei == subtri[0])
     740       21302 :                 du_da = du_db = -1;
     741     1039040 :               else if (nodei == subtri[1])
     742       21302 :                 du_da = 1;
     743      779280 :               else if (nodei == subtri[2])
     744       21302 :                 du_db = 1;
     745             :               else
     746             :                 // Basis function i is not supported on p's subtriangle
     747       42604 :                 return 0;
     748             : 
     749             :               // We want to return derivatives with respect to xi and
     750             :               // eta in master space for the polygon, but what we
     751             :               // calculated above are with respect to xi and eta
     752             :               // coordinates for a master *triangle*.  We need to
     753             :               // convert from one to the other.
     754             : 
     755      779280 :               const auto master_points = poly.master_subtriangle(s);
     756             : 
     757      779280 :               const Real dxi_da = master_points[1](0) - master_points[0](0);
     758      779280 :               const Real dxi_db = master_points[2](0) - master_points[0](0);
     759      779280 :               const Real deta_da = master_points[1](1) - master_points[0](1);
     760      779280 :               const Real deta_db = master_points[2](1) - master_points[0](1);
     761      779280 :               const Real jac = dxi_da*deta_db - dxi_db*deta_da;
     762             : 
     763      779280 :               switch (j)
     764             :                 {
     765             :                   // d()/dxi
     766      389640 :                 case 0:
     767             :                   {
     768      389640 :                     const Real da_dxi = deta_db / jac;
     769      389640 :                     const Real db_dxi = -deta_da / jac;
     770      389640 :                     return du_da*da_dxi + du_db*db_dxi;
     771             :                   }
     772             :                   // d()/deta
     773      389640 :                 case 1:
     774             :                   {
     775      389640 :                     const Real da_deta = -dxi_db / jac;
     776      389640 :                     const Real db_deta = dxi_da / jac;
     777      389640 :                     return du_da*da_deta + du_db*db_deta;
     778             :                   }
     779           0 :                 default:
     780           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
     781             :                 }
     782             :             }
     783             : 
     784           0 :           default:
     785           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
     786             :           }
     787             :       }
     788             : 
     789             : 
     790             :       // quadratic Lagrange shape functions
     791 14898884448 :     case SECOND:
     792             :       {
     793 13809998144 :         switch (type)
     794             :           {
     795    59970336 :           case QUAD8:
     796             :           case QUADSHELL8:
     797             :             {
     798    59970336 :               const Real xi  = p(0);
     799    59970336 :               const Real eta = p(1);
     800             : 
     801     4863104 :               libmesh_assert_less (i, 8);
     802             : 
     803    59970336 :               switch (j)
     804             :                 {
     805             :                   // d/dxi
     806    29985168 :                 case 0:
     807    29985168 :                   switch (i)
     808             :                     {
     809     3748146 :                     case 0:
     810     4356030 :                       return .25*(1. - eta)*((1. - xi)*(-1.) +
     811     3748146 :                                              (-1.)*(-1. - xi - eta));
     812             : 
     813     3748146 :                     case 1:
     814     4356030 :                       return .25*(1. - eta)*((1. + xi)*(1.) +
     815     3748146 :                                              (1.)*(-1. + xi - eta));
     816             : 
     817     3748146 :                     case 2:
     818     4356030 :                       return .25*(1. + eta)*((1. + xi)*(1.) +
     819     3748146 :                                              (1.)*(-1. + xi + eta));
     820             : 
     821     3748146 :                     case 3:
     822     4356030 :                       return .25*(1. + eta)*((1. - xi)*(-1.) +
     823     3748146 :                                              (-1.)*(-1. - xi + eta));
     824             : 
     825     3748146 :                     case 4:
     826     3748146 :                       return .5*(-2.*xi)*(1. - eta);
     827             : 
     828     3748146 :                     case 5:
     829     3748146 :                       return .5*(1.)*(1. - eta*eta);
     830             : 
     831     3748146 :                     case 6:
     832     3748146 :                       return .5*(-2.*xi)*(1. + eta);
     833             : 
     834     3748146 :                     case 7:
     835     3748146 :                       return .5*(-1.)*(1. - eta*eta);
     836             : 
     837           0 :                     default:
     838           0 :                       libmesh_error_msg("Invalid shape function index i = " << i);
     839             :                     }
     840             : 
     841             :                   // d/deta
     842    29985168 :                 case 1:
     843    29985168 :                   switch (i)
     844             :                     {
     845     3748146 :                     case 0:
     846     4356030 :                       return .25*(1. - xi)*((1. - eta)*(-1.) +
     847     3748146 :                                             (-1.)*(-1. - xi - eta));
     848             : 
     849     3748146 :                     case 1:
     850     4356030 :                       return .25*(1. + xi)*((1. - eta)*(-1.) +
     851     3748146 :                                             (-1.)*(-1. + xi - eta));
     852             : 
     853     3748146 :                     case 2:
     854     4356030 :                       return .25*(1. + xi)*((1. + eta)*(1.) +
     855     3748146 :                                             (1.)*(-1. + xi + eta));
     856             : 
     857     3748146 :                     case 3:
     858     4356030 :                       return .25*(1. - xi)*((1. + eta)*(1.) +
     859     3748146 :                                             (1.)*(-1. - xi + eta));
     860             : 
     861     3748146 :                     case 4:
     862     3748146 :                       return .5*(1. - xi*xi)*(-1.);
     863             : 
     864     3748146 :                     case 5:
     865     3748146 :                       return .5*(1. + xi)*(-2.*eta);
     866             : 
     867     3748146 :                     case 6:
     868     3748146 :                       return .5*(1. - xi*xi)*(1.);
     869             : 
     870     3748146 :                     case 7:
     871     3748146 :                       return .5*(1. - xi)*(-2.*eta);
     872             : 
     873           0 :                     default:
     874           0 :                       libmesh_error_msg("Invalid shape function index i = " << i);
     875             :                     }
     876             : 
     877           0 :                 default:
     878           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
     879             :                 }
     880             :             }
     881             : 
     882  1850488434 :           case QUAD4:
     883        7866 :             libmesh_assert_msg(T == L2_LAGRANGE,
     884             :                                "High order on first order elements only supported for L2 families");
     885             :             libmesh_fallthrough();
     886   129656016 :           case QUAD9:
     887             :           case QUADSHELL9:
     888             :             {
     889             :               // Compute quad shape functions as a tensor-product
     890  1980152316 :               const Real xi  = p(0);
     891  1980152316 :               const Real eta = p(1);
     892             : 
     893   129671748 :               libmesh_assert_less (i, 9);
     894             : 
     895             :               //                                0  1  2  3  4  5  6  7  8
     896             :               static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2};
     897             :               static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2};
     898             : 
     899  1980152316 :               switch (j)
     900             :                 {
     901             :                   // d()/dxi
     902   990076158 :                 case 0:
     903   990076158 :                   return (fe_lagrange_1D_quadratic_shape_deriv(i0[i], 0, xi)*
     904   990076158 :                           fe_lagrange_1D_quadratic_shape      (i1[i], eta));
     905             : 
     906             :                   // d()/deta
     907   990076158 :                 case 1:
     908   990076158 :                   return (fe_lagrange_1D_quadratic_shape      (i0[i], xi)*
     909   990076158 :                           fe_lagrange_1D_quadratic_shape_deriv(i1[i], 0, eta));
     910             : 
     911           0 :                 default:
     912           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
     913             :                 }
     914             :             }
     915             : 
     916 11902635432 :           case TRI3:
     917        5484 :             libmesh_assert_msg(T == L2_LAGRANGE,
     918             :                                "High order on first order elements only supported for L2 families");
     919             :             libmesh_fallthrough();
     920   956027844 :           case TRI6:
     921             :           case TRI7:
     922             :             {
     923   956131848 :               libmesh_assert_less (i, 6);
     924             : 
     925 12858761796 :               const Real zeta1 = p(0);
     926 12858761796 :               const Real zeta2 = p(1);
     927 12858761796 :               const Real zeta0 = 1. - zeta1 - zeta2;
     928             : 
     929   956131848 :               const Real dzeta0dxi  = -1.;
     930   956131848 :               const Real dzeta1dxi  = 1.;
     931   956131848 :               const Real dzeta2dxi  = 0.;
     932             : 
     933   956131848 :               const Real dzeta0deta = -1.;
     934   956131848 :               const Real dzeta1deta = 0.;
     935   956131848 :               const Real dzeta2deta = 1.;
     936             : 
     937 12858761796 :               switch(j)
     938             :                 {
     939  6429380898 :                 case 0:
     940             :                   {
     941  6429380898 :                     switch(i)
     942             :                       {
     943  1071563483 :                       case 0:
     944  1071563483 :                         return (4.*zeta0-1.)*dzeta0dxi;
     945             : 
     946  1071563483 :                       case 1:
     947  1071563483 :                         return (4.*zeta1-1.)*dzeta1dxi;
     948             : 
     949  1071563483 :                       case 2:
     950  1071563483 :                         return (4.*zeta2-1.)*dzeta2dxi;
     951             : 
     952  1071563483 :                       case 3:
     953  1071563483 :                         return 4.*zeta1*dzeta0dxi + 4.*zeta0*dzeta1dxi;
     954             : 
     955  1071563483 :                       case 4:
     956  1071563483 :                         return 4.*zeta2*dzeta1dxi + 4.*zeta1*dzeta2dxi;
     957             : 
     958  1071563483 :                       case 5:
     959  1071563483 :                         return 4.*zeta2*dzeta0dxi + 4*zeta0*dzeta2dxi;
     960             : 
     961           0 :                       default:
     962           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
     963             :                       }
     964             :                   }
     965             : 
     966  6429380898 :                 case 1:
     967             :                   {
     968  6429380898 :                     switch(i)
     969             :                       {
     970  1071563483 :                       case 0:
     971  1071563483 :                         return (4.*zeta0-1.)*dzeta0deta;
     972             : 
     973  1071563483 :                       case 1:
     974  1071563483 :                         return (4.*zeta1-1.)*dzeta1deta;
     975             : 
     976  1071563483 :                       case 2:
     977  1071563483 :                         return (4.*zeta2-1.)*dzeta2deta;
     978             : 
     979  1071563483 :                       case 3:
     980  1071563483 :                         return 4.*zeta1*dzeta0deta + 4.*zeta0*dzeta1deta;
     981             : 
     982  1071563483 :                       case 4:
     983  1071563483 :                         return 4.*zeta2*dzeta1deta + 4.*zeta1*dzeta2deta;
     984             : 
     985  1071563483 :                       case 5:
     986  1071563483 :                         return 4.*zeta2*dzeta0deta + 4*zeta0*dzeta2deta;
     987             : 
     988           0 :                       default:
     989           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
     990             :                       }
     991             :                   }
     992           0 :                 default:
     993           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
     994             :                 }
     995             :             }
     996             : 
     997           0 :           default:
     998           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
     999             :           }
    1000             :       }
    1001             : 
    1002             : 
    1003             : 
    1004             :       // "cubic" (one cubic bubble) Lagrange shape functions on TRI7
    1005  1507618624 :     case THIRD:
    1006             :       {
    1007  1507618624 :         switch (type)
    1008             :           {
    1009  1507618624 :           case TRI7:
    1010             :             {
    1011   124356198 :               libmesh_assert_less (i, 7);
    1012             : 
    1013  1507618624 :               const Real zeta1 = p(0);
    1014  1507618624 :               const Real zeta2 = p(1);
    1015  1507618624 :               const Real zeta0 = 1. - zeta1 - zeta2;
    1016             :               // const Real bubble_27th = zeta0*zeta1*zeta2;
    1017             : 
    1018   124356198 :               const Real dzeta0dxi  = -1.;
    1019   124356198 :               const Real dzeta1dxi  = 1.;
    1020   124356198 :               const Real dzeta2dxi  = 0.;
    1021  1507618624 :               const Real dbubbledxi = zeta2 * (1. - 2.*zeta1 - zeta2);
    1022             : 
    1023   124356198 :               const Real dzeta0deta = -1.;
    1024   124356198 :               const Real dzeta1deta = 0.;
    1025   124356198 :               const Real dzeta2deta = 1.;
    1026  1507618624 :               const Real dbubbledeta= zeta1 * (1. - zeta1 - 2.*zeta2);
    1027             : 
    1028  1507618624 :               switch(j)
    1029             :                 {
    1030   753809312 :                 case 0:
    1031             :                   {
    1032   753809312 :                     switch(i)
    1033             :                       {
    1034   104126846 :                       case 0:
    1035   104126846 :                         return (4.*zeta0-1.)*dzeta0dxi + 3.*dbubbledxi;
    1036             : 
    1037   104126846 :                       case 1:
    1038   104126846 :                         return (4.*zeta1-1.)*dzeta1dxi + 3.*dbubbledxi;
    1039             : 
    1040   104126846 :                       case 2:
    1041   104126846 :                         return (4.*zeta2-1.)*dzeta2dxi + 3.*dbubbledxi;
    1042             : 
    1043   104126846 :                       case 3:
    1044   104126846 :                         return 4.*zeta1*dzeta0dxi + 4.*zeta0*dzeta1dxi - 12.*dbubbledxi;
    1045             : 
    1046   104126846 :                       case 4:
    1047   104126846 :                         return 4.*zeta2*dzeta1dxi + 4.*zeta1*dzeta2dxi - 12.*dbubbledxi;
    1048             : 
    1049   104126846 :                       case 5:
    1050   104126846 :                         return 4.*zeta2*dzeta0dxi + 4*zeta0*dzeta2dxi - 12.*dbubbledxi;
    1051             : 
    1052   129048236 :                       case 6:
    1053   129048236 :                         return 27.*dbubbledxi;
    1054             : 
    1055           0 :                       default:
    1056           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1057             :                       }
    1058             :                   }
    1059             : 
    1060   753809312 :                 case 1:
    1061             :                   {
    1062   753809312 :                     switch(i)
    1063             :                       {
    1064   104126846 :                       case 0:
    1065   104126846 :                         return (4.*zeta0-1.)*dzeta0deta + 3.*dbubbledeta;
    1066             : 
    1067   104126846 :                       case 1:
    1068   104126846 :                         return (4.*zeta1-1.)*dzeta1deta + 3.*dbubbledeta;
    1069             : 
    1070   104126846 :                       case 2:
    1071   104126846 :                         return (4.*zeta2-1.)*dzeta2deta + 3.*dbubbledeta;
    1072             : 
    1073   104126846 :                       case 3:
    1074   104126846 :                         return 4.*zeta1*dzeta0deta + 4.*zeta0*dzeta1deta - 12.*dbubbledeta;
    1075             : 
    1076   104126846 :                       case 4:
    1077   104126846 :                         return 4.*zeta2*dzeta1deta + 4.*zeta1*dzeta2deta - 12.*dbubbledeta;
    1078             : 
    1079   104126846 :                       case 5:
    1080   104126846 :                         return 4.*zeta2*dzeta0deta + 4*zeta0*dzeta2deta - 12.*dbubbledeta;
    1081             : 
    1082   129048236 :                       case 6:
    1083   129048236 :                         return 27.*dbubbledeta;
    1084             : 
    1085           0 :                       default:
    1086           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1087             :                       }
    1088             :                   }
    1089           0 :                 default:
    1090           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
    1091             :                 }
    1092             :             }
    1093             : 
    1094           0 :           default:
    1095           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
    1096             :           }
    1097             :       } // end case THIRD
    1098             : 
    1099             : 
    1100             : 
    1101             :       // unsupported order
    1102           0 :     default:
    1103           0 :       libmesh_error_msg("ERROR: Unsupported 2D FE order: " << order);
    1104             :     }
    1105             : #else // LIBMESH_DIM > 1
    1106             :   libmesh_ignore(type, order, i, j, p);
    1107             :   libmesh_not_implemented();
    1108             : #endif
    1109             : }
    1110             : 
    1111             : 
    1112             : 
    1113             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
    1114             : 
    1115             : template <FEFamily T>
    1116   282140523 : Real fe_lagrange_2D_shape_second_deriv(const ElemType type,
    1117             :                                        const Elem *,
    1118             :                                        const Order order,
    1119             :                                        const unsigned int i,
    1120             :                                        const unsigned int j,
    1121             :                                        const Point & p)
    1122             : {
    1123             : #if LIBMESH_DIM > 1
    1124             : 
    1125             :   // j = 0 ==> d^2 phi / dxi^2
    1126             :   // j = 1 ==> d^2 phi / dxi deta
    1127             :   // j = 2 ==> d^2 phi / deta^2
    1128    25579410 :   libmesh_assert_less (j, 3);
    1129             : 
    1130   282140523 :   switch (order)
    1131             :     {
    1132             :       // linear Lagrange shape functions
    1133     2833725 :     case FIRST:
    1134             :       {
    1135     2833725 :         switch (type)
    1136             :           {
    1137     1739052 :           case QUAD4:
    1138             :           case QUADSHELL4:
    1139             :           case QUAD8:
    1140             :           case QUADSHELL8:
    1141             :           case QUAD9:
    1142             :           case QUADSHELL9:
    1143             :             {
    1144             :               // Compute quad shape functions as a tensor-product
    1145     1739052 :               const Real xi  = p(0);
    1146     1739052 :               const Real eta = p(1);
    1147             : 
    1148      157200 :               libmesh_assert_less (i, 4);
    1149             : 
    1150             :               //                                0  1  2  3
    1151             :               static const unsigned int i0[] = {0, 1, 1, 0};
    1152             :               static const unsigned int i1[] = {0, 0, 1, 1};
    1153             : 
    1154     1739052 :               switch (j)
    1155             :                 {
    1156             :                   // d^2() / dxi^2
    1157       52400 :                 case 0:
    1158       52400 :                   return 0.;
    1159             : 
    1160             :                   // d^2() / dxi deta
    1161      579684 :                 case 1:
    1162      579684 :                   return (fe_lagrange_1D_linear_shape_deriv(i0[i], 0, xi)*
    1163      579684 :                           fe_lagrange_1D_linear_shape_deriv(i1[i], 0, eta));
    1164             : 
    1165             :                   // d^2() / deta^2
    1166       52400 :                 case 2:
    1167       52400 :                   return 0.;
    1168             : 
    1169           0 :                 default:
    1170           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
    1171             :                 }
    1172             :             }
    1173             : 
    1174             :           // All second derivatives for linear triangles are zero.
    1175      101913 :           case TRI3:
    1176             :           case TRISHELL3:
    1177             :           case TRI6:
    1178             :           case TRI7:
    1179             : 
    1180             :           // All second derivatives for piecewise-linear polygons are
    1181             :           // zero or dirac-type distributions, but we can't put the
    1182             :           // latter in a Real, so beware when integrating...
    1183             :           case C0POLYGON:
    1184             :             {
    1185      101913 :               return 0.;
    1186             :             }
    1187             : 
    1188           0 :           default:
    1189           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
    1190             : 
    1191             :           } // end switch (type)
    1192             :       } // end case FIRST
    1193             : 
    1194             : 
    1195             :       // quadratic Lagrange shape functions
    1196   127588464 :     case SECOND:
    1197             :       {
    1198   127588464 :         switch (type)
    1199             :           {
    1200     4866912 :           case QUAD8:
    1201             :           case QUADSHELL8:
    1202             :             {
    1203     4866912 :               const Real xi  = p(0);
    1204     4866912 :               const Real eta = p(1);
    1205             : 
    1206      439488 :               libmesh_assert_less (j, 3);
    1207             : 
    1208     4866912 :               switch (j)
    1209             :                 {
    1210             :                   // d^2() / dxi^2
    1211     1622304 :                 case 0:
    1212             :                   {
    1213     1622304 :                     switch (i)
    1214             :                       {
    1215      405576 :                       case 0:
    1216             :                       case 1:
    1217      405576 :                         return 0.5*(1.-eta);
    1218             : 
    1219      405576 :                       case 2:
    1220             :                       case 3:
    1221      405576 :                         return 0.5*(1.+eta);
    1222             : 
    1223      202788 :                       case 4:
    1224      202788 :                         return eta - 1.;
    1225             : 
    1226       36624 :                       case 5:
    1227             :                       case 7:
    1228       36624 :                         return 0.0;
    1229             : 
    1230      202788 :                       case 6:
    1231      202788 :                         return -1. - eta;
    1232             : 
    1233           0 :                       default:
    1234           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1235             :                       }
    1236             :                   }
    1237             : 
    1238             :                   // d^2() / dxi deta
    1239     1622304 :                 case 1:
    1240             :                   {
    1241     1622304 :                     switch (i)
    1242             :                       {
    1243      202788 :                       case 0:
    1244      202788 :                         return 0.25*( 1. - 2.*xi - 2.*eta);
    1245             : 
    1246      202788 :                       case 1:
    1247      202788 :                         return 0.25*(-1. - 2.*xi + 2.*eta);
    1248             : 
    1249      202788 :                       case 2:
    1250      202788 :                         return 0.25*( 1. + 2.*xi + 2.*eta);
    1251             : 
    1252      202788 :                       case 3:
    1253      202788 :                         return 0.25*(-1. + 2.*xi - 2.*eta);
    1254             : 
    1255       18312 :                       case 4:
    1256       18312 :                         return xi;
    1257             : 
    1258      202788 :                       case 5:
    1259      202788 :                         return -eta;
    1260             : 
    1261      202788 :                       case 6:
    1262      202788 :                         return -xi;
    1263             : 
    1264      202788 :                       case 7:
    1265      202788 :                         return eta;
    1266             : 
    1267           0 :                       default:
    1268           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1269             :                       }
    1270             :                   }
    1271             : 
    1272             :                   // d^2() / deta^2
    1273     1622304 :                 case 2:
    1274             :                   {
    1275     1622304 :                     switch (i)
    1276             :                       {
    1277      405576 :                       case 0:
    1278             :                       case 3:
    1279      405576 :                         return 0.5*(1.-xi);
    1280             : 
    1281      405576 :                       case 1:
    1282             :                       case 2:
    1283      405576 :                         return 0.5*(1.+xi);
    1284             : 
    1285       36624 :                       case 4:
    1286             :                       case 6:
    1287       36624 :                         return 0.0;
    1288             : 
    1289      202788 :                       case 5:
    1290      202788 :                         return -1.0 - xi;
    1291             : 
    1292      202788 :                       case 7:
    1293      202788 :                         return xi - 1.0;
    1294             : 
    1295           0 :                       default:
    1296           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1297             :                       }
    1298             :                   }
    1299             : 
    1300           0 :                 default:
    1301           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
    1302             :                 } // end switch (j)
    1303             :             } // end case QUAD8
    1304             : 
    1305    27317979 :           case QUAD4:
    1306       11799 :             libmesh_assert_msg(T == L2_LAGRANGE,
    1307             :                                "High order on first order elements only supported for L2 families");
    1308             :             libmesh_fallthrough();
    1309     2428056 :           case QUAD9:
    1310             :           case QUADSHELL9:
    1311             :             {
    1312             :               // Compute QUAD9 second derivatives as tensor product
    1313    29757834 :               const Real xi  = p(0);
    1314    29757834 :               const Real eta = p(1);
    1315             : 
    1316     2451654 :               libmesh_assert_less (i, 9);
    1317             : 
    1318             :               //                                0  1  2  3  4  5  6  7  8
    1319             :               static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2};
    1320             :               static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2};
    1321             : 
    1322    29757834 :               switch (j)
    1323             :                 {
    1324             :                   // d^2() / dxi^2
    1325     9919278 :                 case 0:
    1326     9919278 :                   return (fe_lagrange_1D_quadratic_shape_second_deriv(i0[i], 0, xi)*
    1327     9919278 :                           fe_lagrange_1D_quadratic_shape             (i1[i], eta));
    1328             : 
    1329             :                   // d^2() / dxi deta
    1330     9919278 :                 case 1:
    1331     9919278 :                   return (fe_lagrange_1D_quadratic_shape_deriv(i0[i], 0, xi)*
    1332     9919278 :                           fe_lagrange_1D_quadratic_shape_deriv(i1[i], 0, eta));
    1333             : 
    1334             :                   // d^2() / deta^2
    1335     9919278 :                 case 2:
    1336     9919278 :                   return (fe_lagrange_1D_quadratic_shape             (i0[i], xi)*
    1337     9919278 :                           fe_lagrange_1D_quadratic_shape_second_deriv(i1[i], 0, eta));
    1338             : 
    1339           0 :                 default:
    1340           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
    1341             :                 }  // end switch (j)
    1342             :             } // end case QUAD9
    1343             : 
    1344    84743676 :           case TRI3:
    1345        8226 :             libmesh_assert_msg(T == L2_LAGRANGE,
    1346             :                                "High order on first order elements only supported for L2 families");
    1347             :             libmesh_fallthrough();
    1348     8201862 :           case TRI6:
    1349             :           case TRI7:
    1350             :             {
    1351     8228268 :               const Real dzeta0dxi  = -1.;
    1352     8228268 :               const Real dzeta1dxi  = 1.;
    1353     8228268 :               const Real dzeta2dxi  = 0.;
    1354             : 
    1355     8228268 :               const Real dzeta0deta = -1.;
    1356     8228268 :               const Real dzeta1deta = 0.;
    1357     8228268 :               const Real dzeta2deta = 1.;
    1358             : 
    1359     8228268 :               libmesh_assert_less (j, 3);
    1360             : 
    1361    92963718 :               switch (j)
    1362             :                 {
    1363             :                   // d^2() / dxi^2
    1364    30987906 :                 case 0:
    1365             :                   {
    1366    30987906 :                     switch (i)
    1367             :                       {
    1368      457126 :                       case 0:
    1369      457126 :                         return 4.*dzeta0dxi*dzeta0dxi;
    1370             : 
    1371      457126 :                       case 1:
    1372      457126 :                         return 4.*dzeta1dxi*dzeta1dxi;
    1373             : 
    1374      457126 :                       case 2:
    1375      457126 :                         return 4.*dzeta2dxi*dzeta2dxi;
    1376             : 
    1377      457126 :                       case 3:
    1378      457126 :                         return 8.*dzeta0dxi*dzeta1dxi;
    1379             : 
    1380      457126 :                       case 4:
    1381      457126 :                         return 8.*dzeta1dxi*dzeta2dxi;
    1382             : 
    1383      457126 :                       case 5:
    1384      457126 :                         return 8.*dzeta0dxi*dzeta2dxi;
    1385             : 
    1386           0 :                       default:
    1387           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1388             :                       }
    1389             :                   }
    1390             : 
    1391             :                   // d^2() / dxi deta
    1392    30987906 :                 case 1:
    1393             :                   {
    1394    30987906 :                     switch (i)
    1395             :                       {
    1396      457126 :                       case 0:
    1397      457126 :                         return 4.*dzeta0dxi*dzeta0deta;
    1398             : 
    1399      457126 :                       case 1:
    1400      457126 :                         return 4.*dzeta1dxi*dzeta1deta;
    1401             : 
    1402      457126 :                       case 2:
    1403      457126 :                         return 4.*dzeta2dxi*dzeta2deta;
    1404             : 
    1405      457126 :                       case 3:
    1406      457126 :                         return 4.*dzeta1deta*dzeta0dxi + 4.*dzeta0deta*dzeta1dxi;
    1407             : 
    1408      457126 :                       case 4:
    1409      457126 :                         return 4.*dzeta2deta*dzeta1dxi + 4.*dzeta1deta*dzeta2dxi;
    1410             : 
    1411      457126 :                       case 5:
    1412      457126 :                         return 4.*dzeta2deta*dzeta0dxi + 4.*dzeta0deta*dzeta2dxi;
    1413             : 
    1414           0 :                       default:
    1415           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1416             :                       }
    1417             :                   }
    1418             : 
    1419             :                   // d^2() / deta^2
    1420    30987906 :                 case 2:
    1421             :                   {
    1422    30987906 :                     switch (i)
    1423             :                       {
    1424      457126 :                       case 0:
    1425      457126 :                         return 4.*dzeta0deta*dzeta0deta;
    1426             : 
    1427      457126 :                       case 1:
    1428      457126 :                         return 4.*dzeta1deta*dzeta1deta;
    1429             : 
    1430      457126 :                       case 2:
    1431      457126 :                         return 4.*dzeta2deta*dzeta2deta;
    1432             : 
    1433      457126 :                       case 3:
    1434      457126 :                         return 8.*dzeta0deta*dzeta1deta;
    1435             : 
    1436      457126 :                       case 4:
    1437      457126 :                         return 8.*dzeta1deta*dzeta2deta;
    1438             : 
    1439      457126 :                       case 5:
    1440      457126 :                         return 8.*dzeta0deta*dzeta2deta;
    1441             : 
    1442           0 :                       default:
    1443           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1444             :                       }
    1445             :                   }
    1446             : 
    1447           0 :                 default:
    1448           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
    1449             :                 } // end switch (j)
    1450             :             }  // end case TRI6+TRI7
    1451             : 
    1452           0 :           default:
    1453           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
    1454             :           }
    1455             :       } // end case SECOND
    1456             : 
    1457             : 
    1458             : 
    1459             :       // "cubic" (one cubic bubble) Lagrange shape functions on TRI7
    1460   151718334 :     case THIRD:
    1461             :       {
    1462   151718334 :         switch (type)
    1463             :           {
    1464   137517447 :           case TRI3:
    1465           0 :             libmesh_assert_msg(T == L2_LAGRANGE,
    1466             :                                "High order on first order elements only supported for L2 families");
    1467             :             libmesh_fallthrough();
    1468    14190660 :           case TRI6:
    1469             :           case TRI7:
    1470             :             {
    1471   151718334 :               const Real zeta1 = p(0);
    1472   151718334 :               const Real zeta2 = p(1);
    1473             :               // const Real zeta0 = 1. - zeta1 - zeta2;
    1474             : 
    1475    14200887 :               const Real dzeta0dxi  = -1.;
    1476    14200887 :               const Real dzeta1dxi  = 1.;
    1477    14200887 :               const Real dzeta2dxi  = 0.;
    1478             :               // const Real dbubbledxi = zeta2 * (1. - 2.*zeta1 - zeta2);
    1479   151718334 :               const Real d2bubbledxi2 = -2. * zeta2;
    1480             : 
    1481    14200887 :               const Real dzeta0deta = -1.;
    1482    14200887 :               const Real dzeta1deta = 0.;
    1483    14200887 :               const Real dzeta2deta = 1.;
    1484             :               // const Real dbubbledeta= zeta1 * (1. - zeta1 - 2.*zeta2);
    1485   151718334 :               const Real d2bubbledeta2 = -2. * zeta1;
    1486             : 
    1487   151718334 :               const Real d2bubbledxideta = (1. - 2.*zeta1 - 2.*zeta2);
    1488             : 
    1489    14200887 :               libmesh_assert_less (j, 3);
    1490             : 
    1491   151718334 :               switch (j)
    1492             :                 {
    1493             :                   // d^2() / dxi^2
    1494    50572778 :                 case 0:
    1495             :                   {
    1496    50572778 :                     switch (i)
    1497             :                       {
    1498     6754954 :                       case 0:
    1499     6754954 :                         return 4.*dzeta0dxi*dzeta0dxi + 3.*d2bubbledxi2;
    1500             : 
    1501     6754954 :                       case 1:
    1502     6754954 :                         return 4.*dzeta1dxi*dzeta1dxi + 3.*d2bubbledxi2;
    1503             : 
    1504     6754954 :                       case 2:
    1505     6754954 :                         return 4.*dzeta2dxi*dzeta2dxi + 3.*d2bubbledxi2;
    1506             : 
    1507     6754954 :                       case 3:
    1508     6754954 :                         return 8.*dzeta0dxi*dzeta1dxi - 12.*d2bubbledxi2;
    1509             : 
    1510     6754954 :                       case 4:
    1511     6754954 :                         return 8.*dzeta1dxi*dzeta2dxi - 12.*d2bubbledxi2;
    1512             : 
    1513     6754954 :                       case 5:
    1514     6754954 :                         return 8.*dzeta0dxi*dzeta2dxi - 12.*d2bubbledxi2;
    1515             : 
    1516    10043054 :                       case 6:
    1517    10043054 :                         return 27.*d2bubbledxi2;
    1518             : 
    1519           0 :                       default:
    1520           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1521             :                       }
    1522             :                   }
    1523             : 
    1524             :                   // d^2() / dxi deta
    1525    50572778 :                 case 1:
    1526             :                   {
    1527    50572778 :                     switch (i)
    1528             :                       {
    1529     6754954 :                       case 0:
    1530     6754954 :                         return 4.*dzeta0dxi*dzeta0deta + 3.*d2bubbledxideta;
    1531             : 
    1532     6754954 :                       case 1:
    1533     6754954 :                         return 4.*dzeta1dxi*dzeta1deta + 3.*d2bubbledxideta;
    1534             : 
    1535     6754954 :                       case 2:
    1536     6754954 :                         return 4.*dzeta2dxi*dzeta2deta + 3.*d2bubbledxideta;
    1537             : 
    1538     6754954 :                       case 3:
    1539     6754954 :                         return 4.*dzeta1deta*dzeta0dxi + 4.*dzeta0deta*dzeta1dxi - 12.*d2bubbledxideta;
    1540             : 
    1541     6754954 :                       case 4:
    1542     6754954 :                         return 4.*dzeta2deta*dzeta1dxi + 4.*dzeta1deta*dzeta2dxi - 12.*d2bubbledxideta;
    1543             : 
    1544     6754954 :                       case 5:
    1545     6754954 :                         return 4.*dzeta2deta*dzeta0dxi + 4.*dzeta0deta*dzeta2dxi - 12.*d2bubbledxideta;
    1546             : 
    1547    10043054 :                       case 6:
    1548    10043054 :                         return 27.*d2bubbledxideta;
    1549             : 
    1550           0 :                       default:
    1551           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1552             :                       }
    1553             :                   }
    1554             : 
    1555             :                   // d^2() / deta^2
    1556    50572778 :                 case 2:
    1557             :                   {
    1558    50572778 :                     switch (i)
    1559             :                       {
    1560     6754954 :                       case 0:
    1561     6754954 :                         return 4.*dzeta0deta*dzeta0deta + 3.*d2bubbledeta2;
    1562             : 
    1563     6754954 :                       case 1:
    1564     6754954 :                         return 4.*dzeta1deta*dzeta1deta + 3.*d2bubbledeta2;
    1565             : 
    1566     6754954 :                       case 2:
    1567     6754954 :                         return 4.*dzeta2deta*dzeta2deta + 3.*d2bubbledeta2;
    1568             : 
    1569     6754954 :                       case 3:
    1570     6754954 :                         return 8.*dzeta0deta*dzeta1deta - 12.*d2bubbledeta2;
    1571             : 
    1572     6754954 :                       case 4:
    1573     6754954 :                         return 8.*dzeta1deta*dzeta2deta - 12.*d2bubbledeta2;
    1574             : 
    1575     6754954 :                       case 5:
    1576     6754954 :                         return 8.*dzeta0deta*dzeta2deta - 12.*d2bubbledeta2;
    1577             : 
    1578    10043054 :                       case 6:
    1579    10043054 :                         return 27.*d2bubbledeta2;
    1580             : 
    1581           0 :                       default:
    1582           0 :                         libmesh_error_msg("Invalid shape function index i = " << i);
    1583             :                       }
    1584             :                   }
    1585             : 
    1586           0 :                 default:
    1587           0 :                   libmesh_error_msg("ERROR: Invalid derivative index j = " << j);
    1588             :                 } // end switch (j)
    1589             :             }  // end case TRI6+TRI7
    1590             : 
    1591           0 :           default:
    1592           0 :             libmesh_error_msg("ERROR: Unsupported 2D element type: " << Utility::enum_to_string(type));
    1593             :           }
    1594             :       } // end case THIRD
    1595             : 
    1596             :       // unsupported order
    1597           0 :     default:
    1598           0 :       libmesh_error_msg("ERROR: Unsupported 2D FE order: " << order);
    1599             : 
    1600             :     } // end switch (order)
    1601             : 
    1602             : #else // LIBMESH_DIM > 1
    1603             :   libmesh_ignore(type, order, i, j, p);
    1604             :   libmesh_not_implemented();
    1605             : #endif
    1606             : }
    1607             : 
    1608             : #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
    1609             : 
    1610             : } // anonymous namespace

Generated by: LCOV version 1.14