LCOV - code coverage report
Current view: top level - src/fe - fe_clough_shape_1D.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4232 (290bfc) with base 82cc40 Lines: 0 160 0.0 %
Date: 2025-08-27 15:46:53 Functions: 0 17 0.0 %
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             : // libmesh includes
      20             : #include "libmesh/fe.h"
      21             : #include "libmesh/elem.h"
      22             : #include "libmesh/fe_interface.h"
      23             : #include "libmesh/enum_to_string.h"
      24             : 
      25             : // Anonymous namespace for persistent variables.
      26             : // This allows us to cache the global-to-local mapping transformation
      27             : // This should also screw up multithreading royally
      28             : namespace
      29             : {
      30             : using namespace libMesh;
      31             : 
      32             : // Keep track of which element was most recently used to generate
      33             : // cached data
      34             : static dof_id_type old_elem_id = DofObject::invalid_id;
      35             : static const Elem * old_elem_ptr = nullptr;
      36             : 
      37             : // Coefficient naming: d(1)d(2n) is the coefficient of the
      38             : // global shape function corresponding to value 1 in terms of the
      39             : // local shape function corresponding to normal derivative 2
      40             : static Real d1xd1x, d2xd2x;
      41             : 
      42             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
      43             : 
      44             : Real clough_raw_shape_second_deriv(const unsigned int basis_num,
      45             :                                    const unsigned int deriv_type,
      46             :                                    const Point & p);
      47             : 
      48             : #endif
      49             : 
      50             : Real clough_raw_shape_deriv(const unsigned int basis_num,
      51             :                             const unsigned int deriv_type,
      52             :                             const Point & p);
      53             : Real clough_raw_shape(const unsigned int basis_num,
      54             :                       const Point & p);
      55             : 
      56             : 
      57             : // Compute the static coefficients for an element
      58           0 : void clough_compute_coefs(const Elem * elem)
      59             : {
      60             :   // Using static globals for old_elem_id, etc. will fail
      61             :   // horribly with more than one thread.
      62           0 :   libmesh_assert_equal_to (libMesh::n_threads(), 1);
      63             : 
      64             :   // Coefficients are cached from old elements; we rely on that cache
      65             :   // except in dbg mode
      66             : #ifndef DEBUG
      67           0 :   if (elem->id() == old_elem_id &&
      68           0 :       elem == old_elem_ptr)
      69           0 :     return;
      70             : #endif
      71             : 
      72           0 :   const FEFamily mapping_family = FEMap::map_fe_type(*elem);
      73           0 :   const FEType map_fe_type(elem->default_order(), mapping_family);
      74             : 
      75             :   // Note: we explicitly don't consider the elem->p_level() when
      76             :   // computing the number of mapping shape functions.
      77             :   const int n_mapping_shape_functions =
      78           0 :     FEInterface::n_shape_functions(map_fe_type, /*extra_order=*/0, elem);
      79             : 
      80             :   // Degrees of freedom are at vertices and edge midpoints
      81           0 :   std::vector<Point> dofpt;
      82           0 :   dofpt.push_back(Point(0));
      83           0 :   dofpt.push_back(Point(1));
      84             : 
      85             :   // Mapping functions - first derivatives at each dofpt
      86           0 :   std::vector<Real> dxdxi(2);
      87           0 :   std::vector<Real> dxidx(2);
      88             : 
      89             :   FEInterface::shape_deriv_ptr shape_deriv_ptr =
      90           0 :     FEInterface::shape_deriv_function(map_fe_type, elem);
      91             : 
      92           0 :   for (int p = 0; p != 2; ++p)
      93             :     {
      94           0 :       for (int i = 0; i != n_mapping_shape_functions; ++i)
      95             :         {
      96             :           const Real ddxi = shape_deriv_ptr
      97           0 :             (map_fe_type, elem, i, 0, dofpt[p], /*add_p_level=*/false);
      98           0 :           dxdxi[p] += dofpt[p](0) * ddxi;
      99             :         }
     100             :     }
     101             : 
     102             :   // Calculate derivative scaling factors
     103             : 
     104             : #ifdef DEBUG
     105             :   // The cached factors should equal our calculations
     106           0 :   if (elem->id() == old_elem_id &&
     107           0 :       elem == old_elem_ptr)
     108             :     {
     109           0 :       libmesh_assert_equal_to(d1xd1x, dxdxi[0]);
     110           0 :       libmesh_assert_equal_to(d2xd2x, dxdxi[1]);
     111             :     }
     112             : #endif
     113             : 
     114           0 :   old_elem_id = elem->id();
     115           0 :   old_elem_ptr = elem;
     116             : 
     117           0 :   d1xd1x = dxdxi[0];
     118           0 :   d2xd2x = dxdxi[1];
     119           0 : }
     120             : 
     121             : 
     122             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     123             : 
     124             : // Return shape function second derivatives on the unit interval
     125           0 : Real clough_raw_shape_second_deriv(const unsigned int basis_num,
     126             :                                    const unsigned int deriv_type,
     127             :                                    const Point & p)
     128             : {
     129           0 :   Real xi = p(0);
     130             : 
     131           0 :   switch (deriv_type)
     132             :     {
     133             : 
     134             :       // second derivative in xi-xi direction
     135           0 :     case 0:
     136           0 :       switch (basis_num)
     137             :         {
     138           0 :         case 0:
     139           0 :           return -6 + 12*xi;
     140           0 :         case 1:
     141           0 :           return 6 - 12*xi;
     142           0 :         case 2:
     143           0 :           return -4 + 6*xi;
     144           0 :         case 3:
     145           0 :           return -2 + 6*xi;
     146             : 
     147           0 :         default:
     148           0 :           libmesh_error_msg("Invalid shape function index i = " <<
     149             :                             basis_num);
     150             :         }
     151             : 
     152           0 :     default:
     153           0 :       libmesh_error_msg("Invalid shape function derivative j = " <<
     154             :                         deriv_type);
     155             :     }
     156             : }
     157             : 
     158             : #endif
     159             : 
     160             : 
     161           0 : Real clough_raw_shape_deriv(const unsigned int basis_num,
     162             :                             const unsigned int deriv_type,
     163             :                             const Point & p)
     164             : {
     165           0 :   Real xi = p(0);
     166             : 
     167           0 :   switch (deriv_type)
     168             :     {
     169           0 :     case 0:
     170           0 :       switch (basis_num)
     171             :         {
     172           0 :         case 0:
     173           0 :           return -6*xi + 6*xi*xi;
     174           0 :         case 1:
     175           0 :           return 6*xi - 6*xi*xi;
     176           0 :         case 2:
     177           0 :           return 1 - 4*xi + 3*xi*xi;
     178           0 :         case 3:
     179           0 :           return -2*xi + 3*xi*xi;
     180             : 
     181           0 :         default:
     182           0 :           libmesh_error_msg("Invalid shape function index i = " <<
     183             :                             basis_num);
     184             :         }
     185             : 
     186           0 :     default:
     187           0 :       libmesh_error_msg("Invalid shape function derivative j = " <<
     188             :                         deriv_type);
     189             :     }
     190             : }
     191             : 
     192           0 : Real clough_raw_shape(const unsigned int basis_num,
     193             :                       const Point & p)
     194             : {
     195           0 :   Real xi = p(0);
     196             : 
     197           0 :   switch (basis_num)
     198             :     {
     199           0 :     case 0:
     200           0 :       return 1 - 3*xi*xi + 2*xi*xi*xi;
     201           0 :     case 1:
     202           0 :       return 3*xi*xi - 2*xi*xi*xi;
     203           0 :     case 2:
     204           0 :       return xi - 2*xi*xi + xi*xi*xi;
     205           0 :     case 3:
     206           0 :       return -xi*xi + xi*xi*xi;
     207             : 
     208           0 :     default:
     209           0 :       libmesh_error_msg("Invalid shape function index i = " <<
     210             :                         basis_num);
     211             :     }
     212             : }
     213             : 
     214             : 
     215             : } // end anonymous namespace
     216             : 
     217             : 
     218             : namespace libMesh
     219             : {
     220             : 
     221             : 
     222           0 : LIBMESH_DEFAULT_VECTORIZED_FE(1,CLOUGH)
     223             : 
     224             : 
     225             : template <>
     226           0 : Real FE<1,CLOUGH>::shape(const Elem * elem,
     227             :                          const Order order,
     228             :                          const unsigned int i,
     229             :                          const Point & p,
     230             :                          const bool add_p_level)
     231             : {
     232           0 :   libmesh_assert(elem);
     233             : 
     234           0 :   clough_compute_coefs(elem);
     235             : 
     236           0 :   const ElemType type = elem->type();
     237             : 
     238             :   const Order totalorder =
     239           0 :     order + add_p_level*elem->p_level();
     240             : 
     241           0 :   switch (totalorder)
     242             :     {
     243             :       // 3rd-order C1 cubic element
     244           0 :     case THIRD:
     245             :       {
     246           0 :         switch (type)
     247             :           {
     248             :             // C1 functions on the C1 cubic edge
     249           0 :           case EDGE2:
     250             :           case EDGE3:
     251             :             {
     252           0 :               libmesh_assert_less (i, 4);
     253             : 
     254           0 :               switch (i)
     255             :                 {
     256           0 :                 case 0:
     257           0 :                   return clough_raw_shape(0, p);
     258           0 :                 case 1:
     259           0 :                   return clough_raw_shape(1, p);
     260           0 :                 case 2:
     261           0 :                   return d1xd1x * clough_raw_shape(2, p);
     262           0 :                 case 3:
     263           0 :                   return d2xd2x * clough_raw_shape(3, p);
     264           0 :                 default:
     265           0 :                   libmesh_error_msg("Invalid shape function index i = " << i);
     266             :                 }
     267             :             }
     268           0 :           default:
     269           0 :             libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     270             :           }
     271             :       }
     272             :       // by default throw an error
     273           0 :     default:
     274           0 :       libmesh_error_msg("ERROR: Unsupported polynomial order = " << totalorder);
     275             :     }
     276             : }
     277             : 
     278             : 
     279             : 
     280             : template <>
     281           0 : Real FE<1,CLOUGH>::shape(const ElemType,
     282             :                          const Order,
     283             :                          const unsigned int,
     284             :                          const Point &)
     285             : {
     286           0 :   libmesh_error_msg("Clough-Tocher elements require the real element \nto construct gradient-based degrees of freedom.");
     287             :   return 0.;
     288             : }
     289             : 
     290             : template <>
     291           0 : Real FE<1,CLOUGH>::shape(const FEType fet,
     292             :                          const Elem * elem,
     293             :                          const unsigned int i,
     294             :                          const Point & p,
     295             :                          const bool add_p_level)
     296             : {
     297           0 :   return FE<1,CLOUGH>::shape(elem, fet.order, i, p, add_p_level);
     298             : }
     299             : 
     300             : 
     301             : 
     302             : 
     303             : template <>
     304           0 : Real FE<1,CLOUGH>::shape_deriv(const ElemType,
     305             :                                const Order,
     306             :                                const unsigned int,
     307             :                                const unsigned int,
     308             :                                const Point &)
     309             : {
     310           0 :   libmesh_error_msg("Clough-Tocher elements require the real element \nto construct gradient-based degrees of freedom.");
     311             :   return 0.;
     312             : }
     313             : 
     314             : 
     315             : 
     316             : template <>
     317           0 : Real FE<1,CLOUGH>::shape_deriv(const Elem * elem,
     318             :                                const Order order,
     319             :                                const unsigned int i,
     320             :                                const unsigned int j,
     321             :                                const Point & p,
     322             :                                const bool add_p_level)
     323             : {
     324           0 :   libmesh_assert(elem);
     325             : 
     326           0 :   clough_compute_coefs(elem);
     327             : 
     328           0 :   const ElemType type = elem->type();
     329             : 
     330             :   const Order totalorder =
     331           0 :     order + add_p_level*elem->p_level();
     332             : 
     333           0 :   switch (totalorder)
     334             :     {
     335             :       // 3rd-order C1 cubic element
     336           0 :     case THIRD:
     337             :       {
     338           0 :         switch (type)
     339             :           {
     340             :             // C1 functions on the C1 cubic edge
     341           0 :           case EDGE2:
     342             :           case EDGE3:
     343             :             {
     344           0 :               switch (i)
     345             :                 {
     346           0 :                 case 0:
     347           0 :                   return clough_raw_shape_deriv(0, j, p);
     348           0 :                 case 1:
     349           0 :                   return clough_raw_shape_deriv(1, j, p);
     350           0 :                 case 2:
     351           0 :                   return d1xd1x * clough_raw_shape_deriv(2, j, p);
     352           0 :                 case 3:
     353           0 :                   return d2xd2x * clough_raw_shape_deriv(3, j, p);
     354           0 :                 default:
     355           0 :                   libmesh_error_msg("Invalid shape function index i = " << i);
     356             :                 }
     357             :             }
     358           0 :           default:
     359           0 :             libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     360             :           }
     361             :       }
     362             :       // by default throw an error
     363           0 :     default:
     364           0 :       libmesh_error_msg("ERROR: Unsupported polynomial order = " << totalorder);
     365             :     }
     366             : }
     367             : 
     368             : 
     369             : template <>
     370           0 : Real FE<1,CLOUGH>::shape_deriv(const FEType fet,
     371             :                                const Elem * elem,
     372             :                                const unsigned int i,
     373             :                                const unsigned int j,
     374             :                                const Point & p,
     375             :                                const bool add_p_level)
     376             : {
     377           0 :   return FE<1,CLOUGH>::shape_deriv(elem, fet.order, i, j, p, add_p_level);
     378             : }
     379             : 
     380             : 
     381             : 
     382             : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
     383             : 
     384             : template <>
     385           0 : Real FE<1,CLOUGH>::shape_second_deriv(const Elem * elem,
     386             :                                       const Order order,
     387             :                                       const unsigned int i,
     388             :                                       const unsigned int j,
     389             :                                       const Point & p,
     390             :                                       const bool add_p_level)
     391             : {
     392           0 :   libmesh_assert(elem);
     393             : 
     394           0 :   clough_compute_coefs(elem);
     395             : 
     396           0 :   const ElemType type = elem->type();
     397             : 
     398             :   const Order totalorder =
     399           0 :     order + add_p_level*elem->p_level();
     400             : 
     401           0 :   switch (totalorder)
     402             :     {
     403             :       // 3rd-order C1 cubic element
     404           0 :     case THIRD:
     405             :       {
     406           0 :         switch (type)
     407             :           {
     408             :             // C1 functions on the C1 cubic edge
     409           0 :           case EDGE2:
     410             :           case EDGE3:
     411             :             {
     412           0 :               switch (i)
     413             :                 {
     414           0 :                 case 0:
     415           0 :                   return clough_raw_shape_second_deriv(0, j, p);
     416           0 :                 case 1:
     417           0 :                   return clough_raw_shape_second_deriv(1, j, p);
     418           0 :                 case 2:
     419           0 :                   return d1xd1x * clough_raw_shape_second_deriv(2, j, p);
     420           0 :                 case 3:
     421           0 :                   return d2xd2x * clough_raw_shape_second_deriv(3, j, p);
     422           0 :                 default:
     423           0 :                   libmesh_error_msg("Invalid shape function index i = " << i);
     424             :                 }
     425             :             }
     426           0 :           default:
     427           0 :             libmesh_error_msg("ERROR: Unsupported element type = " << Utility::enum_to_string(type));
     428             :           }
     429             :       }
     430             :       // by default throw an error
     431           0 :     default:
     432           0 :       libmesh_error_msg("ERROR: Unsupported polynomial order = " << totalorder);
     433             :     }
     434             : }
     435             : 
     436             : 
     437             : template <>
     438           0 : Real FE<1,CLOUGH>::shape_second_deriv(const ElemType,
     439             :                                       const Order,
     440             :                                       const unsigned int,
     441             :                                       const unsigned int,
     442             :                                       const Point &)
     443             : {
     444           0 :   libmesh_error_msg("Clough-Tocher elements require the real element \nto construct gradient-based degrees of freedom.");
     445             :   return 0.;
     446             : }
     447             : 
     448             : template <>
     449           0 : Real FE<1,CLOUGH>::shape_second_deriv(const FEType fet,
     450             :                                       const Elem * elem,
     451             :                                       const unsigned int i,
     452             :                                       const unsigned int j,
     453             :                                       const Point & p,
     454             :                                       const bool add_p_level)
     455             : {
     456           0 :   return FE<1,CLOUGH>::shape_second_deriv(elem, fet.order, i, j, p, add_p_level);
     457             : }
     458             : 
     459             : 
     460             : 
     461             : #endif
     462             : 
     463             : } // namespace libMesh

Generated by: LCOV version 1.14