LCOV - code coverage report
Current view: top level - src/fe - fe_lagrange.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 381 534 71.3 %
Date: 2025-08-19 19:27:09 Functions: 47 60 78.3 %
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/dof_map.h"
      22             : #include "libmesh/elem.h"
      23             : #include "libmesh/enum_to_string.h"
      24             : #include "libmesh/fe.h"
      25             : #include "libmesh/fe_interface.h"
      26             : #include "libmesh/fe_macro.h"
      27             : #include "libmesh/remote_elem.h"
      28             : #include "libmesh/threads.h"
      29             : 
      30             : 
      31             : #ifdef LIBMESH_ENABLE_AMR
      32             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
      33             : // to have the macro 'inf_fe_switch' available.
      34             : #include "libmesh/fe_interface_macros.h"
      35             : #include "libmesh/inf_fe.h"
      36             : #endif
      37             : #endif
      38             : 
      39             : namespace libMesh
      40             : {
      41             : 
      42             : // global helper function
      43     8596910 : void lagrange_nodal_soln(const Elem * elem,
      44             :                          const Order order,
      45             :                          const std::vector<Number> & elem_soln,
      46             :                          std::vector<Number> &       nodal_soln,
      47             :                          const bool add_p_level)
      48             : {
      49     8596910 :   const unsigned int n_nodes = elem->n_nodes();
      50     8596910 :   const ElemType type        = elem->type();
      51             : 
      52     9362368 :   const Order totalorder = order + add_p_level*elem->p_level();
      53             : 
      54     8596910 :   nodal_soln.resize(n_nodes);
      55             : 
      56             : 
      57             : 
      58     8596910 :   switch (totalorder)
      59             :     {
      60             :       // linear Lagrange shape functions
      61     7713227 :     case FIRST:
      62             :       {
      63     7713227 :         switch (type)
      64             :           {
      65         328 :           case EDGE3:
      66             :             {
      67         164 :               libmesh_assert_equal_to (elem_soln.size(), 2);
      68         164 :               libmesh_assert_equal_to (nodal_soln.size(), 3);
      69             : 
      70        1968 :               nodal_soln[0] = elem_soln[0];
      71        1968 :               nodal_soln[1] = elem_soln[1];
      72        1968 :               nodal_soln[2] = .5*(elem_soln[0] + elem_soln[1]);
      73             : 
      74        1968 :               return;
      75             :             }
      76             : 
      77           0 :           case EDGE4:
      78             :             {
      79           0 :               libmesh_assert_equal_to (elem_soln.size(), 2);
      80           0 :               libmesh_assert_equal_to (nodal_soln.size(), 4);
      81             : 
      82           0 :               nodal_soln[0] = elem_soln[0];
      83           0 :               nodal_soln[1] = elem_soln[1];
      84           0 :               nodal_soln[2] = (2.*elem_soln[0] + elem_soln[1])/3.;
      85           0 :               nodal_soln[3] = (elem_soln[0] + 2.*elem_soln[1])/3.;
      86             : 
      87           0 :               return;
      88             :             }
      89             : 
      90             : 
      91        1350 :           case TRI7:
      92         450 :             libmesh_assert_equal_to (nodal_soln.size(), 7);
      93        5400 :             nodal_soln[6] = (elem_soln[0] + elem_soln[1] + elem_soln[2])/3.;
      94             :             libmesh_fallthrough();
      95       15120 :           case TRI6:
      96             :             {
      97        1292 :               libmesh_assert (type == TRI7 || nodal_soln.size() == 6);
      98        1292 :               libmesh_assert_equal_to (elem_soln.size(), 3);
      99             : 
     100       15120 :               nodal_soln[0] = elem_soln[0];
     101       15120 :               nodal_soln[1] = elem_soln[1];
     102       15120 :               nodal_soln[2] = elem_soln[2];
     103       15120 :               nodal_soln[3] = .5*(elem_soln[0] + elem_soln[1]);
     104       15120 :               nodal_soln[4] = .5*(elem_soln[1] + elem_soln[2]);
     105       15120 :               nodal_soln[5] = .5*(elem_soln[2] + elem_soln[0]);
     106             : 
     107       15120 :               return;
     108             :             }
     109             : 
     110             : 
     111       22647 :           case QUAD8:
     112             :           case QUAD9:
     113             :             {
     114       22647 :               libmesh_assert_equal_to (elem_soln.size(), 4);
     115             : 
     116       22647 :               if (type == QUAD8)
     117           0 :                 libmesh_assert_equal_to (nodal_soln.size(), 8);
     118             :               else
     119       22647 :                 libmesh_assert_equal_to (nodal_soln.size(), 9);
     120             : 
     121             : 
     122      269869 :               nodal_soln[0] = elem_soln[0];
     123      269869 :               nodal_soln[1] = elem_soln[1];
     124      269869 :               nodal_soln[2] = elem_soln[2];
     125      269869 :               nodal_soln[3] = elem_soln[3];
     126      269869 :               nodal_soln[4] = .5*(elem_soln[0] + elem_soln[1]);
     127      269869 :               nodal_soln[5] = .5*(elem_soln[1] + elem_soln[2]);
     128      269869 :               nodal_soln[6] = .5*(elem_soln[2] + elem_soln[3]);
     129      269869 :               nodal_soln[7] = .5*(elem_soln[3] + elem_soln[0]);
     130             : 
     131      269869 :               if (type == QUAD9)
     132      269869 :                 nodal_soln[8] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3]);
     133             : 
     134       22647 :               return;
     135             :             }
     136             : 
     137             : 
     138        4608 :           case TET14:
     139        1536 :             libmesh_assert_equal_to (nodal_soln.size(), 14);
     140       18432 :             nodal_soln[10] = (elem_soln[0] + elem_soln[1] + elem_soln[2])/3.;
     141       18432 :             nodal_soln[11] = (elem_soln[0] + elem_soln[1] + elem_soln[3])/3.;
     142       18432 :             nodal_soln[12] = (elem_soln[1] + elem_soln[2] + elem_soln[3])/3.;
     143       18432 :             nodal_soln[13] = (elem_soln[0] + elem_soln[2] + elem_soln[3])/3.;
     144             :             libmesh_fallthrough();
     145       18432 :           case TET10:
     146             :             {
     147        1536 :               libmesh_assert_equal_to (elem_soln.size(), 4);
     148        1536 :               libmesh_assert (type == TET14 || nodal_soln.size() == 10);
     149             : 
     150       18432 :               nodal_soln[0] = elem_soln[0];
     151       18432 :               nodal_soln[1] = elem_soln[1];
     152       18432 :               nodal_soln[2] = elem_soln[2];
     153       18432 :               nodal_soln[3] = elem_soln[3];
     154       18432 :               nodal_soln[4] = .5*(elem_soln[0] + elem_soln[1]);
     155       18432 :               nodal_soln[5] = .5*(elem_soln[1] + elem_soln[2]);
     156       18432 :               nodal_soln[6] = .5*(elem_soln[2] + elem_soln[0]);
     157       18432 :               nodal_soln[7] = .5*(elem_soln[3] + elem_soln[0]);
     158       18432 :               nodal_soln[8] = .5*(elem_soln[3] + elem_soln[1]);
     159       18432 :               nodal_soln[9] = .5*(elem_soln[3] + elem_soln[2]);
     160             : 
     161       18432 :               return;
     162             :             }
     163             : 
     164             : 
     165        1936 :           case HEX20:
     166             :           case HEX27:
     167             :             {
     168        1936 :               libmesh_assert_equal_to (elem_soln.size(), 8);
     169             : 
     170        1936 :               if (type == HEX20)
     171           0 :                 libmesh_assert_equal_to (nodal_soln.size(), 20);
     172             :               else
     173        1936 :                 libmesh_assert_equal_to (nodal_soln.size(), 27);
     174             : 
     175       23112 :               nodal_soln[0]  = elem_soln[0];
     176       23112 :               nodal_soln[1]  = elem_soln[1];
     177       23112 :               nodal_soln[2]  = elem_soln[2];
     178       23112 :               nodal_soln[3]  = elem_soln[3];
     179       23112 :               nodal_soln[4]  = elem_soln[4];
     180       23112 :               nodal_soln[5]  = elem_soln[5];
     181       23112 :               nodal_soln[6]  = elem_soln[6];
     182       23112 :               nodal_soln[7]  = elem_soln[7];
     183       23112 :               nodal_soln[8]  = .5*(elem_soln[0] + elem_soln[1]);
     184       23112 :               nodal_soln[9]  = .5*(elem_soln[1] + elem_soln[2]);
     185       23112 :               nodal_soln[10] = .5*(elem_soln[2] + elem_soln[3]);
     186       23112 :               nodal_soln[11] = .5*(elem_soln[3] + elem_soln[0]);
     187       23112 :               nodal_soln[12] = .5*(elem_soln[0] + elem_soln[4]);
     188       23112 :               nodal_soln[13] = .5*(elem_soln[1] + elem_soln[5]);
     189       23112 :               nodal_soln[14] = .5*(elem_soln[2] + elem_soln[6]);
     190       23112 :               nodal_soln[15] = .5*(elem_soln[3] + elem_soln[7]);
     191       23112 :               nodal_soln[16] = .5*(elem_soln[4] + elem_soln[5]);
     192       23112 :               nodal_soln[17] = .5*(elem_soln[5] + elem_soln[6]);
     193       23112 :               nodal_soln[18] = .5*(elem_soln[6] + elem_soln[7]);
     194       23112 :               nodal_soln[19] = .5*(elem_soln[4] + elem_soln[7]);
     195             : 
     196       23112 :               if (type == HEX27)
     197             :                 {
     198       23112 :                   nodal_soln[20] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3]);
     199       23112 :                   nodal_soln[21] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[4] + elem_soln[5]);
     200       23112 :                   nodal_soln[22] = .25*(elem_soln[1] + elem_soln[2] + elem_soln[5] + elem_soln[6]);
     201       23112 :                   nodal_soln[23] = .25*(elem_soln[2] + elem_soln[3] + elem_soln[6] + elem_soln[7]);
     202       23112 :                   nodal_soln[24] = .25*(elem_soln[3] + elem_soln[0] + elem_soln[7] + elem_soln[4]);
     203       23112 :                   nodal_soln[25] = .25*(elem_soln[4] + elem_soln[5] + elem_soln[6] + elem_soln[7]);
     204             : 
     205       26984 :                   nodal_soln[26] = .125*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3] +
     206       21296 :                                          elem_soln[4] + elem_soln[5] + elem_soln[6] + elem_soln[7]);
     207             :                 }
     208             : 
     209        1936 :               return;
     210             :             }
     211             : 
     212             : 
     213           0 :           case PRISM21:
     214           0 :             nodal_soln[20]  = (elem_soln[9] + elem_soln[10] + elem_soln[11])/Real(3);
     215             :             libmesh_fallthrough();
     216           0 :           case PRISM20:
     217           0 :             if (type == PRISM20)
     218           0 :               libmesh_assert_equal_to (nodal_soln.size(), 20);
     219           0 :             nodal_soln[18]  = (elem_soln[0] + elem_soln[1] + elem_soln[2])/Real(3);
     220           0 :             nodal_soln[19]  = (elem_soln[3] + elem_soln[4] + elem_soln[5])/Real(3);
     221             :             libmesh_fallthrough();
     222           0 :           case PRISM18:
     223           0 :             if (type == PRISM18)
     224           0 :               libmesh_assert_equal_to (nodal_soln.size(), 18);
     225           0 :             nodal_soln[15] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[4] + elem_soln[3]);
     226           0 :             nodal_soln[16] = .25*(elem_soln[1] + elem_soln[2] + elem_soln[5] + elem_soln[4]);
     227           0 :             nodal_soln[17] = .25*(elem_soln[2] + elem_soln[0] + elem_soln[3] + elem_soln[5]);
     228             :             libmesh_fallthrough();
     229           0 :           case PRISM15:
     230             :             {
     231           0 :               libmesh_assert_equal_to (elem_soln.size(), 6);
     232             : 
     233           0 :               if (type == PRISM15)
     234           0 :                 libmesh_assert_equal_to (nodal_soln.size(), 15);
     235             : 
     236           0 :               nodal_soln[0]  = elem_soln[0];
     237           0 :               nodal_soln[1]  = elem_soln[1];
     238           0 :               nodal_soln[2]  = elem_soln[2];
     239           0 :               nodal_soln[3]  = elem_soln[3];
     240           0 :               nodal_soln[4]  = elem_soln[4];
     241           0 :               nodal_soln[5]  = elem_soln[5];
     242           0 :               nodal_soln[6]  = .5*(elem_soln[0] + elem_soln[1]);
     243           0 :               nodal_soln[7]  = .5*(elem_soln[1] + elem_soln[2]);
     244           0 :               nodal_soln[8]  = .5*(elem_soln[0] + elem_soln[2]);
     245           0 :               nodal_soln[9]  = .5*(elem_soln[0] + elem_soln[3]);
     246           0 :               nodal_soln[10] = .5*(elem_soln[1] + elem_soln[4]);
     247           0 :               nodal_soln[11] = .5*(elem_soln[2] + elem_soln[5]);
     248           0 :               nodal_soln[12] = .5*(elem_soln[3] + elem_soln[4]);
     249           0 :               nodal_soln[13] = .5*(elem_soln[4] + elem_soln[5]);
     250           0 :               nodal_soln[14] = .5*(elem_soln[3] + elem_soln[5]);
     251             : 
     252           0 :               return;
     253             :             }
     254             : 
     255           0 :           case PYRAMID18:
     256             :             {
     257           0 :               libmesh_assert_equal_to (nodal_soln.size(), 18);
     258             : 
     259           0 :               nodal_soln[14] = (elem_soln[0] + elem_soln[1] + elem_soln[4])/Real(3);
     260           0 :               nodal_soln[15] = (elem_soln[1] + elem_soln[2] + elem_soln[4])/Real(3);
     261           0 :               nodal_soln[16] = (elem_soln[2] + elem_soln[3] + elem_soln[4])/Real(3);
     262           0 :               nodal_soln[17] = (elem_soln[0] + elem_soln[3] + elem_soln[4])/Real(3);
     263             : 
     264             :               libmesh_fallthrough();
     265             :             }
     266             : 
     267           0 :           case PYRAMID14:
     268             :             {
     269           0 :               if (type == PYRAMID14)
     270           0 :                 libmesh_assert_equal_to (nodal_soln.size(), 14);
     271             : 
     272           0 :               nodal_soln[13] = .25*(elem_soln[0] + elem_soln[1] + elem_soln[2] + elem_soln[3]);
     273             : 
     274             :               libmesh_fallthrough();
     275             :             }
     276             : 
     277           0 :           case PYRAMID13:
     278             :             {
     279           0 :               libmesh_assert_equal_to (elem_soln.size(), 5);
     280             : 
     281           0 :               if (type == PYRAMID13)
     282           0 :                 libmesh_assert_equal_to (nodal_soln.size(), 13);
     283             : 
     284           0 :               nodal_soln[0]  = elem_soln[0];
     285           0 :               nodal_soln[1]  = elem_soln[1];
     286           0 :               nodal_soln[2]  = elem_soln[2];
     287           0 :               nodal_soln[3]  = elem_soln[3];
     288           0 :               nodal_soln[4]  = elem_soln[4];
     289           0 :               nodal_soln[5]  = .5*(elem_soln[0] + elem_soln[1]);
     290           0 :               nodal_soln[6]  = .5*(elem_soln[1] + elem_soln[2]);
     291           0 :               nodal_soln[7]  = .5*(elem_soln[2] + elem_soln[3]);
     292           0 :               nodal_soln[8]  = .5*(elem_soln[3] + elem_soln[0]);
     293           0 :               nodal_soln[9]  = .5*(elem_soln[0] + elem_soln[4]);
     294           0 :               nodal_soln[10] = .5*(elem_soln[1] + elem_soln[4]);
     295           0 :               nodal_soln[11] = .5*(elem_soln[2] + elem_soln[4]);
     296           0 :               nodal_soln[12] = .5*(elem_soln[3] + elem_soln[4]);
     297             : 
     298           0 :               return;
     299             :             }
     300     7384726 :           default:
     301             :             {
     302             :               // By default the element solution _is_ nodal,
     303             :               // so just copy it.
     304     7384726 :               nodal_soln = elem_soln;
     305             : 
     306     7384726 :               return;
     307             :             }
     308             :           }
     309             :       }
     310             : 
     311      881163 :     case SECOND:
     312             :       {
     313      881163 :         switch (type)
     314             :           {
     315           0 :           case EDGE4:
     316             :             {
     317           0 :               libmesh_assert_equal_to (elem_soln.size(), 3);
     318           0 :               libmesh_assert_equal_to (nodal_soln.size(), 4);
     319             : 
     320             :               // Project quadratic solution onto cubic element nodes
     321           0 :               nodal_soln[0] = elem_soln[0];
     322           0 :               nodal_soln[1] = elem_soln[1];
     323           0 :               nodal_soln[2] = (2.*elem_soln[0] - elem_soln[1] +
     324           0 :                                8.*elem_soln[2])/9.;
     325           0 :               nodal_soln[3] = (-elem_soln[0] + 2.*elem_soln[1] +
     326           0 :                                8.*elem_soln[2])/9.;
     327           0 :               return;
     328             :             }
     329             : 
     330         450 :           case TRI7:
     331             :             {
     332         450 :               libmesh_assert_equal_to (elem_soln.size(), 6);
     333         450 :               libmesh_assert_equal_to (nodal_soln.size(), 7);
     334             : 
     335       37800 :               for (int i=0; i != 6; ++i)
     336       37800 :                 nodal_soln[i] = elem_soln[i];
     337             : 
     338        5850 :               nodal_soln[6] = -1./9. * (elem_soln[0] + elem_soln[1] + elem_soln[2])
     339        4950 :                               +4./9. * (elem_soln[3] + elem_soln[4] + elem_soln[5]);
     340             : 
     341        5400 :               return;
     342             :             }
     343             : 
     344        1536 :           case TET14:
     345             :             {
     346        1536 :               libmesh_assert_equal_to (elem_soln.size(), 10);
     347        1536 :               libmesh_assert_equal_to (nodal_soln.size(), 14);
     348             : 
     349      202752 :               for (int i=0; i != 10; ++i)
     350      215040 :                 nodal_soln[i] = elem_soln[i];
     351             : 
     352       19968 :               nodal_soln[10] = -1./9. * (elem_soln[0] + elem_soln[1] + elem_soln[2])
     353       16896 :                                +4./9. * (elem_soln[4] + elem_soln[5] + elem_soln[6]);
     354       19968 :               nodal_soln[11] = -1./9. * (elem_soln[0] + elem_soln[1] + elem_soln[3])
     355       16896 :                                +4./9. * (elem_soln[4] + elem_soln[7] + elem_soln[8]);
     356       19968 :               nodal_soln[12] = -1./9. * (elem_soln[1] + elem_soln[2] + elem_soln[3])
     357       16896 :                                +4./9. * (elem_soln[5] + elem_soln[8] + elem_soln[9]);
     358       19968 :               nodal_soln[13] = -1./9. * (elem_soln[0] + elem_soln[2] + elem_soln[3])
     359       16896 :                                +4./9. * (elem_soln[6] + elem_soln[7] + elem_soln[9]);
     360             : 
     361       18432 :               return;
     362             :             }
     363             : 
     364         606 :           case PRISM21:
     365             :             {
     366        2424 :               nodal_soln[20]  = (elem_soln[9] + elem_soln[10] + elem_soln[11])/Real(3);
     367             :               libmesh_fallthrough();
     368             :             }
     369         202 :           case PRISM20:
     370             :             {
     371         202 :               if (type == PRISM20)
     372           0 :                 libmesh_assert_equal_to (nodal_soln.size(), 20);
     373             : 
     374       46056 :               for (int i=0; i != 18; ++i)
     375       50904 :                 nodal_soln[i] = elem_soln[i];
     376             : 
     377        2424 :               nodal_soln[18]  = (elem_soln[0] + elem_soln[1] + elem_soln[2])/Real(3);
     378        2424 :               nodal_soln[19]  = (elem_soln[3] + elem_soln[4] + elem_soln[5])/Real(3);
     379        2424 :               return;
     380             :             }
     381             : 
     382           0 :           case PYRAMID18:
     383             :             {
     384           0 :               libmesh_assert_equal_to (nodal_soln.size(), 18);
     385             : 
     386           0 :               for (int i=0; i != 14; ++i)
     387           0 :                 nodal_soln[i] = elem_soln[i];
     388             : 
     389           0 :               nodal_soln[14] = (elem_soln[0] + elem_soln[1] + elem_soln[4])/Real(3);
     390           0 :               nodal_soln[15] = (elem_soln[1] + elem_soln[2] + elem_soln[4])/Real(3);
     391           0 :               nodal_soln[16] = (elem_soln[2] + elem_soln[3] + elem_soln[4])/Real(3);
     392           0 :               nodal_soln[17] = (elem_soln[0] + elem_soln[3] + elem_soln[4])/Real(3);
     393             : 
     394             :               libmesh_fallthrough();
     395             :             }
     396             : 
     397      854907 :           default:
     398             :             {
     399             :               // By default the element solution _is_ nodal, so just
     400             :               // copy the portion relevant to the nodal solution.
     401             :               // (this is the whole nodal solution for true Lagrange
     402             :               // elements, but a smaller part for "L2 Lagrange"
     403       75879 :               libmesh_assert_less_equal(nodal_soln.size(), elem_soln.size());
     404     8558616 :               for (const auto i : index_range(nodal_soln))
     405     9070433 :                 nodal_soln[i] = elem_soln[i];
     406             : 
     407      151758 :               return;
     408             :             }
     409             :           }
     410             :       }
     411             : 
     412             : 
     413             : 
     414             : 
     415         210 :     default:
     416             :       {
     417             :         // By default the element solution _is_ nodal, so just copy
     418             :         // the portion relevant to the nodal solution.  (this is the
     419             :         // whole nodal solution for true Lagrange elements, but a
     420             :         // smaller part for "L2 Lagrange"
     421         210 :         libmesh_assert_less_equal(nodal_soln.size(), elem_soln.size());
     422       49392 :         for (const auto i : index_range(nodal_soln))
     423       54684 :           nodal_soln[i] = elem_soln[i];
     424             : 
     425         420 :         return;
     426             :       }
     427             :     }
     428             : }
     429             : 
     430             : 
     431             : // Anonymous namespace for local helper functions
     432             : namespace {
     433  1238611585 : unsigned int lagrange_n_dofs(const ElemType t, const Elem * e, const Order o)
     434             : {
     435   108235564 :   libmesh_assert(!e || e->type() == t);
     436             : 
     437  1238611585 :   switch (o)
     438             :     {
     439             :       // lagrange can only be constant on a single node
     440      146021 :     case CONSTANT:
     441             :       {
     442      146021 :         switch (t)
     443             :           {
     444       12157 :           case NODEELEM:
     445       12157 :             return 1;
     446             : 
     447           0 :           default:
     448           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     449             :           }
     450             :       }
     451             : 
     452             :       // linear Lagrange shape functions
     453   289996873 :     case FIRST:
     454             :       {
     455   289996873 :         switch (t)
     456             :           {
     457        1352 :           case NODEELEM:
     458        1352 :             return 1;
     459             : 
     460    14590287 :           case EDGE2:
     461             :           case EDGE3:
     462             :           case EDGE4:
     463    14590287 :             return 2;
     464             : 
     465     6633714 :           case TRI3:
     466             :           case TRISHELL3:
     467             :           case TRI3SUBDIVISION:
     468             :           case TRI6:
     469             :           case TRI7:
     470     6633714 :             return 3;
     471             : 
     472    23461617 :           case QUAD4:
     473             :           case QUADSHELL4:
     474             :           case QUAD8:
     475             :           case QUADSHELL8:
     476             :           case QUAD9:
     477             :           case QUADSHELL9:
     478    23461617 :             return 4;
     479             : 
     480     1450476 :           case TET4:
     481             :           case TET10:
     482             :           case TET14:
     483     1450476 :             return 4;
     484             : 
     485    16721010 :           case HEX8:
     486             :           case HEX20:
     487             :           case HEX27:
     488    16721010 :             return 8;
     489             : 
     490     1754306 :           case PRISM6:
     491             :           case PRISM15:
     492             :           case PRISM18:
     493             :           case PRISM20:
     494             :           case PRISM21:
     495     1754306 :             return 6;
     496             : 
     497     1338847 :           case PYRAMID5:
     498             :           case PYRAMID13:
     499             :           case PYRAMID14:
     500             :           case PYRAMID18:
     501     1338847 :             return 5;
     502             : 
     503           0 :           case INVALID_ELEM:
     504           0 :             return 0;
     505             : 
     506     3714952 :           case C0POLYGON:
     507             :           case C0POLYHEDRON:
     508             :             // Polygons and polyhedra require using newer FE APIs
     509     3714952 :             if (!e)
     510           0 :               libmesh_error_msg("Code (see stack trace) used an outdated FE function overload.\n"
     511      631722 :                                 "n_dofs() on a polygon or polyhedron is not defined by ElemType alone.");
     512     3714952 :             return e->n_nodes();
     513             : 
     514           0 :           default:
     515           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     516             :           }
     517             :       }
     518             : 
     519             : 
     520             :       // quadratic Lagrange shape functions
     521   723048389 :     case SECOND:
     522             :       {
     523   723048389 :         switch (t)
     524             :           {
     525         195 :           case NODEELEM:
     526         195 :             return 1;
     527             : 
     528     5327004 :           case EDGE3:
     529     5327004 :             return 3;
     530             : 
     531    47285778 :           case TRI6:
     532             :           case TRI7:
     533    47285778 :             return 6;
     534             : 
     535     1321957 :           case QUAD8:
     536             :           case QUADSHELL8:
     537     1321957 :             return 8;
     538             : 
     539    21937851 :           case QUAD9:
     540             :           case QUADSHELL9:
     541    21937851 :             return 9;
     542             : 
     543    70566205 :           case TET10:
     544             :           case TET14:
     545    70566205 :             return 10;
     546             : 
     547     1380349 :           case HEX20:
     548     1380349 :             return 20;
     549             : 
     550   117730463 :           case HEX27:
     551   117730463 :             return 27;
     552             : 
     553    12649134 :           case PRISM15:
     554    12649134 :             return 15;
     555             : 
     556     3076907 :           case PRISM18:
     557             :           case PRISM20:
     558             :           case PRISM21:
     559     3076907 :             return 18;
     560             : 
     561     5209427 :           case PYRAMID13:
     562     5209427 :             return 13;
     563             : 
     564      353845 :           case PYRAMID14:
     565             :           case PYRAMID18:
     566      353845 :             return 14;
     567             : 
     568           0 :           case INVALID_ELEM:
     569           0 :             return 0;
     570             : 
     571           0 :           default:
     572           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     573             :           }
     574             :       }
     575             : 
     576   225420302 :     case THIRD:
     577             :       {
     578   225420302 :         switch (t)
     579             :           {
     580           0 :           case NODEELEM:
     581           0 :             return 1;
     582             : 
     583         616 :           case EDGE4:
     584         616 :             return 4;
     585             : 
     586     2274767 :           case PRISM20:
     587     2274767 :             return 20;
     588             : 
     589     3098398 :           case PRISM21:
     590     3098398 :             return 21;
     591             : 
     592      496071 :           case PYRAMID18:
     593      496071 :             return 18;
     594             : 
     595    82562892 :           case TRI7:
     596    82562892 :             return 7;
     597             : 
     598     6903944 :           case TET14:
     599     6903944 :             return 14;
     600             : 
     601           0 :           case INVALID_ELEM:
     602           0 :             return 0;
     603             : 
     604           0 :           default:
     605           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     606             :           }
     607             :       }
     608             : 
     609           0 :     default:
     610           0 :       libmesh_error_msg("ERROR: Invalid Order " << Utility::enum_to_string(o) << " selected for LAGRANGE FE family!");
     611             :     }
     612             : }
     613             : 
     614             : 
     615             : 
     616  1142628466 : unsigned int lagrange_n_dofs_at_node(const ElemType t,
     617             :                                      const Order o,
     618             :                                      const unsigned int n)
     619             : {
     620  1142628466 :   switch (o)
     621             :     {
     622             :       // lagrange can only be constant on a single node
     623           0 :     case CONSTANT:
     624             :       {
     625           0 :         switch (t)
     626             :           {
     627           0 :           case NODEELEM:
     628           0 :             return 1;
     629             : 
     630           0 :           default:
     631           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     632             :           }
     633             :       }
     634             : 
     635             :       // linear Lagrange shape functions
     636   831007147 :     case FIRST:
     637             :       {
     638   831007147 :         switch (t)
     639             :           {
     640        1648 :           case NODEELEM:
     641        1648 :             return 1;
     642             : 
     643    26848902 :           case EDGE2:
     644             :           case EDGE3:
     645             :           case EDGE4:
     646             :             {
     647    26848902 :               switch (n)
     648             :                 {
     649     1314237 :                 case 0:
     650             :                 case 1:
     651     1314237 :                   return 1;
     652             : 
     653     1208462 :                 default:
     654     1208462 :                   return 0;
     655             :                 }
     656             :             }
     657             : 
     658    74388071 :           case TRI3:
     659             :           case TRISHELL3:
     660             :           case TRI3SUBDIVISION:
     661             :           case TRI6:
     662             :           case TRI7:
     663             :             {
     664    74388071 :               switch (n)
     665             :                 {
     666     4834230 :                 case 0:
     667             :                 case 1:
     668             :                 case 2:
     669     4834230 :                   return 1;
     670             : 
     671       20237 :                 default:
     672       20237 :                   return 0;
     673             :                 }
     674             :             }
     675             : 
     676   491925633 :           case QUAD4:
     677             :           case QUADSHELL4:
     678             :           case QUAD8:
     679             :           case QUADSHELL8:
     680             :           case QUAD9:
     681             :           case QUADSHELL9:
     682             :             {
     683   491925633 :               switch (n)
     684             :                 {
     685    42859705 :                 case 0:
     686             :                 case 1:
     687             :                 case 2:
     688             :                 case 3:
     689    42859705 :                   return 1;
     690             : 
     691     6348191 :                 default:
     692     6348191 :                   return 0;
     693             :                 }
     694             :             }
     695             : 
     696        2322 :           case C0POLYGON:
     697             :           case C0POLYHEDRON:
     698        2322 :             return 1;
     699             : 
     700             : 
     701    71102891 :           case TET4:
     702             :           case TET10:
     703             :           case TET14:
     704             :             {
     705    71102891 :               switch (n)
     706             :                 {
     707     4126622 :                 case 0:
     708             :                 case 1:
     709             :                 case 2:
     710             :                 case 3:
     711     4126622 :                   return 1;
     712             : 
     713           0 :                 default:
     714           0 :                   return 0;
     715             :                 }
     716             :             }
     717             : 
     718   165289507 :           case HEX8:
     719             :           case HEX20:
     720             :           case HEX27:
     721             :             {
     722   165289507 :               switch (n)
     723             :                 {
     724    11925167 :                 case 0:
     725             :                 case 1:
     726             :                 case 2:
     727             :                 case 3:
     728             :                 case 4:
     729             :                 case 5:
     730             :                 case 6:
     731             :                 case 7:
     732    11925167 :                   return 1;
     733             : 
     734     2603770 :                 default:
     735     2603770 :                   return 0;
     736             :                 }
     737             :             }
     738             : 
     739     1319257 :           case PRISM6:
     740             :           case PRISM15:
     741             :           case PRISM18:
     742             :           case PRISM20:
     743             :           case PRISM21:
     744             :             {
     745     1319257 :               switch (n)
     746             :                 {
     747       81391 :                 case 0:
     748             :                 case 1:
     749             :                 case 2:
     750             :                 case 3:
     751             :                 case 4:
     752             :                 case 5:
     753       81391 :                   return 1;
     754             : 
     755           0 :                 default:
     756           0 :                   return 0;
     757             :                 }
     758             :             }
     759             : 
     760       70092 :           case PYRAMID5:
     761             :           case PYRAMID13:
     762             :           case PYRAMID14:
     763             :           case PYRAMID18:
     764             :             {
     765       70092 :               switch (n)
     766             :                 {
     767        3582 :                 case 0:
     768             :                 case 1:
     769             :                 case 2:
     770             :                 case 3:
     771             :                 case 4:
     772        3582 :                   return 1;
     773             : 
     774           0 :                 default:
     775           0 :                   return 0;
     776             :                 }
     777             :             }
     778             : 
     779           0 :           case INVALID_ELEM:
     780           0 :             return 0;
     781             : 
     782           0 :           default:
     783           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     784             :           }
     785             :       }
     786             : 
     787             :       // quadratic Lagrange shape functions
     788   303776555 :     case SECOND:
     789             :       {
     790   303776555 :         switch (t)
     791             :           {
     792             :             // quadratic lagrange has one dof at each node
     793    26012262 :           case NODEELEM:
     794             :           case EDGE3:
     795             :           case TRI6:
     796             :           case QUAD8:
     797             :           case QUADSHELL8:
     798             :           case QUAD9:
     799             :           case QUADSHELL9:
     800             :           case TET10:
     801             :           case HEX20:
     802             :           case HEX27:
     803             :           case PRISM15:
     804             :           case PRISM18:
     805             :           case PYRAMID13:
     806             :           case PYRAMID14:
     807    26012262 :             return 1;
     808             : 
     809     3645483 :           case PRISM20:
     810             :           case PRISM21:
     811     3645483 :             return (n < 18);
     812             : 
     813           0 :           case PYRAMID18:
     814           0 :             return (n < 14);
     815             : 
     816       29406 :           case TRI7:
     817       29406 :             return (n < 6);
     818             : 
     819      782361 :           case TET14:
     820      782361 :             return (n < 10);
     821             : 
     822           0 :           case INVALID_ELEM:
     823           0 :             return 0;
     824             : 
     825           0 :           default:
     826           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     827             :           }
     828             :       }
     829             : 
     830     7844764 :     case THIRD:
     831             :       {
     832     7293470 :         switch (t)
     833             :           {
     834      551056 :           case NODEELEM:
     835             :           case EDGE4:
     836             :           case PRISM20:
     837             :           case PRISM21:
     838             :           case PYRAMID18:
     839             :           case TRI7:
     840             :           case TET14:
     841      551056 :             return 1;
     842             : 
     843           0 :           case INVALID_ELEM:
     844           0 :             return 0;
     845             : 
     846           0 :           default:
     847           0 :             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
     848             :           }
     849             :       }
     850             : 
     851           0 :     default:
     852           0 :       libmesh_error_msg("Unsupported order: " << o );
     853             :     }
     854             : }
     855             : 
     856             : 
     857             : 
     858    87646174 : unsigned int lagrange_n_dofs_at_node(const Elem & e,
     859             :                                      const Order o,
     860             :                                      const unsigned int n)
     861             : {
     862    94307864 :   return lagrange_n_dofs_at_node(e.type(), o, n);
     863             : }
     864             : 
     865             : 
     866             : #ifdef LIBMESH_ENABLE_AMR
     867     4343507 : void lagrange_compute_constraints (DofConstraints & constraints,
     868             :                                    DofMap & dof_map,
     869             :                                    const unsigned int variable_number,
     870             :                                    const Elem * elem,
     871             :                                    const unsigned Dim)
     872             : {
     873             :   // Only constrain elements in 2,3D.
     874     4343507 :   if (Dim == 1)
     875      380840 :     return;
     876             : 
     877      414697 :   libmesh_assert(elem);
     878             : 
     879             :   // Only constrain active and ancestor elements
     880     4343507 :   if (elem->subactive())
     881       36396 :     return;
     882             : 
     883             : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
     884     1051705 :    if (elem->infinite())
     885             :    {
     886        3212 :       const FEType fe_t = dof_map.variable_type(variable_number);
     887             : 
     888             :       // expand the infinite_compute_constraint in its template-arguments.
     889        3212 :       switch(Dim)
     890             :       {
     891           0 :          case 2:
     892             :             {
     893           0 :             inf_fe_family_mapping_switch(2, inf_compute_constraints (constraints, dof_map, variable_number, elem) , ,; break;);
     894           0 :             break;
     895             :           }
     896        3212 :          case 3:
     897             :             {
     898        3212 :             inf_fe_family_mapping_switch(3, inf_compute_constraints (constraints, dof_map, variable_number, elem) , ,; break;);
     899        1056 :             break;
     900             :             }
     901           0 :          default:
     902           0 :            libmesh_error_msg("Invalid dim = " << Dim);
     903             :       }
     904        1056 :       return;
     905             :    }
     906             : #endif
     907             : 
     908     3962667 :   const Variable & var = dof_map.variable(variable_number);
     909     3962667 :   const FEType fe_type = var.type();
     910     3962667 :   const bool add_p_level = dof_map.should_p_refine_var(variable_number);
     911             : 
     912             :   // Pull objects out of the loop to reduce heap operations
     913      754490 :   std::vector<dof_id_type> my_dof_indices, parent_dof_indices;
     914     4256670 :   std::unique_ptr<const Elem> my_side, parent_side;
     915             : 
     916             :   // Look at the element faces.  Check to see if we need to
     917             :   // build constraints.
     918    20446443 :   for (auto s : elem->side_index_range())
     919    18045061 :     if (const Elem * const neigh = elem->neighbor_ptr(s);
     920    15478633 :         neigh && neigh != remote_elem)
     921             :       {
     922             :         // constrain dofs shared between this element and ones coarser
     923    15509827 :         if (neigh->level() < elem->level() &&
     924      318852 :             var.active_on_subdomain(neigh->subdomain_id()))
     925             :           {
     926             :             // than this element.
     927             :             // Get pointers to the elements of interest and its parent.
     928       72316 :             const Elem * parent = elem->parent();
     929             : 
     930             :             // This can't happen...  Only level-0 elements have nullptr
     931             :             // parents, and no level-0 elements can be at a higher
     932             :             // level than their neighbors!
     933       36158 :             libmesh_assert(parent);
     934             : 
     935      318510 :             elem->build_side_ptr(my_side, s);
     936      318510 :             parent->build_side_ptr(parent_side, s);
     937             : 
     938             :             // We have some elements with interior bubble function bases
     939             :             // and lower-order sides.  We need to only ask for the lower
     940             :             // order in those cases.
     941      318510 :             FEType side_fe_type = fe_type;
     942       36158 :             int extra_order = 0;
     943      318510 :             if (my_side->default_order() < fe_type.order)
     944             :               {
     945        1104 :                 side_fe_type.order = my_side->default_order();
     946        1196 :                 extra_order = (int)(side_fe_type.order) -
     947          92 :                               (int)(fe_type.order);
     948             :               }
     949             : 
     950             :             // This function gets called element-by-element, so there
     951             :             // will be a lot of memory allocation going on.  We can
     952             :             // at least minimize this for the case of the dof indices
     953             :             // by efficiently preallocating the requisite storage.
     954      318510 :             my_dof_indices.reserve (my_side->n_nodes());
     955      318510 :             parent_dof_indices.reserve (parent_side->n_nodes());
     956             : 
     957      318510 :             dof_map.dof_indices (my_side.get(), my_dof_indices,
     958       72316 :                                  variable_number, extra_order);
     959      318510 :             dof_map.dof_indices (parent_side.get(), parent_dof_indices,
     960       72316 :                                  variable_number, extra_order);
     961             : 
     962             :             const unsigned int n_side_dofs =
     963      318510 :               FEInterface::n_dofs(side_fe_type, my_side.get());
     964             :             const unsigned int n_parent_side_dofs =
     965      318510 :               FEInterface::n_dofs(side_fe_type, parent_side.get());
     966     1167050 :             for (unsigned int my_dof=0; my_dof != n_side_dofs; my_dof++)
     967             :               {
     968       93762 :                 libmesh_assert_less (my_dof, my_side->n_nodes());
     969             : 
     970             :                 // My global dof index.
     971      942302 :                 const dof_id_type my_dof_g = my_dof_indices[my_dof];
     972             : 
     973             :                 // Hunt for "constraining against myself" cases before
     974             :                 // we bother creating a constraint row
     975       93762 :                 bool self_constraint = false;
     976     2743303 :                 for (unsigned int their_dof=0;
     977     2837065 :                      their_dof != n_parent_side_dofs; their_dof++)
     978             :                   {
     979      255853 :                     libmesh_assert_less (their_dof, parent_side->n_nodes());
     980             : 
     981             :                     // Their global dof index.
     982             :                     const dof_id_type their_dof_g =
     983     2344019 :                       parent_dof_indices[their_dof];
     984             : 
     985     2344019 :                     if (their_dof_g == my_dof_g)
     986             :                       {
     987       40858 :                         self_constraint = true;
     988       40858 :                         break;
     989             :                       }
     990             :                   }
     991             : 
     992      848540 :                 if (self_constraint)
     993      635005 :                   continue;
     994             : 
     995             :                 DofConstraintRow * constraint_row;
     996             : 
     997             :                 // we may be running constraint methods concurrently
     998             :                 // on multiple threads, so we need a lock to
     999             :                 // ensure that this constraint is "ours"
    1000             :                 {
    1001       52904 :                   Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
    1002             : 
    1003      493046 :                   if (dof_map.is_constrained_dof(my_dof_g))
    1004       29643 :                     continue;
    1005             : 
    1006      213535 :                   constraint_row = &(constraints[my_dof_g]);
    1007       23261 :                   libmesh_assert(constraint_row->empty());
    1008             :                 }
    1009             : 
    1010             :                 // The support point of the DOF
    1011       46522 :                 const Point & support_point = my_side->point(my_dof);
    1012             : 
    1013             :                 // Figure out where my node lies on their reference element.
    1014      167013 :                 const Point mapped_point = FEMap::inverse_map(Dim-1,
    1015             :                                                               parent_side.get(),
    1016       46522 :                                                               support_point);
    1017             : 
    1018             :                 // Compute the parent's side shape function values.
    1019      702354 :                 for (unsigned int their_dof=0;
    1020      892628 :                      their_dof != n_parent_side_dofs; their_dof++)
    1021             :                   {
    1022       73275 :                     libmesh_assert_less (their_dof, parent_side->n_nodes());
    1023             : 
    1024             :                     // Their global dof index.
    1025             :                     const dof_id_type their_dof_g =
    1026      752368 :                       parent_dof_indices[their_dof];
    1027             : 
    1028      679093 :                     const Real their_dof_value = FEInterface::shape(side_fe_type,
    1029             :                                                                     parent_side.get(),
    1030             :                                                                     their_dof,
    1031      679093 :                                                                     mapped_point);
    1032             : 
    1033             :                     // Only add non-zero and non-identity values
    1034             :                     // for Lagrange basis functions.
    1035      737191 :                     if ((std::abs(their_dof_value) > 1.e-5) &&
    1036       58098 :                         (std::abs(their_dof_value) < .999))
    1037             :                       {
    1038       58098 :                         constraint_row->emplace(their_dof_g, their_dof_value);
    1039             :                       }
    1040             :   #ifdef DEBUG
    1041             :                     // Protect for the case u_i = 0.999 u_j,
    1042             :                     // in which case i better equal j.
    1043       15177 :                     else if (their_dof_value >= .999)
    1044           0 :                       libmesh_assert_equal_to (my_dof_g, their_dof_g);
    1045             :   #endif
    1046             :                   }
    1047             :               }
    1048             :           }
    1049             : 
    1050    13601486 :         if (elem->active() && add_p_level)
    1051             :           {
    1052             :             // p refinement constraints:
    1053             :             // constrain dofs shared between
    1054             :             // active elements and neighbors with
    1055             :             // lower polynomial degrees
    1056             :             const unsigned int min_p_level =
    1057    14640664 :               neigh->min_p_level_by_neighbor(elem, elem->p_level());
    1058    14640664 :             if (min_p_level < elem->p_level())
    1059           0 :               libmesh_error_msg(
    1060             :                 "Mismatched p-refinement levels for LAGRANGE is not currently supported");
    1061             :           }
    1062             :       }
    1063     2914174 : } // lagrange_compute_constraints()
    1064             : #endif // #ifdef LIBMESH_ENABLE_AMR
    1065             : 
    1066             : } // anonymous namespace
    1067             : 
    1068             : 
    1069             : // Instantiate (side_) nodal_soln() function for every dimension
    1070     8483027 : LIBMESH_FE_NODAL_SOLN(LAGRANGE, lagrange_nodal_soln)
    1071        1584 : LIBMESH_FE_SIDE_NODAL_SOLN(LAGRANGE)
    1072             : 
    1073             : 
    1074             : // Do full-specialization for every dimension, instead
    1075             : // of explicit instantiation at the end of this function.
    1076             : // This could be macro-ified.
    1077           0 : template <> unsigned int FE<0,LAGRANGE>::n_dofs(const ElemType t, const Order o) { return lagrange_n_dofs(t, nullptr, o); }
    1078           0 : template <> unsigned int FE<1,LAGRANGE>::n_dofs(const ElemType t, const Order o) { return lagrange_n_dofs(t, nullptr, o); }
    1079        1590 : template <> unsigned int FE<2,LAGRANGE>::n_dofs(const ElemType t, const Order o) { return lagrange_n_dofs(t, nullptr, o); }
    1080           0 : template <> unsigned int FE<3,LAGRANGE>::n_dofs(const ElemType t, const Order o) { return lagrange_n_dofs(t, nullptr, o); }
    1081             : 
    1082      150384 : template <> unsigned int FE<0,LAGRANGE>::n_dofs(const Elem * e, const Order o) { return lagrange_n_dofs(e->type(), e, o); }
    1083   113029705 : template <> unsigned int FE<1,LAGRANGE>::n_dofs(const Elem * e, const Order o) { return lagrange_n_dofs(e->type(), e, o); }
    1084   630760768 : template <> unsigned int FE<2,LAGRANGE>::n_dofs(const Elem * e, const Order o) { return lagrange_n_dofs(e->type(), e, o); }
    1085   494669138 : template <> unsigned int FE<3,LAGRANGE>::n_dofs(const Elem * e, const Order o) { return lagrange_n_dofs(e->type(), e, o); }
    1086             : 
    1087             : 
    1088             : // Do full-specialization for every dimension, instead
    1089             : // of explicit instantiation at the end of this function.
    1090       21208 : template <> unsigned int FE<0,LAGRANGE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(t, o, n); }
    1091    27016723 : template <> unsigned int FE<1,LAGRANGE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(t, o, n); }
    1092   775037175 : template <> unsigned int FE<2,LAGRANGE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(t, o, n); }
    1093   246245496 : template <> unsigned int FE<3,LAGRANGE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(t, o, n); }
    1094             : 
    1095       23152 : template <> unsigned int FE<0,LAGRANGE>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(e, o, n); }
    1096       98853 : template <> unsigned int FE<1,LAGRANGE>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(e, o, n); }
    1097    66730735 : template <> unsigned int FE<2,LAGRANGE>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(e, o, n); }
    1098    27455124 : template <> unsigned int FE<3,LAGRANGE>::n_dofs_at_node(const Elem & e, const Order o, const unsigned int n) { return lagrange_n_dofs_at_node(e, o, n); }
    1099             : 
    1100             : 
    1101             : // Lagrange elements have no dofs per element
    1102             : // (just at the nodes)
    1103           0 : template <> unsigned int FE<0,LAGRANGE>::n_dofs_per_elem(const ElemType, const Order) { return 0; }
    1104           0 : template <> unsigned int FE<1,LAGRANGE>::n_dofs_per_elem(const ElemType, const Order) { return 0; }
    1105           0 : template <> unsigned int FE<2,LAGRANGE>::n_dofs_per_elem(const ElemType, const Order) { return 0; }
    1106           0 : template <> unsigned int FE<3,LAGRANGE>::n_dofs_per_elem(const ElemType, const Order) { return 0; }
    1107             : 
    1108       32784 : template <> unsigned int FE<0,LAGRANGE>::n_dofs_per_elem(const Elem &, const Order) { return 0; }
    1109     9172944 : template <> unsigned int FE<1,LAGRANGE>::n_dofs_per_elem(const Elem &, const Order) { return 0; }
    1110   166466859 : template <> unsigned int FE<2,LAGRANGE>::n_dofs_per_elem(const Elem &, const Order) { return 0; }
    1111    36284706 : template <> unsigned int FE<3,LAGRANGE>::n_dofs_per_elem(const Elem &, const Order) { return 0; }
    1112             : 
    1113             : // Lagrange FEMs are always C^0 continuous
    1114           0 : template <> FEContinuity FE<0,LAGRANGE>::get_continuity() const { return C_ZERO; }
    1115       14895 : template <> FEContinuity FE<1,LAGRANGE>::get_continuity() const { return C_ZERO; }
    1116      333351 : template <> FEContinuity FE<2,LAGRANGE>::get_continuity() const { return C_ZERO; }
    1117      133253 : template <> FEContinuity FE<3,LAGRANGE>::get_continuity() const { return C_ZERO; }
    1118             : 
    1119             : // Lagrange FEMs are not hierarchic
    1120           0 : template <> bool FE<0,LAGRANGE>::is_hierarchic() const { return false; }
    1121          24 : template <> bool FE<1,LAGRANGE>::is_hierarchic() const { return false; }
    1122         180 : template <> bool FE<2,LAGRANGE>::is_hierarchic() const { return false; }
    1123         656 : template <> bool FE<3,LAGRANGE>::is_hierarchic() const { return false; }
    1124             : 
    1125             : // Lagrange FEM shapes do not need reinit (is this always true?)
    1126        3084 : template <> bool FE<0,LAGRANGE>::shapes_need_reinit() const { return false; }
    1127       30254 : template <> bool FE<1,LAGRANGE>::shapes_need_reinit() const { return false; }
    1128   137062338 : template <> bool FE<2,LAGRANGE>::shapes_need_reinit() const { return false; }
    1129     5867132 : template <> bool FE<3,LAGRANGE>::shapes_need_reinit() const { return false; }
    1130             : 
    1131             : // Methods for computing Lagrange constraints.  Note: we pass the
    1132             : // dimension as the last argument to the anonymous helper function.
    1133             : // Also note: we only need instantiations of this function for
    1134             : // Dim==2 and 3.
    1135             : #ifdef LIBMESH_ENABLE_AMR
    1136             : template <>
    1137     3159585 : void FE<2,LAGRANGE>::compute_constraints (DofConstraints & constraints,
    1138             :                                           DofMap & dof_map,
    1139             :                                           const unsigned int variable_number,
    1140             :                                           const Elem * elem)
    1141     3159585 : { lagrange_compute_constraints(constraints, dof_map, variable_number, elem, /*Dim=*/2); }
    1142             : 
    1143             : template <>
    1144     1183922 : void FE<3,LAGRANGE>::compute_constraints (DofConstraints & constraints,
    1145             :                                           DofMap & dof_map,
    1146             :                                           const unsigned int variable_number,
    1147             :                                           const Elem * elem)
    1148     1183922 : { lagrange_compute_constraints(constraints, dof_map, variable_number, elem, /*Dim=*/3); }
    1149             : #endif // LIBMESH_ENABLE_AMR
    1150             : 
    1151             : } // namespace libMesh

Generated by: LCOV version 1.14