LCOV - code coverage report
Current view: top level - src/fe - fe_hierarchic.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 171 208 82.2 %
Date: 2025-08-19 19:27:09 Functions: 42 62 67.7 %
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             : 
      20             : // Local includes
      21             : #include "libmesh/elem.h"
      22             : #include "libmesh/enum_to_string.h"
      23             : #include "libmesh/fe.h"
      24             : #include "libmesh/fe_interface.h"
      25             : #include "libmesh/fe_macro.h"
      26             : 
      27             : namespace libMesh
      28             : {
      29             : 
      30             : // ------------------------------------------------------------
      31             : // Hierarchic-specific implementations
      32             : 
      33             : // Anonymous namespace for local helper functions
      34             : namespace {
      35             : 
      36        4824 : void hierarchic_nodal_soln(const Elem * elem,
      37             :                            const Order order,
      38             :                            const std::vector<Number> & elem_soln,
      39             :                            std::vector<Number> & nodal_soln,
      40             :                            const bool add_p_level)
      41             : {
      42        4824 :   const unsigned int n_nodes = elem->n_nodes();
      43             : 
      44        4824 :   const ElemType elem_type = elem->type();
      45             : 
      46        4824 :   nodal_soln.resize(n_nodes);
      47             : 
      48        5226 :   const Order totalorder = order + add_p_level*elem->p_level();
      49             : 
      50             :   // FEType object to be passed to various FEInterface functions below.
      51         402 :   FEType fe_type(order, HIERARCHIC);
      52             : 
      53        4824 :   switch (totalorder)
      54             :     {
      55             :       // Constant shape functions
      56           0 :     case CONSTANT:
      57             :       {
      58           0 :         libmesh_assert_equal_to (elem_soln.size(), 1);
      59             : 
      60           0 :         std::fill(nodal_soln.begin(), nodal_soln.end(), elem_soln[0]);
      61             : 
      62           0 :         return;
      63             :       }
      64             : 
      65             : 
      66             :       // For other orders do interpolation at the nodes
      67             :       // explicitly.
      68        4824 :     default:
      69             :       {
      70             :         const unsigned int n_sf =
      71        4824 :           FEInterface::n_shape_functions(fe_type, elem);
      72             : 
      73         804 :         std::vector<Point> refspace_nodes;
      74        4824 :         FEBase::get_refspace_nodes(elem_type,refspace_nodes);
      75         402 :         libmesh_assert_equal_to (refspace_nodes.size(), n_nodes);
      76         402 :         libmesh_assert_equal_to (elem_soln.size(), n_sf);
      77             : 
      78             :         // Zero before summation
      79         402 :         std::fill(nodal_soln.begin(), nodal_soln.end(), 0);
      80             : 
      81       61920 :         for (unsigned int n=0; n<n_nodes; n++)
      82             :           // u_i = Sum (alpha_i phi_i)
      83     1130328 :           for (unsigned int i=0; i<n_sf; i++)
      84     1162668 :             nodal_soln[n] += elem_soln[i] *
      85     1162668 :               FEInterface::shape(fe_type, elem, i, refspace_nodes[n]);
      86             : 
      87         402 :         return;
      88             :       }
      89             :     }
      90             : } // hierarchic_nodal_soln()
      91             : 
      92             : 
      93             : 
      94     1571689 : unsigned int HIERARCHIC_n_dofs(const ElemType t, const Order o)
      95             : {
      96      193520 :   libmesh_assert_greater (o, 0);
      97     1571689 :   switch (t)
      98             :     {
      99           0 :     case NODEELEM:
     100           0 :       return 1;
     101        4814 :     case EDGE2:
     102             :     case EDGE3:
     103       25969 :       return (o+1);
     104         507 :     case QUAD4:
     105             :     case QUADSHELL4:
     106         507 :       libmesh_assert_less (o, 2);
     107             :       libmesh_fallthrough();
     108             :     case QUAD8:
     109             :     case QUADSHELL8:
     110             :     case QUAD9:
     111             :     case QUADSHELL9:
     112      312101 :       return ((o+1)*(o+1));
     113        3439 :     case HEX8:
     114             :     case HEX20:
     115        3439 :       libmesh_assert_less (o, 2);
     116             :       libmesh_fallthrough();
     117             :     case HEX27:
     118      633807 :       return ((o+1)*(o+1)*(o+1));
     119        7180 :     case PRISM6:
     120             :     case PRISM15:
     121        7180 :       libmesh_assert_less (o, 2);
     122             :       libmesh_fallthrough();
     123             :     case PRISM18:
     124       11463 :       libmesh_assert_less (o, 3);
     125             :       libmesh_fallthrough();
     126             :     case PRISM20:
     127             :     case PRISM21:
     128      390879 :       return ((o+1)*(o+1)*(o+2)/2);
     129         609 :     case TRI3:
     130         609 :       libmesh_assert_less (o, 2);
     131             :       libmesh_fallthrough();
     132             :     case TRI6:
     133             :     case TRI7:
     134      123696 :       return ((o+1)*(o+2)/2);
     135        1257 :     case TET4:
     136        1257 :       libmesh_assert_less (o, 2);
     137             :       libmesh_fallthrough();
     138             :     case TET10:
     139        4281 :       libmesh_assert_less (o, 3);
     140             :       libmesh_fallthrough();
     141             :     case TET14:
     142      122986 :       return ((o+1)*(o+2)*(o+3)/6);
     143           0 :     case INVALID_ELEM:
     144           0 :       return 0;
     145           0 :     default:
     146           0 :       libmesh_error_msg("ERROR: Invalid ElemType " << Utility::enum_to_string(t) << " selected for HIERARCHIC FE family!");
     147             :     }
     148             : } // HIERARCHIC_n_dofs()
     149             : 
     150             : 
     151             : 
     152     1451880 : unsigned int HIERARCHIC_n_dofs(const Elem * e, const Order o)
     153             : {
     154      193520 :   libmesh_assert(e);
     155     1571689 :   return HIERARCHIC_n_dofs(e->type(), o);
     156             : }
     157             : 
     158             : 
     159             : 
     160    24552910 : unsigned int HIERARCHIC_n_dofs_at_node(const ElemType t,
     161             :                                        const Order o,
     162             :                                        const unsigned int n)
     163             : {
     164     1718859 :   libmesh_assert_greater (o, 0);
     165    24552910 :   switch (t)
     166             :     {
     167           0 :     case NODEELEM:
     168           0 :       return 1;
     169      160815 :     case EDGE2:
     170             :     case EDGE3:
     171      160815 :       switch (n)
     172             :         {
     173        9000 :         case 0:
     174             :         case 1:
     175        9000 :           return 1;
     176             :           // Internal DoFs are associated with the elem, not its nodes
     177        8329 :         case 2:
     178        4166 :           libmesh_assert_equal_to(t, EDGE3);
     179        8329 :           return 0;
     180           0 :         default:
     181           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for EDGE2/3!");
     182             :         }
     183      816336 :     case TRI3:
     184         792 :       libmesh_assert_less (n, 3);
     185         792 :       libmesh_assert_less (o, 2);
     186             :       libmesh_fallthrough();
     187             :     case TRI6:
     188             :       // Internal DoFs are associated with the elem on a Tri6, or node 6 on a Tri7
     189       42128 :       libmesh_assert_less (n, 6);
     190             :       libmesh_fallthrough();
     191             :     case TRI7:
     192      879253 :       switch (n)
     193             :         {
     194       31798 :         case 0:
     195             :         case 1:
     196             :         case 2:
     197       31798 :           return 1;
     198             : 
     199       28819 :         case 3:
     200             :         case 4:
     201             :         case 5:
     202      395972 :           return (o-1);
     203             : 
     204        3092 :         case 6:
     205       39263 :           return ((o-1)*(o-2)/2);
     206           0 :         default:
     207           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TRI!");
     208             :         }
     209     3914603 :     case QUAD4:
     210             :     case QUADSHELL4:
     211         513 :       libmesh_assert_less (n, 4);
     212         513 :       libmesh_assert_less (o, 2);
     213             :       libmesh_fallthrough();
     214             :     case QUAD8:
     215             :     case QUADSHELL8:
     216             :     case QUAD9:
     217             :     case QUADSHELL9:
     218     4245922 :       switch (n)
     219             :         {
     220      153896 :         case 0:
     221             :         case 1:
     222             :         case 2:
     223             :         case 3:
     224      153896 :           return 1;
     225             : 
     226      142428 :         case 4:
     227             :         case 5:
     228             :         case 6:
     229             :         case 7:
     230     1819146 :           return (o-1);
     231             : 
     232             :           // Internal DoFs are associated with the elem, not its nodes
     233       70840 :         case 8:
     234       70840 :           return 0;
     235             : 
     236           0 :         default:
     237           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for QUAD4/8/9!");
     238             :         }
     239    12964603 :     case HEX8:
     240        1593 :       libmesh_assert_less (n, 8);
     241        1593 :       libmesh_assert_less (o, 2);
     242             :       libmesh_fallthrough();
     243             :     case HEX20:
     244        1593 :       libmesh_assert_less (n, 20);
     245        1593 :       libmesh_assert_less (o, 2);
     246             :       libmesh_fallthrough();
     247             :     case HEX27:
     248    13914242 :       switch (n)
     249             :         {
     250      289053 :         case 0:
     251             :         case 1:
     252             :         case 2:
     253             :         case 3:
     254             :         case 4:
     255             :         case 5:
     256             :         case 6:
     257             :         case 7:
     258      289053 :           return 1;
     259             : 
     260      418027 :         case 8:
     261             :         case 9:
     262             :         case 10:
     263             :         case 11:
     264             :         case 12:
     265             :         case 13:
     266             :         case 14:
     267             :         case 15:
     268             :         case 16:
     269             :         case 17:
     270             :         case 18:
     271             :         case 19:
     272     6084822 :           return (o-1);
     273             : 
     274      209388 :         case 20:
     275             :         case 21:
     276             :         case 22:
     277             :         case 23:
     278             :         case 24:
     279             :         case 25:
     280     3045864 :           return ((o-1)*(o-1));
     281             : 
     282             :           // Internal DoFs are associated with the elem, not its nodes
     283       68637 :         case 26:
     284       68637 :           return 0;
     285           0 :         default:
     286           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for HEX8/20/27!");
     287             :         }
     288             : 
     289     1789578 :     case PRISM6:
     290        2322 :       libmesh_assert_less (n, 6);
     291             :       libmesh_fallthrough();
     292             :     case PRISM15:
     293        7740 :       libmesh_assert_less (n, 15);
     294        7740 :       libmesh_assert_less (o, 2);
     295             :       libmesh_fallthrough();
     296             :     case PRISM18:
     297       26721 :       libmesh_assert_less (n, 18);
     298       26721 :       libmesh_assert_less (o, 3);
     299             :       libmesh_fallthrough();
     300             :     case PRISM20:
     301             :       // Internal DoFs are associated with the elem on a Prism20, or
     302             :       // node 20 on a Prism21
     303       97794 :       libmesh_assert_less (n, 20);
     304             :       libmesh_fallthrough();
     305             :     case PRISM21:
     306      172422 :       libmesh_assert_less (n, 21);
     307     1959678 :       switch (n)
     308             :         {
     309       54756 :         case 0:
     310             :         case 1:
     311             :         case 2:
     312             :         case 3:
     313             :         case 4:
     314             :         case 5:
     315       54756 :           return 1;
     316             : 
     317       75807 :         case 6:
     318             :         case 7:
     319             :         case 8:
     320             :         case 9:
     321             :         case 10:
     322             :         case 11:
     323             :         case 12:
     324             :         case 13:
     325             :         case 14:
     326      861876 :           return (o-1);
     327             : 
     328       24300 :         case 15:
     329             :         case 16:
     330             :         case 17:
     331      276732 :           return ((o-1)*(o-1));
     332             : 
     333       14004 :         case 18:
     334             :         case 19:
     335      159624 :           return ((o-1)*(o-2)/2);
     336        3555 :         case 20:
     337       44109 :           return ((o-1)*(o-1)*(o-2)/2);
     338           0 :         default:
     339           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TRI!");
     340             :         }
     341             : 
     342     3213441 :     case TET4:
     343        6939 :       libmesh_assert_less (o, 2);
     344        6939 :       libmesh_assert_less (n, 4);
     345             :       libmesh_fallthrough();
     346             :     case TET10:
     347       39420 :       libmesh_assert_less (o, 3);
     348       39420 :       libmesh_assert_less (n, 10);
     349             :       libmesh_fallthrough();
     350             :     case TET14:
     351      186498 :       libmesh_assert_less (n, 14);
     352     3206502 :       switch (n)
     353             :         {
     354       65556 :         case 0:
     355             :         case 1:
     356             :         case 2:
     357             :         case 3:
     358       65556 :           return 1;
     359             : 
     360       79866 :         case 4:
     361             :         case 5:
     362             :         case 6:
     363             :         case 7:
     364             :         case 8:
     365             :         case 9:
     366     1402218 :           return (o-1);
     367             : 
     368       41076 :         case 10:
     369             :         case 11:
     370             :         case 12:
     371             :         case 13:
     372      696546 :           return ((o-1)*(o-2)/2);
     373             : 
     374           0 :         default:
     375           0 :           libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TET!");
     376             :         }
     377             : 
     378             : 
     379           0 :     case INVALID_ELEM:
     380           0 :       return 0;
     381             : 
     382           0 :     default:
     383           0 :       libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     384             :     }
     385             : } // HIERARCHIC_n_dofs_at_node()
     386             : 
     387             : 
     388             : 
     389     5837126 : unsigned int HIERARCHIC_n_dofs_at_node(const Elem & e,
     390             :                                        const Order o,
     391             :                                        const unsigned int n)
     392             : {
     393     6238459 :   return HIERARCHIC_n_dofs_at_node(e.type(), o, n);
     394             : }
     395             : 
     396             : 
     397             : 
     398     1337092 : unsigned int HIERARCHIC_n_dofs_per_elem(const ElemType t,
     399             :                                         const Order o)
     400             : {
     401       94871 :   libmesh_assert_greater (o, 0);
     402     1337092 :   switch (t)
     403             :     {
     404           0 :     case NODEELEM:
     405           0 :       return 0;
     406        4135 :     case EDGE2:
     407             :     case EDGE3:
     408       50673 :       return (o-1);
     409         351 :     case TRI3:
     410             :     case TRISHELL3:
     411             :     case QUAD4:
     412             :     case QUADSHELL4:
     413         351 :       return 0;
     414        6076 :     case TRI6:
     415       86812 :       return ((o-1)*(o-2)/2);
     416        2732 :     case TRI7:
     417        2732 :       return 0;
     418       32816 :     case QUAD8:
     419             :     case QUADSHELL8:
     420             :     case QUAD9:
     421             :     case QUADSHELL9:
     422      419437 :       return ((o-1)*(o-1));
     423         189 :     case HEX8:
     424             :     case HEX20:
     425         189 :       libmesh_assert_less (o, 2);
     426         189 :       return 0;
     427       29033 :     case HEX27:
     428      428755 :       return ((o-1)*(o-1)*(o-1));
     429         720 :     case PRISM6:
     430             :     case PRISM15:
     431         720 :       libmesh_assert_less (o, 2);
     432             :       libmesh_fallthrough();
     433             :     case PRISM18:
     434        1557 :       libmesh_assert_less (o, 3);
     435        1557 :       return 0;
     436        2799 :     case PRISM20:
     437       34551 :       return ((o-1)*(o-1)*(o-2)/2);
     438        2799 :     case PRISM21: // Store interior DoFs on interior node
     439        2799 :       return 0;
     440        1449 :     case TET4:
     441        1449 :       libmesh_assert_less (o, 2);
     442             :       libmesh_fallthrough();
     443             :     case TET10:
     444        4122 :       libmesh_assert_less (o, 3);
     445             :       libmesh_fallthrough();
     446             :     case TET14:
     447      242019 :       return ((o-3)*(o-2)*(o-1)/6);
     448           0 :     case INVALID_ELEM:
     449           0 :       return 0;
     450           0 :     default:
     451           0 :       libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     452             :     }
     453             : } // HIERARCHIC_n_dofs_per_elem()
     454             : 
     455             : 
     456             : 
     457     1185387 : unsigned int HIERARCHIC_n_dofs_per_elem(const Elem & e,
     458             :                                         const Order o)
     459             : {
     460     1273784 :   return HIERARCHIC_n_dofs_per_elem(e.type(), o);
     461             : }
     462             : 
     463             : } // anonymous namespace
     464             : 
     465             : 
     466             : // Instantiate (side_) nodal_soln() function for every dimension
     467        4824 : LIBMESH_FE_NODAL_SOLN(HIERARCHIC, hierarchic_nodal_soln)
     468        1248 : LIBMESH_FE_SIDE_NODAL_SOLN(HIERARCHIC)
     469             : 
     470             : 
     471             : // Instantiate n_dofs*() functions for every dimension
     472    27461691 : LIBMESH_DEFAULT_NDOFS(HIERARCHIC)
     473             : 
     474             : 
     475             : // Hierarchic FEMs are C^0 continuous
     476           0 : template <> FEContinuity FE<0,HIERARCHIC>::get_continuity() const { return C_ZERO; }
     477       27744 : template <> FEContinuity FE<1,HIERARCHIC>::get_continuity() const { return C_ZERO; }
     478      107090 : template <> FEContinuity FE<2,HIERARCHIC>::get_continuity() const { return C_ZERO; }
     479      237044 : template <> FEContinuity FE<3,HIERARCHIC>::get_continuity() const { return C_ZERO; }
     480             : 
     481             : // Hierarchic FEMs are hierarchic (duh!)
     482           0 : template <> bool FE<0,HIERARCHIC>::is_hierarchic() const { return true; }
     483          48 : template <> bool FE<1,HIERARCHIC>::is_hierarchic() const { return true; }
     484         250 : template <> bool FE<2,HIERARCHIC>::is_hierarchic() const { return true; }
     485         516 : template <> bool FE<3,HIERARCHIC>::is_hierarchic() const { return true; }
     486             : 
     487             : #ifdef LIBMESH_ENABLE_AMR
     488             : // compute_constraints() specializations are only needed for 2 and 3D
     489             : template <>
     490       17428 : void FE<2,HIERARCHIC>::compute_constraints (DofConstraints & constraints,
     491             :                                             DofMap & dof_map,
     492             :                                             const unsigned int variable_number,
     493             :                                             const Elem * elem)
     494       17428 : { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
     495             : 
     496             : template <>
     497       18972 : void FE<3,HIERARCHIC>::compute_constraints (DofConstraints & constraints,
     498             :                                             DofMap & dof_map,
     499             :                                             const unsigned int variable_number,
     500             :                                             const Elem * elem)
     501       18972 : { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
     502             : #endif // #ifdef LIBMESH_ENABLE_AMR
     503             : 
     504             : // Hierarchic FEM shapes need reinit
     505           0 : template <> bool FE<0,HIERARCHIC>::shapes_need_reinit() const { return true; }
     506       15954 : template <> bool FE<1,HIERARCHIC>::shapes_need_reinit() const { return true; }
     507      177631 : template <> bool FE<2,HIERARCHIC>::shapes_need_reinit() const { return true; }
     508      160714 : template <> bool FE<3,HIERARCHIC>::shapes_need_reinit() const { return true; }
     509             : 
     510             : } // namespace libMesh

Generated by: LCOV version 1.14