LCOV - code coverage report
Current view: top level - src/fe - fe_bernstein_shape_2D.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 171 279 61.3 %
Date: 2025-08-19 19:27:09 Functions: 8 14 57.1 %
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             : #include "libmesh/libmesh_config.h"
      20             : 
      21             : #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
      22             : 
      23             : // libmesh includes
      24             : #include "libmesh/fe.h"
      25             : #include "libmesh/elem.h"
      26             : #include "libmesh/number_lookups.h"
      27             : #include "libmesh/utility.h"
      28             : #include "libmesh/enum_to_string.h"
      29             : 
      30             : 
      31             : namespace {
      32             : 
      33             : using namespace libMesh;
      34             : 
      35             : /*
      36             :  * Helper function for finding indices, when computing quad shape
      37             :  * functions and derivatives via a tensor-product of 1D functions and
      38             :  * derivatives.
      39             :  */
      40   850351704 : std::pair<unsigned int, unsigned int> quad_i0_i1 (const unsigned int i,
      41             :                                                   const Order totalorder,
      42             :                                                   const Elem & elem)
      43             : {
      44    78807455 :   libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u));
      45             : 
      46             :   unsigned int i0, i1;
      47             : 
      48             :   // Vertex DoFs
      49   156484636 :   if (i == 0)
      50     8761999 :     { i0 = 0; i1 = 0; }
      51   139086224 :   else if (i == 1)
      52     8761999 :     { i0 = 1; i1 = 0; }
      53   121687812 :   else if (i == 2)
      54     8761999 :     { i0 = 1; i1 = 1; }
      55   104289400 :   else if (i == 3)
      56     8761999 :     { i0 = 0; i1 = 1; }
      57             : 
      58             : 
      59             :   // Edge DoFs
      60   472148088 :   else if (i < totalorder + 3u)
      61    94366872 :     { i0 = i - 2; i1 = 0; }
      62   377781216 :   else if (i < 2u*totalorder + 2)
      63    94366872 :     { i0 = 1; i1 = i - totalorder - 1; }
      64   283414344 :   else if (i < 3u*totalorder + 1)
      65    94366872 :     { i0 = i - 2u*totalorder; i1 = 1; }
      66   189047472 :   else if (i < 4u*totalorder)
      67    94366872 :     { i0 = 0; i1 = i - 3u*totalorder + 1; }
      68             :   // Interior DoFs
      69             :   else
      70             :     {
      71    94680600 :       unsigned int basisnum = i - 4*totalorder;
      72    94680600 :       i0 = square_number_column[basisnum] + 2;
      73    94680600 :       i1 = square_number_row[basisnum] + 2;
      74             :     }
      75             : 
      76             : 
      77             :   // Flip odd degree of freedom values if necessary
      78             :   // to keep continuity on sides
      79   850351704 :   if      ((i>= 4                 && i<= 4+  totalorder-2u) && elem.point(0) > elem.point(1)) i0=totalorder+2-i0;
      80   758671443 :   else if ((i>= 4+  totalorder-1u && i<= 4+2*totalorder-3u) && elem.point(1) > elem.point(2)) i1=totalorder+2-i1;
      81   666664644 :   else if ((i>= 4+2*totalorder-2u && i<= 4+3*totalorder-4u) && elem.point(3) > elem.point(2)) i0=totalorder+2-i0;
      82   574991673 :   else if ((i>= 4+3*totalorder-3u && i<= 4+4*totalorder-5u) && elem.point(0) > elem.point(3)) i1=totalorder+2-i1;
      83             : 
      84   929159159 :   return std::make_pair(i0, i1);
      85             : }
      86             : 
      87             : }
      88             : 
      89             : namespace libMesh
      90             : {
      91             : 
      92             : 
      93    15336884 : LIBMESH_DEFAULT_VECTORIZED_FE(2,BERNSTEIN)
      94             : 
      95             : 
      96             : template <>
      97   508028966 : Real FE<2,BERNSTEIN>::shape(const Elem * elem,
      98             :                             const Order order,
      99             :                             const unsigned int i,
     100             :                             const Point & p,
     101             :                             const bool add_p_level)
     102             : {
     103    47887451 :   libmesh_assert(elem);
     104             : 
     105   508028966 :   const ElemType type = elem->type();
     106             : 
     107             :   const Order totalorder =
     108   554786143 :     order + add_p_level*elem->p_level();
     109             : 
     110             :   // Declare that we are using our own special power function
     111             :   // from the Utility namespace.  This saves typing later.
     112             :   using Utility::pow;
     113             : 
     114   461271789 :   switch (type)
     115             :     {
     116             :       // Hierarchic shape functions on the quadrilateral.
     117   498373206 :     case QUAD4:
     118             :     case QUADSHELL4:
     119             :     case QUAD9:
     120             :     case QUADSHELL9:
     121             :       {
     122             :         // Compute quad shape functions as a tensor-product
     123   498373206 :         auto [i0, i1] = quad_i0_i1(i, totalorder, *elem);
     124             : 
     125   544272650 :         return (FE<1,BERNSTEIN>::shape(EDGE3, totalorder, i0, p(0))*
     126   544272650 :                 FE<1,BERNSTEIN>::shape(EDGE3, totalorder, i1, p(1)));
     127             :       }
     128             :       // handle serendipity QUAD8 element separately
     129     1761792 :     case QUAD8:
     130             :     case QUADSHELL8:
     131             :       {
     132      146816 :         libmesh_assert_less (totalorder, 3);
     133             : 
     134     1761792 :         const Real xi  = p(0);
     135     1761792 :         const Real eta = p(1);
     136             : 
     137      146816 :         libmesh_assert_less (i, 8);
     138             : 
     139             :         //                                0  1  2  3  4  5  6  7  8
     140             :         static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2};
     141             :         static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2};
     142             :         static const Real scal[] = {-0.25, -0.25, -0.25, -0.25, 0.5, 0.5, 0.5, 0.5};
     143             : 
     144             :         //B_t,i0(i)|xi * B_s,i1(i)|eta + scal(i) * B_t,2|xi * B_t,2|eta
     145     1761792 :         return (FE<1,BERNSTEIN>::shape(EDGE3, totalorder, i0[i], xi)*
     146     1761792 :                 FE<1,BERNSTEIN>::shape(EDGE3, totalorder, i1[i], eta)
     147     1908608 :                 +scal[i]*
     148     1761792 :                 FE<1,BERNSTEIN>::shape(EDGE3, totalorder, i0[8], xi)*
     149     1761792 :                 FE<1,BERNSTEIN>::shape(EDGE3, totalorder, i1[8], eta));
     150             : 
     151             :       }
     152             : 
     153     7334638 :     case TRI3:
     154             :     case TRISHELL3:
     155      151587 :       libmesh_assert_less (totalorder, 2);
     156             :       libmesh_fallthrough();
     157             :     case TRI6:
     158             :     case TRI7:
     159     7893968 :       switch (totalorder)
     160             :         {
     161     1669752 :         case FIRST:
     162             :           {
     163     1669752 :             const Real x=p(0);
     164     1669752 :             const Real y=p(1);
     165     1669752 :             const Real r=1.-x-y;
     166             : 
     167      151587 :             libmesh_assert_less (i, 3);
     168             : 
     169     1669752 :             switch(i)
     170             :               {
     171       50529 :               case 0: return r;  //f0,0,1
     172      556584 :               case 1: return x;  //f0,1,1
     173      556584 :               case 2: return y;  //f1,0,1
     174             : 
     175           0 :               default:
     176           0 :                 libmesh_error_msg("Invalid shape function index i = " << i);
     177             :               }
     178             :           }
     179     1059216 :         case SECOND:
     180             :           {
     181     1059216 :             const Real x=p(0);
     182     1059216 :             const Real y=p(1);
     183     1059216 :             const Real r=1.-x-y;
     184             : 
     185       95340 :             libmesh_assert_less (i, 6);
     186             : 
     187     1059216 :             switch(i)
     188             :               {
     189      176536 :               case 0: return r*r;
     190      176536 :               case 1: return x*x;
     191      176536 :               case 2: return y*y;
     192             : 
     193      176536 :               case 3: return 2.*x*r;
     194      176536 :               case 4: return 2.*x*y;
     195      176536 :               case 5: return 2.*r*y;
     196             : 
     197           0 :               default:
     198           0 :                 libmesh_error_msg("Invalid shape function index i = " << i);
     199             :               }
     200             :           }
     201     1944200 :         case THIRD:
     202             :           {
     203     1944200 :             const Real x=p(0);
     204     1944200 :             const Real y=p(1);
     205     1944200 :             const Real r=1.-x-y;
     206      174700 :             libmesh_assert_less (i, 10);
     207             : 
     208      174700 :             unsigned int shape=i;
     209             : 
     210             : 
     211     1944200 :             if ((i==3||i==4) &&  elem->positive_edge_orientation(0)) shape=7-i;
     212     1944200 :             if ((i==5||i==6) &&  elem->positive_edge_orientation(1)) shape=11-i;
     213     1944200 :             if ((i==7||i==8) && !elem->positive_edge_orientation(2)) shape=15-i;
     214             : 
     215     1944200 :             switch(shape)
     216             :               {
     217      194420 :               case 0: return r*r*r;
     218      194420 :               case 1: return x*x*x;
     219      194420 :               case 2: return y*y*y;
     220             : 
     221      194420 :               case 3: return 3.*x*r*r;
     222      194420 :               case 4: return 3.*x*x*r;
     223             : 
     224      194420 :               case 5: return 3.*y*x*x;
     225      194420 :               case 6: return 3.*y*y*x;
     226             : 
     227      194420 :               case 7: return 3.*y*r*r;
     228      194420 :               case 8: return 3.*y*y*r;
     229             : 
     230      194420 :               case 9: return 6.*x*y*r;
     231             : 
     232           0 :               default:
     233           0 :                 libmesh_error_msg("Invalid shape function index shape = " << shape);
     234             :               }
     235             :           }
     236     3220800 :         case FOURTH:
     237             :           {
     238     3220800 :             const Real x=p(0);
     239     3220800 :             const Real y=p(1);
     240     3220800 :             const Real r=1-x-y;
     241      289290 :             unsigned int shape=i;
     242             : 
     243      289290 :             libmesh_assert_less (i, 15);
     244             : 
     245     3220800 :             if ((i==3||i== 5) &&  elem->positive_edge_orientation(0)) shape=8-i;
     246     3220800 :             if ((i==6||i== 8) &&  elem->positive_edge_orientation(1)) shape=14-i;
     247     3220800 :             if ((i==9||i==11) && !elem->positive_edge_orientation(2)) shape=20-i;
     248             : 
     249             : 
     250     3220800 :             switch(shape)
     251             :               {
     252             :                 // point functions
     253      214720 :               case  0: return r*r*r*r;
     254      214720 :               case  1: return x*x*x*x;
     255      214720 :               case  2: return y*y*y*y;
     256             : 
     257             :                 // edge functions
     258      214720 :               case  3: return 4.*x*r*r*r;
     259      214720 :               case  4: return 6.*x*x*r*r;
     260      214720 :               case  5: return 4.*x*x*x*r;
     261             : 
     262      214720 :               case  6: return 4.*y*x*x*x;
     263      214720 :               case  7: return 6.*y*y*x*x;
     264      214720 :               case  8: return 4.*y*y*y*x;
     265             : 
     266      214720 :               case  9: return 4.*y*r*r*r;
     267      214720 :               case 10: return 6.*y*y*r*r;
     268      214720 :               case 11: return 4.*y*y*y*r;
     269             : 
     270             :                 // inner functions
     271      214720 :               case 12: return 12.*x*y*r*r;
     272      214720 :               case 13: return 12.*x*x*y*r;
     273      214720 :               case 14: return 12.*x*y*y*r;
     274             : 
     275           0 :               default:
     276           0 :                 libmesh_error_msg("Invalid shape function index shape = " << shape);
     277             :               }
     278             :           }
     279           0 :         case FIFTH:
     280             :           {
     281           0 :             const Real x=p(0);
     282           0 :             const Real y=p(1);
     283           0 :             const Real r=1-x-y;
     284           0 :             unsigned int shape=i;
     285             : 
     286           0 :             libmesh_assert_less (i, 21);
     287             : 
     288           0 :             if ((i>= 3&&i<= 6) &&  elem->positive_edge_orientation(0)) shape=9-i;
     289           0 :             if ((i>= 7&&i<=10) &&  elem->positive_edge_orientation(1)) shape=17-i;
     290           0 :             if ((i>=11&&i<=14) && !elem->positive_edge_orientation(2)) shape=25-i;
     291             : 
     292           0 :             switch(shape)
     293             :               {
     294             :                 //point functions
     295           0 :               case  0: return pow<5>(r);
     296           0 :               case  1: return pow<5>(x);
     297           0 :               case  2: return pow<5>(y);
     298             : 
     299             :                 //edge functions
     300           0 :               case  3: return  5.*x        *pow<4>(r);
     301           0 :               case  4: return 10.*pow<2>(x)*pow<3>(r);
     302           0 :               case  5: return 10.*pow<3>(x)*pow<2>(r);
     303           0 :               case  6: return  5.*pow<4>(x)*r;
     304             : 
     305           0 :               case  7: return  5.*y   *pow<4>(x);
     306           0 :               case  8: return 10.*pow<2>(y)*pow<3>(x);
     307           0 :               case  9: return 10.*pow<3>(y)*pow<2>(x);
     308           0 :               case 10: return  5.*pow<4>(y)*x;
     309             : 
     310           0 :               case 11: return  5.*y   *pow<4>(r);
     311           0 :               case 12: return 10.*pow<2>(y)*pow<3>(r);
     312           0 :               case 13: return 10.*pow<3>(y)*pow<2>(r);
     313           0 :               case 14: return  5.*pow<4>(y)*r;
     314             : 
     315             :                 //inner functions
     316           0 :               case 15: return 20.*x*y*pow<3>(r);
     317           0 :               case 16: return 30.*x*pow<2>(y)*pow<2>(r);
     318           0 :               case 17: return 30.*pow<2>(x)*y*pow<2>(r);
     319           0 :               case 18: return 20.*x*pow<3>(y)*r;
     320           0 :               case 19: return 20.*pow<3>(x)*y*r;
     321           0 :               case 20: return 30.*pow<2>(x)*pow<2>(y)*r;
     322             : 
     323           0 :               default:
     324           0 :                 libmesh_error_msg("Invalid shape function index shape = " << shape);
     325             :               }
     326             :           }
     327           0 :         case SIXTH:
     328             :           {
     329           0 :             const Real x=p(0);
     330           0 :             const Real y=p(1);
     331           0 :             const Real r=1-x-y;
     332           0 :             unsigned int shape=i;
     333             : 
     334           0 :             libmesh_assert_less (i, 28);
     335             : 
     336           0 :             if ((i>= 3&&i<= 7) &&  elem->positive_edge_orientation(0)) shape=10-i;
     337           0 :             if ((i>= 8&&i<=12) &&  elem->positive_edge_orientation(1)) shape=20-i;
     338           0 :             if ((i>=13&&i<=17) && !elem->positive_edge_orientation(2)) shape=30-i;
     339             : 
     340           0 :             switch(shape)
     341             :               {
     342             :                 //point functions
     343           0 :               case  0: return pow<6>(r);
     344           0 :               case  1: return pow<6>(x);
     345           0 :               case  2: return pow<6>(y);
     346             : 
     347             :                 //edge functions
     348           0 :               case  3: return  6.*x        *pow<5>(r);
     349           0 :               case  4: return 15.*pow<2>(x)*pow<4>(r);
     350           0 :               case  5: return 20.*pow<3>(x)*pow<3>(r);
     351           0 :               case  6: return 15.*pow<4>(x)*pow<2>(r);
     352           0 :               case  7: return  6.*pow<5>(x)*r;
     353             : 
     354           0 :               case  8: return  6.*y        *pow<5>(x);
     355           0 :               case  9: return 15.*pow<2>(y)*pow<4>(x);
     356           0 :               case 10: return 20.*pow<3>(y)*pow<3>(x);
     357           0 :               case 11: return 15.*pow<4>(y)*pow<2>(x);
     358           0 :               case 12: return  6.*pow<5>(y)*x;
     359             : 
     360           0 :               case 13: return  6.*y        *pow<5>(r);
     361           0 :               case 14: return 15.*pow<2>(y)*pow<4>(r);
     362           0 :               case 15: return 20.*pow<3>(y)*pow<3>(r);
     363           0 :               case 16: return 15.*pow<4>(y)*pow<2>(r);
     364           0 :               case 17: return  6.*pow<5>(y)*r;
     365             : 
     366             :                 //inner functions
     367           0 :               case 18: return 30.*x*y*pow<4>(r);
     368           0 :               case 19: return 60.*x*pow<2>(y)*pow<3>(r);
     369           0 :               case 20: return 60.*  pow<2>(x)*y*pow<3>(r);
     370           0 :               case 21: return 60.*x*pow<3>(y)*pow<2>(r);
     371           0 :               case 22: return 60.*pow<3>(x)*y*pow<2>(r);
     372           0 :               case 23: return 90.*pow<2>(x)*pow<2>(y)*pow<2>(r);
     373           0 :               case 24: return 30.*x*pow<4>(y)*r;
     374           0 :               case 25: return 60.*pow<2>(x)*pow<3>(y)*r;
     375           0 :               case 26: return 60.*pow<3>(x)*pow<2>(y)*r;
     376           0 :               case 27: return 30.*pow<4>(x)*y*r;
     377             : 
     378           0 :               default:
     379           0 :                 libmesh_error_msg("Invalid shape function index shape = " << shape);
     380             :               } // switch shape
     381             :           }
     382           0 :         default:
     383           0 :           libmesh_error_msg("Invalid totalorder = " << totalorder);
     384             :         } // switch order
     385             : 
     386           0 :     default:
     387           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     388             :     } // switch type
     389             : }
     390             : 
     391             : 
     392             : template <>
     393           0 : Real FE<2,BERNSTEIN>::shape(const ElemType,
     394             :                             const Order,
     395             :                             const unsigned int,
     396             :                             const Point &)
     397             : {
     398           0 :   libmesh_error_msg("Bernstein polynomials require the element type \nbecause edge orientation is needed.");
     399             :   return 0.;
     400             : }
     401             : 
     402             : 
     403             : template <>
     404           0 : Real FE<2,BERNSTEIN>::shape(const FEType fet,
     405             :                             const Elem * elem,
     406             :                             const unsigned int i,
     407             :                             const Point & p,
     408             :                             const bool add_p_level)
     409             : {
     410           0 :   return FE<2,BERNSTEIN>::shape(elem, fet.order, i, p, add_p_level);
     411             : }
     412             : 
     413             : 
     414             : 
     415             : template <>
     416   353827214 : Real FE<2,BERNSTEIN>::shape_deriv(const Elem * elem,
     417             :                                   const Order order,
     418             :                                   const unsigned int i,
     419             :                                   const unsigned int j,
     420             :                                   const Point & p,
     421             :                                   const bool add_p_level)
     422             : {
     423    31956046 :   libmesh_assert(elem);
     424             : 
     425   353827214 :   const ElemType type = elem->type();
     426             : 
     427             :   const Order totalorder =
     428   385783260 :     order + add_p_level*elem->p_level();
     429             : 
     430   321871168 :   switch (type)
     431             :     {
     432             :       // Hierarchic shape functions on the quadrilateral.
     433   349244190 :     case QUAD4:
     434             :     case QUAD9:
     435             :     case QUADSHELL9:
     436             :       {
     437             :         // Compute quad shape functions as a tensor-product
     438   349244190 :         auto [i0, i1] = quad_i0_i1(i, totalorder, *elem);
     439             : 
     440   349244190 :         switch (j)
     441             :           {
     442             :             // d()/dxi
     443   174622095 :           case 0:
     444   190397034 :             return (FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i0, 0, p(0))*
     445   190397034 :                     FE<1,BERNSTEIN>::shape      (EDGE3, totalorder, i1,    p(1)));
     446             : 
     447             :             // d()/deta
     448   174622095 :           case 1:
     449   190397034 :             return (FE<1,BERNSTEIN>::shape      (EDGE3, totalorder, i0,    p(0))*
     450   190397034 :                     FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i1, 0, p(1)));
     451             : 
     452           0 :           default:
     453           0 :             libmesh_error_msg("Invalid shape function derivative j = " << j);
     454             :           }
     455             :       }
     456             : 
     457             :       // Bernstein shape functions on the 8-noded quadrilateral
     458             :       // is handled separately.
     459     1101312 :     case QUAD8:
     460             :     case QUADSHELL8:
     461             :       {
     462       91776 :         libmesh_assert_less (totalorder, 3);
     463             : 
     464     1101312 :         const Real xi  = p(0);
     465     1101312 :         const Real eta = p(1);
     466             : 
     467       91776 :         libmesh_assert_less (i, 8);
     468             : 
     469             :         //                                0  1  2  3  4  5  6  7  8
     470             :         static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2};
     471             :         static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2};
     472             :         static const Real scal[] = {-0.25, -0.25, -0.25, -0.25, 0.5, 0.5, 0.5, 0.5};
     473     1101312 :         switch (j)
     474             :           {
     475             :             // d()/dxi
     476       45888 :           case 0:
     477      550656 :             return (FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i0[i], 0, xi)*
     478      550656 :                     FE<1,BERNSTEIN>::shape      (EDGE3, totalorder, i1[i],    eta)
     479      596544 :                     +scal[i]*
     480      550656 :                     FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i0[8], 0, xi)*
     481      550656 :                     FE<1,BERNSTEIN>::shape      (EDGE3, totalorder, i1[8],    eta));
     482             : 
     483             :             // d()/deta
     484       45888 :           case 1:
     485      550656 :             return (FE<1,BERNSTEIN>::shape      (EDGE3, totalorder, i0[i],    xi)*
     486      550656 :                     FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i1[i], 0, eta)
     487      596544 :                     +scal[i]*
     488      550656 :                     FE<1,BERNSTEIN>::shape      (EDGE3, totalorder, i0[8],    xi)*
     489      550656 :                     FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i1[8], 0, eta));
     490             : 
     491           0 :           default:
     492           0 :             libmesh_error_msg("Invalid shape function derivative j = " << j);
     493             :           }
     494             :       }
     495             : 
     496     3232960 :     case TRI3:
     497             :     case TRISHELL3:
     498       65640 :       libmesh_assert_less (totalorder, 2);
     499             :       libmesh_fallthrough();
     500             :     case TRI6:
     501             :     case TRI7:
     502             :       {
     503     3481712 :         return fe_fdm_deriv(elem, order, i, j, p, add_p_level, FE<2,BERNSTEIN>::shape);
     504             :       }
     505             : 
     506           0 :     default:
     507           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     508             :     }
     509             : }
     510             : 
     511             : 
     512             : 
     513             : 
     514             : template <>
     515           0 : Real FE<2,BERNSTEIN>::shape_deriv(const ElemType,
     516             :                                   const Order,
     517             :                                   const unsigned int,
     518             :                                   const unsigned int,
     519             :                                   const Point &)
     520             : {
     521           0 :   libmesh_error_msg("Bernstein polynomials require the element type \nbecause edge orientation is needed.");
     522             :   return 0.;
     523             : }
     524             : 
     525             : template <>
     526           0 : Real FE<2,BERNSTEIN>::shape_deriv(const FEType fet,
     527             :                                   const Elem * elem,
     528             :                                   const unsigned int i,
     529             :                                   const unsigned int j,
     530             :                                   const Point & p,
     531             :                                   const bool add_p_level)
     532             : {
     533           0 :   return FE<2,BERNSTEIN>::shape_deriv(elem, fet.order, i, j, p, add_p_level);
     534             : }
     535             : 
     536             : 
     537             : 
     538             : 
     539             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     540             : 
     541             : 
     542             : 
     543             : template <>
     544     3983124 : Real FE<2,BERNSTEIN>::shape_second_deriv(const Elem * elem,
     545             :                                          const Order order,
     546             :                                          const unsigned int i,
     547             :                                          const unsigned int j,
     548             :                                          const Point & p,
     549             :                                          const bool add_p_level)
     550             : {
     551      340590 :   libmesh_assert(elem);
     552             : 
     553     3983124 :   const ElemType type = elem->type();
     554             : 
     555             :   const Order totalorder =
     556     4323714 :     order + add_p_level*elem->p_level();
     557             : 
     558     3642534 :   switch (type)
     559             :     {
     560             :       // Hierarchic shape functions on the quadrilateral.
     561     2734308 :     case QUAD4:
     562             :     case QUAD9:
     563             :     case QUADSHELL9:
     564             :       {
     565             :         // Compute quad shape functions as a tensor-product
     566     2734308 :         auto [i0, i1] = quad_i0_i1(i, totalorder, *elem);
     567             : 
     568     2734308 :         switch (j)
     569             :           {
     570             :             // d^2() / dxi^2
     571      911436 :           case 0:
     572      987389 :             return (FE<1,BERNSTEIN>::shape_second_deriv(EDGE3, totalorder, i0, 0, p(0))*
     573      987389 :                     FE<1,BERNSTEIN>::shape             (EDGE3, totalorder, i1,    p(1)));
     574             : 
     575             :             // d^2() / dxi deta
     576      911436 :           case 1:
     577      987389 :             return (FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i0, 0, p(0))*
     578      987389 :                     FE<1,BERNSTEIN>::shape_deriv(EDGE3, totalorder, i1, 0, p(1)));
     579             : 
     580             :             // d^2() / deta^2
     581      911436 :           case 2:
     582      987389 :             return (FE<1,BERNSTEIN>::shape             (EDGE3, totalorder, i0,    p(0))*
     583      987389 :                     FE<1,BERNSTEIN>::shape_second_deriv(EDGE3, totalorder, i1, 0, p(1)));
     584             : 
     585           0 :           default:
     586           0 :             libmesh_error_msg("Invalid shape function derivative j = " << j);
     587             :           }
     588             :       }
     589             : 
     590             :       // Going to be lazy again about the hard cases.
     591     1155534 :     case TRI3:
     592             :     case TRISHELL3:
     593       19449 :       libmesh_assert_less (totalorder, 2);
     594             :       libmesh_fallthrough();
     595             :     case QUAD8:
     596             :     case QUADSHELL8:
     597             :     case TRI6:
     598             :     case TRI7:
     599             :       {
     600     1248816 :         return fe_fdm_second_deriv(elem, order, i, j, p, add_p_level,
     601     1248816 :                                    FE<2,BERNSTEIN>::shape_deriv);
     602             :       }
     603             : 
     604           0 :     default:
     605           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     606             :     }
     607             : }
     608             : 
     609             : 
     610             : template <>
     611           0 : Real FE<2,BERNSTEIN>::shape_second_deriv(const ElemType,
     612             :                                          const Order,
     613             :                                          const unsigned int,
     614             :                                          const unsigned int,
     615             :                                          const Point &)
     616             : {
     617           0 :   libmesh_error_msg("Bernstein polynomials require the element type \nbecause edge orientation is needed.");
     618             :   return 0.;
     619             : }
     620             : 
     621             : 
     622             : template <>
     623           0 : Real FE<2,BERNSTEIN>::shape_second_deriv(const FEType fet,
     624             :                                          const Elem * elem,
     625             :                                          const unsigned int i,
     626             :                                          const unsigned int j,
     627             :                                          const Point & p,
     628             :                                          const bool add_p_level)
     629             : {
     630           0 :   libmesh_assert(elem);
     631           0 :   return FE<2,BERNSTEIN>::shape_second_deriv(elem, fet.order, i, j, p, add_p_level);
     632             : }
     633             : 
     634             : 
     635             : 
     636             : #endif
     637             : 
     638             : } // namespace libMesh
     639             : 
     640             : 
     641             : #endif// LIBMESH_ENABLE_HIGHER_ORDER_SHAPES

Generated by: LCOV version 1.14