LCOV - code coverage report
Current view: top level - src/fe - fe_hermite_shape_2D.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 151 185 81.6 %
Date: 2025-08-19 19:27:09 Functions: 10 16 62.5 %
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_interface.h"
      23             : #include "libmesh/number_lookups.h"
      24             : #include "libmesh/enum_to_string.h"
      25             : 
      26             : namespace
      27             : {
      28             : using namespace libMesh;
      29             : 
      30             : // Compute the static coefficients for an element
      31    33598328 : void hermite_compute_coefs(const Elem * elem, std::vector<std::vector<Real>> & dxdxi
      32             : #ifdef DEBUG
      33             :                            , std::vector<Real> & dxdeta, std::vector<Real> & dydxi
      34             : #endif
      35             :                            )
      36             : {
      37    33598328 :   const FEFamily mapping_family = FEMap::map_fe_type(*elem);
      38    33598328 :   const FEType map_fe_type(elem->default_order(), mapping_family);
      39             : 
      40             :   // Note: we explicitly don't consider the elem->p_level() when
      41             :   // computing the number of mapping shape functions.
      42             :   const int n_mapping_shape_functions =
      43    33598328 :     FEInterface::n_shape_functions (map_fe_type, /*extra_order=*/0, elem);
      44             : 
      45    33598328 :   static const Point dofpt[2] = {Point(-1,-1), Point(1,1)};
      46             : 
      47             :   FEInterface::shape_deriv_ptr shape_deriv_ptr =
      48    33598328 :     FEInterface::shape_deriv_function(map_fe_type, elem);
      49             : 
      50   100794984 :   for (int p = 0; p != 2; ++p)
      51             :     {
      52    67196656 :       dxdxi[0][p] = 0;
      53    71278356 :       dxdxi[1][p] = 0;
      54             : #ifdef DEBUG
      55     4081700 :       dxdeta[p] = 0;
      56     4081700 :       dydxi[p] = 0;
      57             : #endif
      58   671966560 :       for (int i = 0; i != n_mapping_shape_functions; ++i)
      59             :         {
      60             :           const Real ddxi = shape_deriv_ptr
      61   604769904 :             (map_fe_type, elem, i, 0, dofpt[p], /*add_p_level=*/false);
      62             :           const Real ddeta = shape_deriv_ptr
      63   604769904 :             (map_fe_type, elem, i, 1, dofpt[p], /*add_p_level=*/false);
      64             : 
      65   641505204 :           dxdxi[0][p] += elem->point(i)(0) * ddxi;
      66   641505204 :           dxdxi[1][p] += elem->point(i)(1) * ddeta;
      67             :           // dxdeta and dydxi should be 0!
      68             : #ifdef DEBUG
      69    36735300 :           dxdeta[p] += elem->point(i)(0) * ddeta;
      70    36735300 :           dydxi[p] += elem->point(i)(1) * ddxi;
      71             : #endif
      72             :         }
      73             :       // No singular elements!
      74     4081700 :       libmesh_assert(dxdxi[0][p]);
      75     4081700 :       libmesh_assert(dxdxi[1][p]);
      76             :       // No non-rectilinear or non-axis-aligned elements!
      77             : #ifdef DEBUG
      78     4081700 :       libmesh_assert_less (std::abs(dxdeta[p]), 1e-9);
      79     4081700 :       libmesh_assert_less (std::abs(dydxi[p]), 1e-9);
      80             : #endif
      81             :     }
      82    33598328 : }
      83             : 
      84             : 
      85             : 
      86    33598328 : Real hermite_bases_2D (std::vector<unsigned int> & bases1D,
      87             :                        const std::vector<std::vector<Real>> & dxdxi,
      88             :                        const Order & o,
      89             :                        unsigned int i)
      90             : {
      91     2040850 :   bases1D.clear();
      92    33598328 :   bases1D.resize(2,0);
      93     2040850 :   Real coef = 1.0;
      94             : 
      95    33598328 :   unsigned int e = o-3;
      96             : 
      97             :   // Nodes
      98    33598328 :   if (i < 16)
      99             :     {
     100    33091808 :       switch (i / 4)
     101             :         {
     102      499660 :         case 0:
     103      499660 :           break;
     104      999320 :         case 1:
     105     8272952 :           bases1D[0] = 1;
     106     8272952 :           break;
     107      999320 :         case 2:
     108     8272952 :           bases1D[0] = 1;
     109     8272952 :           bases1D[1] = 1;
     110     8272952 :           break;
     111      999320 :         case 3:
     112     8272952 :           bases1D[1] = 1;
     113     8272952 :           break;
     114           0 :         default:
     115           0 :           libmesh_error_msg("Invalid basis node = " << i/4);
     116             :         }
     117             : 
     118    33091808 :       unsigned int basisnum = i%4;
     119    33091808 :       switch (basisnum)
     120             :         {
     121      499660 :         case 0: // DoF = value at node
     122      499660 :           coef = 1.0;
     123      499660 :           break;
     124      999320 :         case 1: // DoF = x derivative at node
     125     8272952 :           coef = dxdxi[0][bases1D[0]];
     126     8272952 :           bases1D[0] += 2; break;
     127      999320 :         case 2: // DoF = y derivative at node
     128     8272952 :           coef = dxdxi[1][bases1D[1]];
     129     8272952 :           bases1D[1] += 2; break;
     130      999320 :         case 3: // DoF = xy derivative at node
     131     8772612 :           coef = dxdxi[0][bases1D[0]] * dxdxi[1][bases1D[1]];
     132     8272952 :           bases1D[0] += 2; bases1D[1] += 2; break;
     133           0 :         default:
     134           0 :           libmesh_error_msg("Invalid basisnum = " << basisnum);
     135             :         }
     136             :     }
     137             :   // Edges
     138      506520 :   else if (i < 16 + 4*2*e)
     139             :     {
     140      450240 :       unsigned int basisnum = (i - 16) % (2*e);
     141      450240 :       switch ((i - 16) / (2*e))
     142             :         {
     143      112560 :         case 0:
     144      112560 :           bases1D[0] = basisnum/2 + 4;
     145      112560 :           bases1D[1] = basisnum%2*2;
     146      112560 :           if (basisnum%2)
     147       56280 :             coef = dxdxi[1][0];
     148        9380 :           break;
     149      112560 :         case 1:
     150      112560 :           bases1D[0] = basisnum%2*2 + 1;
     151      112560 :           bases1D[1] = basisnum/2 + 4;
     152      112560 :           if (basisnum%2)
     153       56280 :             coef = dxdxi[0][1];
     154        9380 :           break;
     155      112560 :         case 2:
     156      112560 :           bases1D[0] = basisnum/2 + 4;
     157      112560 :           bases1D[1] = basisnum%2*2 + 1;
     158      112560 :           if (basisnum%2)
     159       56280 :             coef = dxdxi[1][1];
     160        9380 :           break;
     161      112560 :         case 3:
     162      112560 :           bases1D[0] = basisnum%2*2;
     163      112560 :           bases1D[1] = basisnum/2 + 4;
     164      112560 :           if (basisnum%2)
     165       56280 :             coef = dxdxi[0][0];
     166        9380 :           break;
     167           0 :         default:
     168           0 :           libmesh_error_msg("Invalid basisnum = " << basisnum);
     169             :         }
     170             :     }
     171             :   // Interior
     172             :   else
     173             :     {
     174       56280 :       unsigned int basisnum = i - 16 - 8*e;
     175       56280 :       bases1D[0] = square_number_row[basisnum]+4;
     176       56280 :       bases1D[1] = square_number_column[basisnum]+4;
     177             :     }
     178             : 
     179             :   // No singular elements
     180     2040850 :   libmesh_assert(coef);
     181    33598328 :   return coef;
     182             : }
     183             : 
     184             : } // end anonymous namespace
     185             : 
     186             : 
     187             : namespace libMesh
     188             : {
     189             : 
     190             : 
     191     5979471 : LIBMESH_DEFAULT_VECTORIZED_FE(2,HERMITE)
     192             : 
     193             : 
     194             : template <>
     195     6660764 : Real FE<2,HERMITE>::shape(const Elem * elem,
     196             :                           const Order order,
     197             :                           const unsigned int i,
     198             :                           const Point & p,
     199             :                           const bool add_p_level)
     200             : {
     201      429109 :   libmesh_assert(elem);
     202             : 
     203     7948091 :   std::vector<std::vector<Real>> dxdxi(2, std::vector<Real>(2, 0));
     204             : 
     205             : #ifdef DEBUG
     206     1287327 :   std::vector<Real> dxdeta(2), dydxi(2);
     207             : #endif
     208             : 
     209     6660764 :   hermite_compute_coefs(elem,dxdxi
     210             : #ifdef DEBUG
     211             :                         ,dxdeta,dydxi
     212             : #endif
     213             :                         );
     214             : 
     215     6660764 :   const ElemType type = elem->type();
     216             : 
     217             :   const Order totalorder =
     218     7518982 :     order + add_p_level*elem->p_level();
     219             : 
     220     6231655 :   switch (type)
     221             :     {
     222           0 :     case QUAD4:
     223             :     case QUADSHELL4:
     224           0 :       libmesh_assert_less (totalorder, 4);
     225             :       libmesh_fallthrough();
     226             :     case QUAD8:
     227             :     case QUADSHELL8:
     228             :     case QUAD9:
     229             :     case QUADSHELL9:
     230             :       {
     231      429109 :         libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u));
     232             : 
     233      429109 :         std::vector<unsigned int> bases1D;
     234             : 
     235     6660764 :         Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i);
     236             : 
     237     6660764 :         return coef * FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
     238    13321528 :           FEHermite<1>::hermite_raw_shape(bases1D[1],p(1));
     239             :       }
     240           0 :     default:
     241           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     242             :     }
     243     5802546 : }
     244             : 
     245             : 
     246             : 
     247             : template <>
     248           0 : Real FE<2,HERMITE>::shape(const ElemType,
     249             :                           const Order,
     250             :                           const unsigned int,
     251             :                           const Point &)
     252             : {
     253           0 :   libmesh_error_msg("Hermite elements require the real element \nto construct gradient-based degrees of freedom.");
     254             :   return 0.;
     255             : }
     256             : 
     257             : 
     258             : template <>
     259           0 : Real FE<2,HERMITE>::shape(const FEType fet,
     260             :                           const Elem * elem,
     261             :                           const unsigned int i,
     262             :                           const Point & p,
     263             :                           const bool add_p_level)
     264             : {
     265           0 :   return FE<2,HERMITE>::shape(elem, fet.order, i, p, add_p_level);
     266             : }
     267             : 
     268             : 
     269             : template <>
     270    13070880 : Real FE<2,HERMITE>::shape_deriv(const Elem * elem,
     271             :                                 const Order order,
     272             :                                 const unsigned int i,
     273             :                                 const unsigned int j,
     274             :                                 const Point & p,
     275             :                                 const bool add_p_level)
     276             : {
     277      835176 :   libmesh_assert(elem);
     278      835176 :   libmesh_assert (j == 0 || j == 1);
     279             : 
     280    15576408 :   std::vector<std::vector<Real>> dxdxi(2, std::vector<Real>(2, 0));
     281             : 
     282             : #ifdef DEBUG
     283     2505528 :   std::vector<Real> dxdeta(2), dydxi(2);
     284             : #endif
     285             : 
     286    13070880 :   hermite_compute_coefs(elem,dxdxi
     287             : #ifdef DEBUG
     288             :                         ,dxdeta,dydxi
     289             : #endif
     290             :                         );
     291             : 
     292    13070880 :   const ElemType type = elem->type();
     293             : 
     294             :   const Order totalorder =
     295    14741232 :     order + add_p_level*elem->p_level();
     296             : 
     297    12235704 :   switch (type)
     298             :     {
     299           0 :     case QUAD4:
     300             :     case QUADSHELL4:
     301           0 :       libmesh_assert_less (totalorder, 4);
     302             :       libmesh_fallthrough();
     303             :     case QUAD8:
     304             :     case QUADSHELL8:
     305             :     case QUAD9:
     306             :     case QUADSHELL9:
     307             :       {
     308      835176 :         libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u));
     309             : 
     310     1670352 :         std::vector<unsigned int> bases1D;
     311             : 
     312    13070880 :         Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i);
     313             : 
     314    13070880 :         switch (j)
     315             :           {
     316     6535440 :           case 0:
     317     6535440 :             return coef *
     318     6535440 :               FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
     319     6535440 :               FEHermite<1>::hermite_raw_shape(bases1D[1],p(1));
     320     6535440 :           case 1:
     321     6535440 :             return coef *
     322     6535440 :               FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
     323     6535440 :               FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1));
     324           0 :           default:
     325           0 :             libmesh_error_msg("Invalid derivative index j = " << j);
     326             :           }
     327             :       }
     328           0 :     default:
     329           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     330             :     }
     331    11400528 : }
     332             : 
     333             : 
     334             : template <>
     335           0 : Real FE<2,HERMITE>::shape_deriv(const ElemType,
     336             :                                 const Order,
     337             :                                 const unsigned int,
     338             :                                 const unsigned int,
     339             :                                 const Point &)
     340             : {
     341           0 :   libmesh_error_msg("Hermite elements require the real element \nto construct gradient-based degrees of freedom.");
     342             :   return 0.;
     343             : }
     344             : 
     345             : 
     346             : template <>
     347           0 : Real FE<2,HERMITE>::shape_deriv(const FEType fet,
     348             :                                 const Elem * elem,
     349             :                                 const unsigned int i,
     350             :                                 const unsigned int j,
     351             :                                 const Point & p,
     352             :                                 const bool add_p_level)
     353             : {
     354           0 :   return FE<2,HERMITE>::shape_deriv(elem, fet.order, i, j, p, add_p_level);
     355             : }
     356             : 
     357             : 
     358             : 
     359             : 
     360             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     361             : 
     362             : 
     363             : template <>
     364    13866684 : Real FE<2,HERMITE>::shape_second_deriv(const Elem * elem,
     365             :                                        const Order order,
     366             :                                        const unsigned int i,
     367             :                                        const unsigned int j,
     368             :                                        const Point & p,
     369             :                                        const bool add_p_level)
     370             : {
     371      776565 :   libmesh_assert(elem);
     372      776565 :   libmesh_assert (j == 0 || j == 1 || j == 2);
     373             : 
     374    16196379 :   std::vector<std::vector<Real>> dxdxi(2, std::vector<Real>(2, 0));
     375             : 
     376             : #ifdef DEBUG
     377     2329695 :   std::vector<Real> dxdeta(2), dydxi(2);
     378             : #endif
     379             : 
     380    13866684 :   hermite_compute_coefs(elem,dxdxi
     381             : #ifdef DEBUG
     382             :                         ,dxdeta,dydxi
     383             : #endif
     384             :                         );
     385             : 
     386    13866684 :   const ElemType type = elem->type();
     387             : 
     388             :   const Order totalorder =
     389    15419814 :     order + add_p_level*elem->p_level();
     390             : 
     391    13090119 :   switch (type)
     392             :     {
     393           0 :     case QUAD4:
     394             :     case QUADSHELL4:
     395           0 :       libmesh_assert_less (totalorder, 4);
     396             :       libmesh_fallthrough();
     397             :     case QUAD8:
     398             :     case QUADSHELL8:
     399             :     case QUAD9:
     400             :     case QUADSHELL9:
     401             :       {
     402      776565 :         libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u));
     403             : 
     404     1553130 :         std::vector<unsigned int> bases1D;
     405             : 
     406    13866684 :         Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i);
     407             : 
     408    13866684 :         switch (j)
     409             :           {
     410     4622228 :           case 0:
     411     4622228 :             return coef *
     412     4622228 :               FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[0],p(0)) *
     413     4622228 :               FEHermite<1>::hermite_raw_shape(bases1D[1],p(1));
     414     4622228 :           case 1:
     415     4622228 :             return coef *
     416     4622228 :               FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) *
     417     4622228 :               FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1));
     418     4622228 :           case 2:
     419     4622228 :             return coef *
     420     4622228 :               FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) *
     421     4622228 :               FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[1],p(1));
     422           0 :           default:
     423           0 :             libmesh_error_msg("Invalid derivative index j = " << j);
     424             :           }
     425             :       }
     426           0 :     default:
     427           0 :       libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     428             :     }
     429    12313554 : }
     430             : 
     431             : 
     432             : template <>
     433           0 : Real FE<2,HERMITE>::shape_second_deriv(const ElemType,
     434             :                                        const Order,
     435             :                                        const unsigned int,
     436             :                                        const unsigned int,
     437             :                                        const Point &)
     438             : {
     439           0 :   libmesh_error_msg("Hermite elements require the real element \nto construct gradient-based degrees of freedom.");
     440             :   return 0.;
     441             : }
     442             : 
     443             : 
     444             : template <>
     445           0 : Real FE<2,HERMITE>::shape_second_deriv(const FEType fet,
     446             :                                        const Elem * elem,
     447             :                                        const unsigned int i,
     448             :                                        const unsigned int j,
     449             :                                        const Point & p,
     450             :                                        const bool add_p_level)
     451             : {
     452           0 :   return FE<2,HERMITE>::shape_second_deriv(elem, fet.order, i, j, p, add_p_level);
     453             : }
     454             : 
     455             : 
     456             : #endif
     457             : 
     458             : } // namespace libMesh

Generated by: LCOV version 1.14