LCOV - code coverage report
Current view: top level - src/fe - fe_bernstein.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4640 (c5f9f0) with base a68dd6 Lines: 140 202 69.3 %
Date: 2026-11-02 23:02:27 Functions: 33 62 53.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : 
      20             : // Local includes
      21             : #include "libmesh/libmesh_config.h"
      22             : 
      23             : #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
      24             : 
      25             : #include "libmesh/elem.h"
      26             : #include "libmesh/enum_to_string.h"
      27             : #include "libmesh/fe.h"
      28             : #include "libmesh/fe_interface.h"
      29             : #include "libmesh/fe_macro.h"
      30             : 
      31             : namespace libMesh
      32             : {
      33             : 
      34             : // ------------------------------------------------------------
      35             : // Bernstein-specific implementations, Steffen Petersen 2005
      36             : 
      37             : // Anonymous namespace for local helper functions
      38             : namespace {
      39             : 
      40           0 : void bernstein_nodal_soln(const Elem * elem,
      41             :                           const Order order,
      42             :                           const std::vector<Number> & elem_soln,
      43             :                           std::vector<Number> & nodal_soln,
      44             :                           const bool add_p_level)
      45             : {
      46           0 :   const unsigned int n_nodes = elem->n_nodes();
      47             : 
      48           0 :   const ElemType elem_type = elem->type();
      49             : 
      50           0 :   nodal_soln.resize(n_nodes);
      51             : 
      52           0 :   const Order totalorder = order + add_p_level*elem->p_level();
      53             : 
      54             :   // FEType object to be passed to various FEInterface functions below.
      55           0 :   FEType fe_type(order, BERNSTEIN);
      56             : 
      57           0 :   switch (totalorder)
      58             :     {
      59             :       // Constant shape functions
      60           0 :     case CONSTANT:
      61             :       {
      62           0 :         libmesh_assert_equal_to (elem_soln.size(), 1);
      63             : 
      64           0 :         std::fill(nodal_soln.begin(), nodal_soln.end(), elem_soln[0]);
      65             : 
      66           0 :         return;
      67             :       }
      68             : 
      69             : 
      70             :       // For other bases do interpolation at the nodes
      71             :       // explicitly.
      72           0 :     case FIRST:
      73             :     case SECOND:
      74             :     case THIRD:
      75             :     case FOURTH:
      76             :     case FIFTH:
      77             :     case SIXTH:
      78             :       {
      79             :         const unsigned int n_sf =
      80           0 :           FEInterface::n_shape_functions(fe_type, elem);
      81             : 
      82           0 :         std::vector<Point> refspace_nodes;
      83           0 :         FEBase::get_refspace_nodes(elem_type,refspace_nodes);
      84           0 :         libmesh_assert_equal_to (refspace_nodes.size(), n_nodes);
      85           0 :         libmesh_assert_equal_to (elem_soln.size(), n_sf);
      86             : 
      87             :         // Zero before summation
      88           0 :         std::fill(nodal_soln.begin(), nodal_soln.end(), 0);
      89             : 
      90           0 :         for (unsigned int n=0; n<n_nodes; n++)
      91             :           // u_i = Sum (alpha_i phi_i)
      92           0 :           for (unsigned int i=0; i<n_sf; i++)
      93           0 :             nodal_soln[n] += elem_soln[i] *
      94           0 :               FEInterface::shape(fe_type, elem, i, refspace_nodes[n]);
      95             : 
      96           0 :         return;
      97             :       }
      98             : 
      99           0 :     default:
     100           0 :       libmesh_error_msg("ERROR: Invalid total order " << totalorder);
     101             :     }
     102             : } //  bernstein_nodal_soln()
     103             : 
     104             : 
     105             : 
     106    99408003 : unsigned int BERNSTEIN_n_dofs(const ElemType t, const Order o)
     107             : {
     108    99408003 :   switch (t)
     109             :     {
     110      244365 :     case NODEELEM:
     111      244365 :       return 1;
     112       94504 :     case EDGE2:
     113             :     case EDGE3:
     114             :     case EDGE4:
     115     1033293 :       return (o+1);
     116        9371 :     case QUAD4:
     117             :     case QUADSHELL4:
     118        9371 :       libmesh_assert_less (o, 2);
     119             :       libmesh_fallthrough();
     120             :     case QUAD8:
     121             :     case QUADSHELL8:
     122             :       {
     123      357464 :         if (o == 1)
     124        9371 :           return 4;
     125      247884 :         else if (o == 2)
     126       20658 :           return 8;
     127             :         else
     128           0 :           libmesh_error_msg("ERROR: Invalid Order " << Utility::enum_to_string(o) << " selected for BERNSTEIN FE family!");
     129             :       }
     130     5409064 :     case QUAD9:
     131             :     case QUADSHELL9:
     132    57744797 :       return ((o+1)*(o+1));
     133      279891 :     case HEX8:
     134      279891 :       libmesh_assert_less (o, 2);
     135             :       libmesh_fallthrough();
     136             :     case HEX20:
     137             :       {
     138    11313840 :         if (o == 1)
     139      279891 :           return 8;
     140     7960308 :         else if (o == 2)
     141      663360 :           return 20;
     142             :         else
     143           0 :           libmesh_error_msg("ERROR: Invalid Order " << Utility::enum_to_string(o) << " selected for BERNSTEIN FE family!");
     144             :       }
     145     1993704 :     case HEX27:
     146    26380808 :       return ((o+1)*(o+1)*(o+1));
     147        8729 :     case TRI3:
     148             :     case TRISHELL3:
     149        8729 :       libmesh_assert_less (o, 2);
     150             :       libmesh_fallthrough();
     151             :     case TRI6:
     152             :     case TRI7:
     153      900836 :       return ((o+1)*(o+2)/2);
     154       31866 :     case TET4:
     155       31866 :       libmesh_assert_less (o, 2);
     156             :       libmesh_fallthrough();
     157             :     case TET10:
     158             :     case TET14:
     159       40882 :       libmesh_assert_less (o, 3);
     160      993166 :       return ((o+1)*(o+2)*(o+3)/6);
     161           0 :     case INVALID_ELEM:
     162           0 :       return 0;
     163           0 :     default:
     164           0 :       libmesh_error_msg("ERROR: Invalid ElemType " << Utility::enum_to_string(t) << " selected for BERNSTEIN FE family!");
     165             :     }
     166             : } // BERNSTEIN_n_dofs()
     167             : 
     168             : 
     169             : 
     170    91057660 : unsigned int BERNSTEIN_n_dofs(const Elem * e, const Order o)
     171             : {
     172     8827178 :   libmesh_assert(e);
     173    99408003 :   return BERNSTEIN_n_dofs(e->type(), o);
     174             : }
     175             : 
     176             : 
     177             : 
     178    19476843 : unsigned int BERNSTEIN_n_dofs_at_node(const ElemType t,
     179             :                                       const Order o,
     180             :                                       const unsigned int n)
     181             : {
     182    19476843 :   switch (t)
     183             :     {
     184      184751 :     case NODEELEM:
     185      184751 :       return 1;
     186             : 
     187       25948 :     case EDGE2:
     188             :     case EDGE3:
     189       25948 :       switch (n)
     190             :         {
     191        1846 :         case 0:
     192             :         case 1:
     193        1846 :           return 1;
     194         624 :         case 2:
     195         624 :           libmesh_assert (o>1);
     196        6916 :           return (o-1);
     197           0 :         default:
     198           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for EDGE2/3!");
     199             :         }
     200        6526 :     case EDGE4:
     201        6526 :       switch (n)
     202             :         {
     203         325 :         case 0:
     204             :         case 1:
     205         325 :           return 1;
     206         143 :         case 2:
     207         143 :           libmesh_assert (o>2);
     208        1573 :           return (o-1)/2;  // floor
     209        1573 :         case 3:
     210         143 :           libmesh_assert (o>2);
     211        1573 :           return o/2;          // "ceiling", add extra DoFs here first
     212           0 :         default:
     213           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for EDGE4!");
     214             :         }
     215      278213 :     case TRI3:
     216        2288 :       libmesh_assert_less (n, 3);
     217        2288 :       libmesh_assert_less (o, 2);
     218             :       libmesh_fallthrough();
     219             :     case TRI6:
     220             :       // Internal DoFs are associated with the elem on a Tri6, or node 6 on a Tri7
     221       13715 :       libmesh_assert_less (n, 6);
     222             :       libmesh_fallthrough();
     223             :     case TRI7:
     224      302926 :       switch (n)
     225             :         {
     226       14222 :         case 0:
     227             :         case 1:
     228             :         case 2:
     229       14222 :           return 1;
     230             : 
     231       10920 :         case 3:
     232             :         case 4:
     233             :         case 5:
     234      122928 :           return (o-1);
     235             : 
     236        1859 :         case 6:
     237       20982 :           return ((o-1)*(o-2)/2);
     238           0 :         default:
     239           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TRI!");
     240             :         }
     241    11494516 :     case QUAD4:
     242        1482 :       libmesh_assert_less (n, 4);
     243        1482 :       libmesh_assert_less (o, 2);
     244             :       libmesh_fallthrough();
     245             :     case QUAD8:
     246        1482 :       libmesh_assert_less (n, 8);
     247        1482 :       libmesh_assert_less (o, 3);
     248             :       libmesh_fallthrough();
     249             :     case QUAD9:
     250             :       {
     251    12848428 :         switch (n)
     252             :           {
     253      611330 :           case 0:
     254             :           case 1:
     255             :           case 2:
     256             :           case 3:
     257      611330 :             return 1;
     258             : 
     259      595064 :           case 4:
     260             :           case 5:
     261             :           case 6:
     262             :           case 7:
     263     5636615 :             return (o-1);
     264             : 
     265      149000 :           case 8:
     266     1411830 :             return ((o-1)*(o-1));
     267             : 
     268           0 :           default:
     269           0 :             libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for QUAD9!");
     270             :           }
     271             :       }
     272     1631175 :     case HEX8:
     273        4602 :       libmesh_assert_less (n, 8);
     274        4602 :       libmesh_assert_less (o, 2);
     275             :       libmesh_fallthrough();
     276             :     case HEX20:
     277        4602 :       libmesh_assert_less (n, 20);
     278        4602 :       libmesh_assert_less (o, 3);
     279             :       libmesh_fallthrough();
     280             :     case HEX27:
     281     1761919 :       switch (n)
     282             :         {
     283       44094 :         case 0:
     284             :         case 1:
     285             :         case 2:
     286             :         case 3:
     287             :         case 4:
     288             :         case 5:
     289             :         case 6:
     290             :         case 7:
     291       44094 :           return 1;
     292             : 
     293       57572 :         case 8:
     294             :         case 9:
     295             :         case 10:
     296             :         case 11:
     297             :         case 12:
     298             :         case 13:
     299             :         case 14:
     300             :         case 15:
     301             :         case 16:
     302             :         case 17:
     303             :         case 18:
     304             :         case 19:
     305      754081 :           return (o-1);
     306             : 
     307       28820 :         case 20:
     308             :         case 21:
     309             :         case 22:
     310             :         case 23:
     311             :         case 24:
     312             :         case 25:
     313      377359 :           return ((o-1)*(o-1));
     314             : 
     315        4860 :         case 26:
     316       63563 :           return ((o-1)*(o-1)*(o-1));
     317             : 
     318           0 :         default:
     319           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for HEX27!");
     320             :         }
     321     2657174 :     case TET4:
     322       20046 :       libmesh_assert_less (n, 4);
     323       20046 :       libmesh_assert_less (o, 2);
     324             :       libmesh_fallthrough();
     325             :     case TET10:
     326       66963 :       libmesh_assert_less (n, 10);
     327             :       libmesh_fallthrough();
     328             :     case TET14:
     329      132548 :       libmesh_assert_less (o, 3);
     330     2637128 :       switch (n)
     331             :         {
     332       60684 :         case 0:
     333             :         case 1:
     334             :         case 2:
     335             :         case 3:
     336       60684 :           return 1;
     337             : 
     338       53196 :         case 4:
     339             :         case 5:
     340             :         case 6:
     341             :         case 7:
     342             :         case 8:
     343             :         case 9:
     344     1033708 :           return (o-1);
     345             : 
     346       18668 :         case 10:
     347             :         case 11:
     348             :         case 12:
     349             :         case 13:
     350       18668 :           return 0;
     351             : 
     352           0 :         default:
     353           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TET4/10/14!");
     354             :         }
     355           0 :     case INVALID_ELEM:
     356           0 :       return 0;
     357           0 :     default:
     358           0 :       libmesh_error_msg("ERROR: Invalid ElemType " << Utility::enum_to_string(t) << " selected for BERNSTEIN FE family!");
     359             :     }
     360             : } // BERNSTEIN_n_dofs_at_node()
     361             : 
     362             : 
     363             : 
     364     2490934 : unsigned int BERNSTEIN_n_dofs_at_node(const Elem & e,
     365             :                                       const Order o,
     366             :                                       const unsigned int n)
     367             : {
     368     2657937 :   return BERNSTEIN_n_dofs_at_node(e.type(), o, n);
     369             : }
     370             : 
     371             : 
     372             : 
     373     3454691 : unsigned int BERNSTEIN_n_dofs_per_elem(const ElemType t, const Order o)
     374             : {
     375     3105511 :   switch (t)
     376             :     {
     377      180866 :     case NODEELEM:
     378             :     case EDGE2:
     379             :     case EDGE3:
     380             :     case EDGE4:
     381      180866 :       return 0;
     382        1014 :     case TRI3:
     383             :     case TRISHELL3:
     384             :     case QUAD4:
     385             :     case QUADSHELL4:
     386        1014 :       return 0;
     387        1625 :     case TRI6:
     388       18252 :       return ((o-1)*(o-2)/2);
     389        1625 :     case TRI7:
     390        1625 :       return 0;
     391           0 :     case QUAD8:
     392             :     case QUADSHELL8:
     393           0 :       if (o <= 2)
     394           0 :         return 0;
     395             :       libmesh_fallthrough();
     396             :     case QUAD9:
     397             :     case QUADSHELL9:
     398      147852 :       return 0;
     399         546 :     case HEX8:
     400         546 :       libmesh_assert_less (o, 2);
     401         546 :       return 0;
     402           0 :     case HEX20:
     403           0 :       libmesh_assert_less (o, 3);
     404           0 :       return 0;
     405        3744 :     case HEX27:
     406        3744 :       return 0;
     407        4186 :     case TET4:
     408        4186 :       libmesh_assert_less (o, 2);
     409             :       libmesh_fallthrough();
     410             :     case TET10:
     411             :     case TET14:
     412       11908 :       libmesh_assert_less (o, 3);
     413       11908 :       return 0;
     414           0 :     case INVALID_ELEM:
     415           0 :       return 0;
     416           0 :     default:
     417           0 :       libmesh_error_msg("ERROR: Invalid ElemType " << Utility::enum_to_string(t) << " selected for BERNSTEIN FE family!");
     418             :     }
     419             : } // BERNSTEIN_n_dofs_per_elem
     420             : 
     421             : 
     422             : 
     423     3105511 : unsigned int BERNSTEIN_n_dofs_per_elem(const Elem & e, const Order o)
     424             : {
     425     3454691 :   return BERNSTEIN_n_dofs_per_elem(e.type(), o);
     426             : }
     427             : 
     428             : } // anonymous namespace
     429             : 
     430             : 
     431             : // Instantiate (side_) nodal_soln() function for every dimension
     432           0 : LIBMESH_FE_NODAL_SOLN(BERNSTEIN, bernstein_nodal_soln)
     433           0 : LIBMESH_FE_SIDE_NODAL_SOLN(BERNSTEIN)
     434             : 
     435             : // Instantiate n_dofs*() functions for every dimension
     436   122339537 : LIBMESH_DEFAULT_NDOFS(BERNSTEIN)
     437             : 
     438             : // Bernstein FEMs are C^0 continuous
     439           0 : template <> FEContinuity FE<0,BERNSTEIN>::get_continuity() const { return C_ZERO; }
     440       23759 : template <> FEContinuity FE<1,BERNSTEIN>::get_continuity() const { return C_ZERO; }
     441       62823 : template <> FEContinuity FE<2,BERNSTEIN>::get_continuity() const { return C_ZERO; }
     442       77847 : template <> FEContinuity FE<3,BERNSTEIN>::get_continuity() const { return C_ZERO; }
     443             : 
     444             : // Bernstein FEMs are not hierarchic
     445           0 : template <> bool FE<0,BERNSTEIN>::is_hierarchic() const { return false; }
     446          60 : template <> bool FE<1,BERNSTEIN>::is_hierarchic() const { return false; }
     447         202 : template <> bool FE<2,BERNSTEIN>::is_hierarchic() const { return false; }
     448         250 : template <> bool FE<3,BERNSTEIN>::is_hierarchic() const { return false; }
     449             : 
     450             : #ifdef LIBMESH_ENABLE_AMR
     451             : // compute_constraints() specializations are only needed for 2 and 3D
     452             : template <>
     453        2808 : void FE<2,BERNSTEIN>::compute_constraints (DofConstraints & constraints,
     454             :                                            DofMap & dof_map,
     455             :                                            const unsigned int variable_number,
     456             :                                            const Elem * elem)
     457        2808 : { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
     458             : 
     459             : template <>
     460       11856 : void FE<3,BERNSTEIN>::compute_constraints (DofConstraints & constraints,
     461             :                                            DofMap & dof_map,
     462             :                                            const unsigned int variable_number,
     463             :                                            const Elem * elem)
     464       11856 : { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
     465             : #endif // #ifdef LIBMESH_ENABLE_AMR
     466             : 
     467             : // Bernstein shapes need reinit only for approximation orders >= 3,
     468             : // but we might reach that with p refinement
     469           0 : template <> bool FE<0,BERNSTEIN>::shapes_need_reinit() const { return true; }
     470         804 : template <> bool FE<1,BERNSTEIN>::shapes_need_reinit() const { return true; }
     471        7574 : template <> bool FE<2,BERNSTEIN>::shapes_need_reinit() const { return true; }
     472       31482 : template <> bool FE<3,BERNSTEIN>::shapes_need_reinit() const { return true; }
     473             : 
     474             : } // namespace libMesh
     475             : 
     476             : #endif //LIBMESH_ENABLE_HIGHER_ORDER_SHAPES

Generated by: LCOV version 1.14