$extrastylesheet
fe_szabab_shape_2D.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 // C++ includes
00021 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00022 #include <cmath> // for std::sqrt
00023 
00024 
00025 // Local includes
00026 #include "libmesh/libmesh_config.h"
00027 
00028 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
00029 
00030 #include "libmesh/fe.h"
00031 #include "libmesh/elem.h"
00032 #include "libmesh/utility.h"
00033 
00034 
00035 // Anonymous namespace to hold static std::sqrt values
00036 namespace
00037 {
00038 using libMesh::Real;
00039 
00040 static const Real sqrt2  = std::sqrt(2.);
00041 static const Real sqrt6  = std::sqrt(6.);
00042 static const Real sqrt10 = std::sqrt(10.);
00043 static const Real sqrt14 = std::sqrt(14.);
00044 static const Real sqrt22 = std::sqrt(22.);
00045 static const Real sqrt26 = std::sqrt(26.);
00046 }
00047 
00048 
00049 namespace libMesh
00050 {
00051 
00052 template <>
00053 Real FE<2,SZABAB>::shape(const ElemType,
00054                          const Order,
00055                          const unsigned int,
00056                          const Point&)
00057 {
00058   libmesh_error_msg("Szabo-Babuska polynomials require the element type \nbecause edge orientation is needed.");
00059   return 0.;
00060 }
00061 
00062 
00063 
00064 template <>
00065 Real FE<2,SZABAB>::shape(const Elem* elem,
00066                          const Order order,
00067                          const unsigned int i,
00068                          const Point& p)
00069 {
00070   libmesh_assert(elem);
00071 
00072   const ElemType type = elem->type();
00073 
00074   const Order totalorder = static_cast<Order>(order + elem->p_level());
00075 
00076   // Declare that we are using our own special power function
00077   // from the Utility namespace.  This saves typing later.
00078   using Utility::pow;
00079 
00080   switch (totalorder)
00081     {
00082       // 1st & 2nd-order Szabo-Babuska.
00083     case FIRST:
00084     case SECOND:
00085       {
00086         switch (type)
00087           {
00088 
00089             // Szabo-Babuska shape functions on the triangle.
00090           case TRI6:
00091             {
00092               const Real l1 = 1-p(0)-p(1);
00093               const Real l2 = p(0);
00094               const Real l3 = p(1);
00095 
00096               libmesh_assert_less (i, 6);
00097 
00098               switch (i)
00099                 {
00100                 case 0: return l1;
00101                 case 1: return l2;
00102                 case 2: return l3;
00103 
00104                 case 3: return l1*l2*(-4.*sqrt6);
00105                 case 4: return l2*l3*(-4.*sqrt6);
00106                 case 5: return l3*l1*(-4.*sqrt6);
00107 
00108                 default:
00109                   libmesh_error_msg("Invalid i = " << i);
00110                 }
00111             }
00112 
00113 
00114             // Szabo-Babuska shape functions on the quadrilateral.
00115           case QUAD8:
00116           case QUAD9:
00117             {
00118               // Compute quad shape functions as a tensor-product
00119               const Real xi  = p(0);
00120               const Real eta = p(1);
00121 
00122               libmesh_assert_less (i, 9);
00123 
00124               //                                0  1  2  3  4  5  6  7  8
00125               static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2};
00126               static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2};
00127 
00128               return (FE<1,SZABAB>::shape(EDGE3, totalorder, i0[i], xi)*
00129                       FE<1,SZABAB>::shape(EDGE3, totalorder, i1[i], eta));
00130 
00131             }
00132 
00133           default:
00134             libmesh_error_msg("Invalid element type = " << type);
00135           }
00136       }
00137 
00138 
00139       // 3rd-order Szabo-Babuska.
00140     case THIRD:
00141       {
00142         switch (type)
00143           {
00144 
00145             // Szabo-Babuska shape functions on the triangle.
00146           case TRI6:
00147             {
00148               Real l1 = 1-p(0)-p(1);
00149               Real l2 = p(0);
00150               Real l3 = p(1);
00151 
00152               Real f=1;
00153 
00154               libmesh_assert_less (i, 10);
00155 
00156 
00157               if (i==4 && (elem->point(0) > elem->point(1)))f=-1;
00158               if (i==6 && (elem->point(1) > elem->point(2)))f=-1;
00159               if (i==8 && (elem->point(2) > elem->point(0)))f=-1;
00160 
00161 
00162               switch (i)
00163                 {
00164                   //nodal modes
00165                 case 0: return l1;
00166                 case 1: return l2;
00167                 case 2: return l3;
00168 
00169                   //side modes
00170                 case 3: return   l1*l2*(-4.*sqrt6);
00171                 case 4: return f*l1*l2*(-4.*sqrt10)*(l2-l1);
00172 
00173                 case 5: return   l2*l3*(-4.*sqrt6);
00174                 case 6: return f*l2*l3*(-4.*sqrt10)*(l3-l2);
00175 
00176                 case 7: return   l3*l1*(-4.*sqrt6);
00177                 case 8: return f*l3*l1*(-4.*sqrt10)*(l1-l3);
00178 
00179                   //internal modes
00180                 case 9: return l1*l2*l3;
00181 
00182                 default:
00183                   libmesh_error_msg("Invalid i = " << i);
00184                 }
00185             }
00186 
00187 
00188             // Szabo-Babuska shape functions on the quadrilateral.
00189           case QUAD8:
00190           case QUAD9:
00191             {
00192               // Compute quad shape functions as a tensor-product
00193               const Real xi  = p(0);
00194               const Real eta = p(1);
00195 
00196               libmesh_assert_less (i, 16);
00197 
00198               //                                0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
00199               static const unsigned int i0[] = {0,  1,  1,  0,  2,  3,  1,  1,  2,  3,  0,  0,  2,  3,  2,  3};
00200               static const unsigned int i1[] = {0,  0,  1,  1,  0,  0,  2,  3,  1,  1,  2,  3,  2,  2,  3,  3};
00201 
00202               Real f=1.;
00203 
00204               // take care of edge orientation, this is needed at
00205               // edge shapes with (y=0)-asymmetric 1D shapes, these have
00206               // one 1D shape index being 0 or 1, the other one being odd and >=3
00207 
00208               switch(i)
00209                 {
00210                 case  5: // edge 0 points
00211                   if (elem->point(0) > elem->point(1))f = -1.;
00212                   break;
00213                 case  7: // edge 1 points
00214                   if (elem->point(1) > elem->point(2))f = -1.;
00215                   break;
00216                 case  9: // edge 2 points
00217                   if (elem->point(3) > elem->point(2))f = -1.;
00218                   break;
00219                 case 11: // edge 3 points
00220                   if (elem->point(0) > elem->point(3))f = -1.;
00221                   break;
00222 
00223                 default:
00224                   libmesh_error_msg("Invalid shape function index i = " << i);
00225                 }
00226 
00227               return f*(FE<1,SZABAB>::shape(EDGE3, totalorder, i0[i], xi)*
00228                         FE<1,SZABAB>::shape(EDGE3, totalorder, i1[i], eta));
00229             }
00230 
00231           default:
00232             libmesh_error_msg("Invalid element type = " << type);
00233           }
00234       }
00235 
00236 
00237 
00238 
00239       // 4th-order Szabo-Babuska.
00240     case FOURTH:
00241       {
00242         switch (type)
00243           {
00244             // Szabo-Babuska shape functions on the triangle.
00245           case TRI6:
00246             {
00247               Real l1 = 1-p(0)-p(1);
00248               Real l2 = p(0);
00249               Real l3 = p(1);
00250 
00251               Real f=1;
00252 
00253               libmesh_assert_less (i, 15);
00254 
00255 
00256               if (i== 4 && (elem->point(0) > elem->point(1)))f=-1;
00257               if (i== 7 && (elem->point(1) > elem->point(2)))f=-1;
00258               if (i==10 && (elem->point(2) > elem->point(0)))f=-1;
00259 
00260 
00261               switch (i)
00262                 {
00263                   //nodal modes
00264                 case  0: return l1;
00265                 case  1: return l2;
00266                 case  2: return l3;
00267 
00268                   //side modes
00269                 case  3: return   l1*l2*(-4.*sqrt6);
00270                 case  4: return f*l1*l2*(-4.*sqrt10)*(l2-l1);
00271                 case  5: return   l1*l2*(-sqrt14)*(5.*pow<2>(l2-l1)-1);
00272 
00273                 case  6: return   l2*l3*(-4.*sqrt6);
00274                 case  7: return f*l2*l3*(-4.*sqrt10)*(l3-l2);
00275                 case  8: return   l2*l3*(-sqrt14)*(5.*pow<2>(l3-l2)-1);
00276 
00277                 case  9: return   l3*l1*(-4.*sqrt6);
00278                 case 10: return f*l3*l1*(-4.*sqrt10)*(l1-l3);
00279                 case 11: return   l3*l1*(-sqrt14)*(5.*pow<2>(l1-l3)-1);
00280 
00281                   //internal modes
00282                 case 12: return l1*l2*l3;
00283 
00284                 case 13: return l1*l2*l3*(l2-l1);
00285                 case 14: return l1*l2*l3*(2*l3-1);
00286 
00287                 default:
00288                   libmesh_error_msg("Invalid i = " << i);
00289                 }
00290             }
00291 
00292 
00293             // Szabo-Babuska shape functions on the quadrilateral.
00294           case QUAD8:
00295           case QUAD9:
00296             {
00297               // Compute quad shape functions as a tensor-product
00298               const Real xi  = p(0);
00299               const Real eta = p(1);
00300 
00301               libmesh_assert_less (i, 25);
00302 
00303               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
00304               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 1, 1, 1, 2, 3, 4, 0, 0, 0, 2, 3, 4, 2, 3, 4, 2, 3, 4};
00305               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 2, 3, 4, 1, 1, 1, 2, 3, 4, 2, 2, 2, 3, 3, 3, 4, 4, 4};
00306 
00307               Real f=1.;
00308 
00309               switch(i)
00310                 {
00311                 case  5: // edge 0 points
00312                   if (elem->point(0) > elem->point(1))f = -1.;
00313                   break;
00314                 case  8: // edge 1 points
00315                   if (elem->point(1) > elem->point(2))f = -1.;
00316                   break;
00317                 case 11: // edge 2 points
00318                   if (elem->point(3) > elem->point(2))f = -1.;
00319                   break;
00320                 case 14: // edge 3 points
00321                   if (elem->point(0) > elem->point(3))f = -1.;
00322                   break;
00323 
00324                 default:
00325                   libmesh_error_msg("Invalid shape function index i = " << i);
00326                 }
00327 
00328               return f*(FE<1,SZABAB>::shape(EDGE3, totalorder, i0[i], xi)*
00329                         FE<1,SZABAB>::shape(EDGE3, totalorder, i1[i], eta));
00330             }
00331 
00332           default:
00333             libmesh_error_msg("Invalid element type = " << type);
00334           }
00335       }
00336 
00337 
00338 
00339 
00340       // 5th-order Szabo-Babuska.
00341     case FIFTH:
00342       {
00343         switch (type)
00344           {
00345             // Szabo-Babuska shape functions on the triangle.
00346           case TRI6:
00347             {
00348               Real l1 = 1-p(0)-p(1);
00349               Real l2 = p(0);
00350               Real l3 = p(1);
00351 
00352               const Real x=l2-l1;
00353               const Real y=2.*l3-1;
00354 
00355               Real f=1;
00356 
00357               libmesh_assert_less (i, 21);
00358 
00359 
00360               if ((i== 4||i== 6) && (elem->point(0) > elem->point(1)))f=-1;
00361               if ((i== 8||i==10) && (elem->point(1) > elem->point(2)))f=-1;
00362               if ((i==12||i==14) && (elem->point(2) > elem->point(0)))f=-1;
00363 
00364 
00365               switch (i)
00366                 {
00367                   //nodal modes
00368                 case  0: return l1;
00369                 case  1: return l2;
00370                 case  2: return l3;
00371 
00372                   //side modes
00373                 case  3: return   l1*l2*(-4.*sqrt6);
00374                 case  4: return f*l1*l2*(-4.*sqrt10)*(l2-l1);
00375                 case  5: return   -sqrt14*l1*l2*(5.0*l1*l1-1.0+(-10.0*l1+5.0*l2)*l2);
00376                 case  6: return f*(-sqrt2)*l1*l2*((9.-21.*l1*l1)*l1+(-9.+63.*l1*l1+(-63.*l1+21.*l2)*l2)*l2);
00377 
00378                 case  7: return   l2*l3*(-4.*sqrt6);
00379                 case  8: return f*l2*l3*(-4.*sqrt10)*(l3-l2);
00380                 case  9: return   -sqrt14*l2*l3*(5.0*l3*l3-1.0+(-10.0*l3+5.0*l2)*l2);
00381                 case 10: return -f*sqrt2*l2*l3*((-9.0+21.0*l3*l3)*l3+(-63.0*l3*l3+9.0+(63.0*l3-21.0*l2)*l2)*l2);
00382 
00383                 case 11: return   l3*l1*(-4.*sqrt6);
00384                 case 12: return f*l3*l1*(-4.*sqrt10)*(l1-l3);
00385                 case 13: return -sqrt14*l3*l1*(5.0*l3*l3-1.0+(-10.0*l3+5.0*l1)*l1);
00386                 case 14: return f*(-sqrt2)*l3*l1*((9.0-21.0*l3*l3)*l3+(-9.0+63.0*l3*l3+(-63.0*l3+21.0*l1)*l1)*l1);
00387 
00388                   //internal modes
00389                 case 15: return l1*l2*l3;
00390 
00391                 case 16: return l1*l2*l3*x;
00392                 case 17: return l1*l2*l3*y;
00393 
00394                 case 18: return l1*l2*l3*(1.5*l1*l1-.5+(-3.0*l1+1.5*l2)*l2);
00395                 case 19: return l1*l2*l3*x*y;
00396                 case 20: return l1*l2*l3*(1.0+(-6.0+6.0*l3)*l3);
00397 
00398                 default:
00399                   libmesh_error_msg("Invalid i = " << i);
00400                 }
00401             } // case TRI6
00402 
00403             // Szabo-Babuska shape functions on the quadrilateral.
00404           case QUAD8:
00405           case QUAD9:
00406             {
00407               // Compute quad shape functions as a tensor-product
00408               const Real xi  = p(0);
00409               const Real eta = p(1);
00410 
00411               libmesh_assert_less (i, 36);
00412 
00413               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
00414               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 0, 0, 0, 0, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5};
00415               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
00416 
00417               Real f=1.;
00418 
00419               switch(i)
00420                 {
00421                 case  5: // edge 0 points
00422                 case  7:
00423                   if (elem->point(0) > elem->point(1))f = -1.;
00424                   break;
00425                 case  9: // edge 1 points
00426                 case 11:
00427                   if (elem->point(1) > elem->point(2))f = -1.;
00428                   break;
00429                 case 13: // edge 2 points
00430                 case 15:
00431                   if (elem->point(3) > elem->point(2))f = -1.;
00432                   break;
00433                 case 14: // edge 3 points
00434                 case 19:
00435                   if (elem->point(0) > elem->point(3))f = -1.;
00436                   break;
00437 
00438                 default:
00439                   libmesh_error_msg("Invalid shape function index i = " << i);
00440                 }
00441 
00442               return f*(FE<1,SZABAB>::shape(EDGE3, totalorder, i0[i], xi)*
00443                         FE<1,SZABAB>::shape(EDGE3, totalorder, i1[i], eta));
00444 
00445             } // case QUAD8/QUAD9
00446 
00447           default:
00448             libmesh_error_msg("Invalid element type = " << type);
00449 
00450           } // switch type
00451 
00452       } // case FIFTH
00453 
00454       // 6th-order Szabo-Babuska.
00455     case SIXTH:
00456       {
00457         switch (type)
00458           {
00459             // Szabo-Babuska shape functions on the triangle.
00460           case TRI6:
00461             {
00462               Real l1 = 1-p(0)-p(1);
00463               Real l2 = p(0);
00464               Real l3 = p(1);
00465 
00466               const Real x=l2-l1;
00467               const Real y=2.*l3-1;
00468 
00469               Real f=1;
00470 
00471               libmesh_assert_less (i, 28);
00472 
00473 
00474               if ((i== 4||i== 6) && (elem->point(0) > elem->point(1)))f=-1;
00475               if ((i== 9||i==11) && (elem->point(1) > elem->point(2)))f=-1;
00476               if ((i==14||i==16) && (elem->point(2) > elem->point(0)))f=-1;
00477 
00478 
00479               switch (i)
00480                 {
00481                   //nodal modes
00482                 case  0: return l1;
00483                 case  1: return l2;
00484                 case  2: return l3;
00485 
00486                   //side modes
00487                 case  3: return   l1*l2*(-4.*sqrt6);
00488                 case  4: return f*l1*l2*(-4.*sqrt10)*(l2-l1);
00489                 case  5: return   -sqrt14*l1*l2*(5.0*l1*l1-1.0+(-10.0*l1+5.0*l2)*l2);
00490                 case  6: return f*(-sqrt2)*l1*l2*((9.0-21.0*l1*l1)*l1+(-9.0+63.0*l1*l1+(-63.0*l1+21.0*l2)*l2)*l2);
00491                 case  7: return   -sqrt22*l1*l2*(0.5+(-7.0+0.105E2*l1*l1)*l1*l1+((14.0-0.42E2*l1*l1)*l1+(-7.0+0.63E2*l1*l1+(-0.42E2*l1+0.105E2*l2)*l2)*l2)*l2);
00492 
00493                 case  8: return   l2*l3*(-4.*sqrt6);
00494                 case  9: return f*l2*l3*(-4.*sqrt10)*(l3-l2);
00495                 case 10: return   -sqrt14*l2*l3*(5.0*l3*l3-1.0+(-10.0*l3+5.0*l2)*l2);
00496                 case 11: return f*(-sqrt2)*l2*l3*((-9.0+21.0*l3*l3)*l3+(-63.0*l3*l3+9.0+(63.0*l3-21.0*l2)*l2)*l2);
00497                 case 12: return   -sqrt22*l2*l3*(0.5+(-7.0+0.105E2*l3*l3)*l3*l3+((14.0-0.42E2*l3*l3)*l3+(-7.0+0.63E2*l3*l3+(-0.42E2*l3+0.105E2*l2)*l2)*l2)*l2);
00498 
00499                 case 13: return   l3*l1*(-4.*sqrt6);
00500                 case 14: return f*l3*l1*(-4.*sqrt10)*(l1-l3);
00501                 case 15: return   -sqrt14*l3*l1*(5.0*l3*l3-1.0+(-10.0*l3+5.0*l1)*l1);
00502                 case 16: return f*(-sqrt2)*l3*l1*((9.0-21.0*l3*l3)*l3+(-9.0+63.0*l3*l3+(-63.0*l3+21.0*l1)*l1)*l1);
00503                 case 17: return   -sqrt22*l3*l1*(0.5+(-7.0+0.105E2*l3*l3)*l3*l3+((14.0-0.42E2*l3*l3)*l3+(-7.0+0.63E2*l3*l3+(-0.42E2*l3+0.105E2*l1)*l1)*l1)*l1);
00504 
00505 
00506 
00507                   //internal modes
00508                 case 18: return l1*l2*l3;
00509 
00510                 case 19: return l1*l2*l3*x;
00511                 case 20: return l1*l2*l3*y;
00512 
00513                 case 21: return 0.5*l1*l2*l3*(3.0*l1*l1-1.0+(-6.0*l1+3.0*l2)*l2);
00514                 case 22: return l1*l2*l3*(l2-l1)*(2.0*l3-1.0);
00515                 case 23: return 0.5*l1*l2*l3*(2.0+(-12.0+12.0*l3)*l3);
00516                 case 24: return 0.5*l1*l2*l3*((3.0-5.0*l1*l1)*l1+(-3.0+15.0*l1*l1+(-15.0*l1+5.0*l2)*l2)*l2);
00517                 case 25: return 0.5*l1*l2*l3*(3.0*l1*l1-1.0+(-6.0*l1+3.0*l2)*l2)*(2.0*l3-1.0);
00518                 case 26: return 0.5*l1*l2*l3*(2.0+(-12.0+12.0*l3)*l3)*(l2-l1);
00519                 case 27: return 0.5*l1*l2*l3*(-2.0+(24.0+(-60.0+40.0*l3)*l3)*l3);
00520 
00521 
00522                 default:
00523                   libmesh_error_msg("Invalid i = " << i);
00524                 }
00525             } // case TRI6
00526 
00527             // Szabo-Babuska shape functions on the quadrilateral.
00528           case QUAD8:
00529           case QUAD9:
00530             {
00531               // Compute quad shape functions as a tensor-product
00532               const Real xi  = p(0);
00533               const Real eta = p(1);
00534 
00535               libmesh_assert_less (i, 49);
00536 
00537               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
00538               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6};
00539               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6};
00540 
00541               Real f=1.;
00542 
00543               switch(i)
00544                 {
00545                 case  5: // edge 0 points
00546                 case  7:
00547                   if (elem->point(0) > elem->point(1))f = -1.;
00548                   break;
00549                 case 10: // edge 1 points
00550                 case 12:
00551                   if (elem->point(1) > elem->point(2))f = -1.;
00552                   break;
00553                 case 15: // edge 2 points
00554                 case 17:
00555                   if (elem->point(3) > elem->point(2))f = -1.;
00556                   break;
00557                 case 20: // edge 3 points
00558                 case 22:
00559                   if (elem->point(0) > elem->point(3))f = -1.;
00560                   break;
00561 
00562                 default:
00563                   libmesh_error_msg("Invalid shape function index i = " << i);
00564                 }
00565 
00566               return f*(FE<1,SZABAB>::shape(EDGE3, totalorder, i0[i], xi)*
00567                         FE<1,SZABAB>::shape(EDGE3, totalorder, i1[i], eta));
00568 
00569             } // case QUAD8/QUAD9
00570 
00571           default:
00572             libmesh_error_msg("Invalid element type = " << type);
00573 
00574           } // switch type
00575 
00576       } // case SIXTH
00577 
00578 
00579       // 7th-order Szabo-Babuska.
00580     case SEVENTH:
00581       {
00582         switch (type)
00583           {
00584             // Szabo-Babuska shape functions on the triangle.
00585           case TRI6:
00586             {
00587 
00588               Real l1 = 1-p(0)-p(1);
00589               Real l2 = p(0);
00590               Real l3 = p(1);
00591 
00592               const Real x=l2-l1;
00593               const Real y=2.*l3-1.;
00594 
00595               Real f=1;
00596 
00597               libmesh_assert_less (i, 36);
00598 
00599 
00600               if ((i>= 4&&i<= 8) && (elem->point(0) > elem->point(1)))f=-1;
00601               if ((i>=10&&i<=14) && (elem->point(1) > elem->point(2)))f=-1;
00602               if ((i>=16&&i<=20) && (elem->point(2) > elem->point(0)))f=-1;
00603 
00604 
00605               switch (i)
00606                 {
00607                   //nodal modes
00608                 case  0: return l1;
00609                 case  1: return l2;
00610                 case  2: return l3;
00611 
00612                   //side modes
00613                 case  3: return   l1*l2*(-4.*sqrt6);
00614                 case  4: return f*l1*l2*(-4.*sqrt10)*(l2-l1);
00615 
00616                 case  5: return   -sqrt14*l1*l2*(5.0*l1*l1-1.0+(-10.0*l1+5.0*l2)*l2);
00617                 case  6: return f*-sqrt2*l1*l2*((9.0-21.0*l1*l1)*l1+(-9.0+63.0*l1*l1+(-63.0*l1+21.0*l2)*l2)*l2);
00618                 case  7: return   -sqrt22*l1*l2*(0.5+(-7.0+0.105E2*l1*l1)*l1*l1+((14.0-0.42E2*l1*l1)*l1+(-7.0+0.63E2*l1*l1+(-0.42E2*l1+0.105E2*l2)*l2)*l2)*l2);
00619                 case  8: return f*-sqrt26*l1*l2*((-0.25E1+(15.0-0.165E2*l1*l1)*l1*l1)*l1+(0.25E1+(-45.0+0.825E2*l1*l1)*l1*l1+((45.0-0.165E3*l1*l1)*l1+(-15.0+0.165E3*l1*l1+(-0.825E2*l1+0.165E2*l2)*l2)*l2)*l2)*l2);
00620 
00621                 case  9: return   l2*l3*(-4.*sqrt6);
00622                 case 10: return f*l2*l3*(-4.*sqrt10)*(l3-l2);
00623 
00624                 case 11: return   -sqrt14*l2*l3*(5.0*l3*l3-1.0+(-10.0*l3+5.0*l2)*l2);
00625                 case 12: return f*-sqrt2*l2*l3*((-9.0+21.0*l3*l3)*l3+(-63.0*l3*l3+9.0+(63.0*l3-21.0*l2)*l2)*l2);
00626                 case 13: return   -sqrt22*l2*l3*(0.5+(-7.0+0.105E2*l3*l3)*l3*l3+((14.0-0.42E2*l3*l3)*l3+(-7.0+0.63E2*l3*l3+(-0.42E2*l3+0.105E2*l2)*l2)*l2)*l2);
00627                 case 14: return f*-sqrt26*l2*l3*((0.25E1+(-15.0+0.165E2*l3*l3)*l3*l3)*l3+(-0.25E1+(45.0-0.825E2*l3*l3)*l3*l3+((-45.0+0.165E3*l3*l3)*l3+(15.0-0.165E3*l3*l3+(0.825E2*l3-0.165E2*l2)*l2)*l2)*l2)*l2);
00628 
00629                 case 15: return   l3*l1*(-4.*sqrt6);
00630                 case 16: return f*l3*l1*(-4.*sqrt10)*(l1-l3);
00631 
00632                 case 17: return   -sqrt14*l3*l1*(5.0*l3*l3-1.0+(-10.0*l3+5.0*l1)*l1);
00633                 case 18: return -f*sqrt2*l3*l1*((9.-21.*l3*l3)*l3+(-9.+63.*l3*l3+(-63.*l3+21.*l1)*l1)*l1);
00634                 case 19: return   -sqrt22*l3*l1*(0.5+(-7.0+0.105E2*l3*l3)*l3*l3+((14.0-0.42E2*l3*l3)*l3+(-7.0+0.63E2*l3*l3+(-0.42E2*l3+0.105E2*l1)*l1)*l1)*l1);
00635                 case 20: return f*-sqrt26*l3*l1*((-0.25E1+(15.0-0.165E2*l3*l3)*l3*l3)*l3+(0.25E1+(-45.0+0.825E2*l3*l3)*l3*l3+((45.0-0.165E3*l3*l3)*l3+(-15.0+0.165E3*l3*l3+(-0.825E2*l3+0.165E2*l1)*l1)*l1)*l1)*l1);
00636 
00637 
00638                   //internal modes
00639                 case 21: return l1*l2*l3;
00640 
00641                 case 22: return l1*l2*l3*x;
00642                 case 23: return l1*l2*l3*y;
00643 
00644                 case 24: return l1*l2*l3*0.5*(3.*pow<2>(x)-1.);
00645                 case 25: return l1*l2*l3*x*y;
00646                 case 26: return l1*l2*l3*0.5*(3.*pow<2>(y)-1.);
00647 
00648                 case 27: return 0.5*l1*l2*l3*((3.0-5.0*l1*l1)*l1+(-3.0+15.0*l1*l1+(-15.0*l1+5.0*l2)*l2)*l2);
00649                 case 28: return 0.5*l1*l2*l3*(3.0*l1*l1-1.0+(-6.0*l1+3.0*l2)*l2)*(2.0*l3-1.0);
00650                 case 29: return 0.5*l1*l2*l3*(2.0+(-12.0+12.0*l3)*l3)*(l2-l1);
00651                 case 30: return 0.5*l1*l2*l3*(-2.0+(24.0+(-60.0+40.0*l3)*l3)*l3);
00652                 case 31: return 0.125*l1*l2*l3*((-15.0+(70.0-63.0*l1*l1)*l1*l1)*l1+(15.0+(-210.0+315.0*l1*l1)*l1*l1+((210.0-630.0*l1*l1)*l1+(-70.0+630.0*l1*l1+(-315.0*l1+63.0*l2)*l2)*l2)*l2)*l2);
00653                 case 32: return 0.5*l1*l2*l3*((3.0-5.0*l1*l1)*l1+(-3.0+15.0*l1*l1+(-15.0*l1+5.0*l2)*l2)*l2)*(2.0*l3-1.0);
00654                 case 33: return 0.25*l1*l2*l3*(3.0*l1*l1-1.0+(-6.0*l1+3.0*l2)*l2)*(2.0+(-12.0+12.0*l3)*l3);
00655                 case 34: return 0.5*l1*l2*l3*(-2.0+(24.0+(-60.0+40.0*l3)*l3)*l3)*(l2-l1);
00656                 case 35: return 0.125*l1*l2*l3*(-8.0+(240.0+(-1680.0+(4480.0+(-5040.0+2016.0*l3)*l3)*l3)*l3)*l3);
00657 
00658                 default:
00659                   libmesh_error_msg("Invalid i = " << i);
00660                 }
00661             } // case TRI6
00662 
00663             // Szabo-Babuska shape functions on the quadrilateral.
00664           case QUAD8:
00665           case QUAD9:
00666             {
00667               // Compute quad shape functions as a tensor-product
00668               const Real xi  = p(0);
00669               const Real eta = p(1);
00670 
00671               libmesh_assert_less (i, 64);
00672 
00673               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
00674               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7};
00675               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7};
00676 
00677               Real f=1.;
00678 
00679               switch(i)
00680                 {
00681                 case  5: // edge 0 points
00682                 case  7:
00683                 case  9:
00684                   if (elem->point(0) > elem->point(1))f = -1.;
00685                   break;
00686                 case 11: // edge 1 points
00687                 case 13:
00688                 case 15:
00689                   if (elem->point(1) > elem->point(2))f = -1.;
00690                   break;
00691                 case 17: // edge 2 points
00692                 case 19:
00693                 case 21:
00694                   if (elem->point(3) > elem->point(2))f = -1.;
00695                   break;
00696                 case 23: // edge 3 points
00697                 case 25:
00698                 case 27:
00699                   if (elem->point(0) > elem->point(3))f = -1.;
00700                   break;
00701 
00702                 default:
00703                   libmesh_error_msg("Invalid shape function index i = " << i);
00704                 }
00705 
00706               return f*(FE<1,SZABAB>::shape(EDGE3, totalorder, i0[i], xi)*
00707                         FE<1,SZABAB>::shape(EDGE3, totalorder, i1[i], eta));
00708 
00709             } // case QUAD8/QUAD9
00710 
00711           default:
00712             libmesh_error_msg("Invalid element type = " << type);
00713 
00714           } // switch type
00715 
00716       } // case SEVENTH
00717 
00718 
00719       // by default throw an error
00720     default:
00721       libmesh_error_msg("ERROR: Unsupported polynomial order!");
00722     } // switch order
00723 
00724   libmesh_error_msg("We'll never get here!");
00725   return 0.;
00726 }
00727 
00728 
00729 
00730 
00731 
00732 template <>
00733 Real FE<2,SZABAB>::shape_deriv(const ElemType,
00734                                const Order,
00735                                const unsigned int,
00736                                const unsigned int,
00737                                const Point&)
00738 {
00739   libmesh_error_msg("Szabo-Babuska polynomials require the element type \nbecause edge orientation is needed.");
00740   return 0.;
00741 }
00742 
00743 
00744 
00745 template <>
00746 Real FE<2,SZABAB>::shape_deriv(const Elem* elem,
00747                                const Order order,
00748                                const unsigned int i,
00749                                const unsigned int j,
00750                                const Point& p)
00751 {
00752   libmesh_assert(elem);
00753 
00754   const ElemType type = elem->type();
00755 
00756   const Order totalorder = static_cast<Order>(order + elem->p_level());
00757 
00758   switch (totalorder)
00759     {
00760 
00761       // 1st & 2nd-order Szabo-Babuska.
00762     case FIRST:
00763     case SECOND:
00764       {
00765         switch (type)
00766           {
00767 
00768             // Szabo-Babuska shape functions on the triangle.
00769           case TRI6:
00770             {
00771               // Here we use finite differences to compute the derivatives!
00772               const Real eps = 1.e-6;
00773 
00774               libmesh_assert_less (i, 6);
00775               libmesh_assert_less (j, 2);
00776 
00777               switch (j)
00778                 {
00779                   //  d()/dxi
00780                 case 0:
00781                   {
00782                     const Point pp(p(0)+eps, p(1));
00783                     const Point pm(p(0)-eps, p(1));
00784 
00785                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
00786                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
00787                   }
00788 
00789                   // d()/deta
00790                 case 1:
00791                   {
00792                     const Point pp(p(0), p(1)+eps);
00793                     const Point pm(p(0), p(1)-eps);
00794 
00795                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
00796                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
00797                   }
00798 
00799                 default:
00800                   libmesh_error_msg("Invalid j = " << j);
00801                 }
00802             }
00803 
00804 
00805 
00806             // Szabo-Babuska shape functions on the quadrilateral.
00807           case QUAD8:
00808           case QUAD9:
00809             {
00810               // Compute quad shape functions as a tensor-product
00811               const Real xi  = p(0);
00812               const Real eta = p(1);
00813 
00814               libmesh_assert_less (i, 9);
00815 
00816               //                                0  1  2  3  4  5  6  7  8
00817               static const unsigned int i0[] = {0, 1, 1, 0, 2, 1, 2, 0, 2};
00818               static const unsigned int i1[] = {0, 0, 1, 1, 0, 2, 1, 2, 2};
00819 
00820               switch (j)
00821                 {
00822                   // d()/dxi
00823                 case 0:
00824                   return (FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i0[i], 0, xi)*
00825                           FE<1,SZABAB>::shape      (EDGE3, totalorder, i1[i],    eta));
00826 
00827                   // d()/deta
00828                 case 1:
00829                   return (FE<1,SZABAB>::shape      (EDGE3, totalorder, i0[i],    xi)*
00830                           FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i1[i], 0, eta));
00831 
00832                 default:
00833                   libmesh_error_msg("Invalid j = " << j);
00834                 }
00835             }
00836 
00837           default:
00838             libmesh_error_msg("Invalid element type = " << type);
00839           }
00840       }
00841 
00842 
00843 
00844       // 3rd-order Szabo-Babuska.
00845     case THIRD:
00846       {
00847         switch (type)
00848           {
00849             // Szabo-Babuska shape functions on the triangle.
00850           case TRI6:
00851             {
00852               // Here we use finite differences to compute the derivatives!
00853               const Real eps = 1.e-6;
00854 
00855               libmesh_assert_less (i, 10);
00856               libmesh_assert_less (j, 2);
00857 
00858               switch (j)
00859                 {
00860                   //  d()/dxi
00861                 case 0:
00862                   {
00863                     const Point pp(p(0)+eps, p(1));
00864                     const Point pm(p(0)-eps, p(1));
00865 
00866                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
00867                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
00868                   }
00869 
00870                   // d()/deta
00871                 case 1:
00872                   {
00873                     const Point pp(p(0), p(1)+eps);
00874                     const Point pm(p(0), p(1)-eps);
00875 
00876                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
00877                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
00878                   }
00879 
00880 
00881                 default:
00882                   libmesh_error_msg("Invalid j = " << j);
00883                 }
00884             }
00885 
00886 
00887             // Szabo-Babuska shape functions on the quadrilateral.
00888           case QUAD8:
00889           case QUAD9:
00890             {
00891               // Compute quad shape functions as a tensor-product
00892               const Real xi  = p(0);
00893               const Real eta = p(1);
00894 
00895               libmesh_assert_less (i, 16);
00896 
00897               //                                0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
00898               static const unsigned int i0[] = {0,  1,  1,  0,  2,  3,  1,  1,  2,  3,  0,  0,  2,  3,  2,  3};
00899               static const unsigned int i1[] = {0,  0,  1,  1,  0,  0,  2,  3,  1,  1,  2,  3,  2,  2,  3,  3};
00900 
00901               Real f=1.;
00902 
00903               switch(i)
00904                 {
00905                 case  5: // edge 0 points
00906                   if (elem->point(0) > elem->point(1))f = -1.;
00907                   break;
00908                 case  7: // edge 1 points
00909                   if (elem->point(1) > elem->point(2))f = -1.;
00910                   break;
00911                 case  9: // edge 2 points
00912                   if (elem->point(3) > elem->point(2))f = -1.;
00913                   break;
00914                 case 11: // edge 3 points
00915                   if (elem->point(0) > elem->point(3))f = -1.;
00916                   break;
00917 
00918                 default:
00919                   libmesh_error_msg("Invalid shape function index i = " << i);
00920                 }
00921 
00922 
00923               switch (j)
00924                 {
00925                   // d()/dxi
00926                 case 0:
00927                   return f*(FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i0[i], 0, xi)*
00928                             FE<1,SZABAB>::shape      (EDGE3, totalorder, i1[i],    eta));
00929 
00930                   // d()/deta
00931                 case 1:
00932                   return f*(FE<1,SZABAB>::shape      (EDGE3, totalorder, i0[i],    xi)*
00933                             FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i1[i], 0, eta));
00934 
00935                 default:
00936                   libmesh_error_msg("Invalid j = " << j);
00937                 }
00938             }
00939 
00940           default:
00941             libmesh_error_msg("Invalid element type = " << type);
00942           }
00943       }
00944 
00945 
00946 
00947 
00948       // 4th-order Szabo-Babuska.
00949     case FOURTH:
00950       {
00951         switch (type)
00952           {
00953 
00954             // Szabo-Babuska shape functions on the triangle.
00955           case TRI6:
00956             {
00957               // Here we use finite differences to compute the derivatives!
00958               const Real eps = 1.e-6;
00959 
00960               libmesh_assert_less (i, 15);
00961               libmesh_assert_less (j, 2);
00962 
00963               switch (j)
00964                 {
00965                   //  d()/dxi
00966                 case 0:
00967                   {
00968                     const Point pp(p(0)+eps, p(1));
00969                     const Point pm(p(0)-eps, p(1));
00970 
00971                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
00972                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
00973                   }
00974 
00975                   // d()/deta
00976                 case 1:
00977                   {
00978                     const Point pp(p(0), p(1)+eps);
00979                     const Point pm(p(0), p(1)-eps);
00980 
00981                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
00982                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
00983                   }
00984 
00985 
00986                 default:
00987                   libmesh_error_msg("Invalid j = " << j);
00988                 }
00989             }
00990 
00991 
00992 
00993             // Szabo-Babuska shape functions on the quadrilateral.
00994           case QUAD8:
00995           case QUAD9:
00996             {
00997               // Compute quad shape functions as a tensor-product
00998               const Real xi  = p(0);
00999               const Real eta = p(1);
01000 
01001               libmesh_assert_less (i, 25);
01002 
01003               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
01004               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 1, 1, 1, 2, 3, 4, 0, 0, 0, 2, 3, 4, 2, 3, 4, 2, 3, 4};
01005               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 2, 3, 4, 1, 1, 1, 2, 3, 4, 2, 2, 2, 3, 3, 3, 4, 4, 4};
01006 
01007               Real f=1.;
01008 
01009               switch(i)
01010                 {
01011                 case  5: // edge 0 points
01012                   if (elem->point(0) > elem->point(1))f = -1.;
01013                   break;
01014                 case  8: // edge 1 points
01015                   if (elem->point(1) > elem->point(2))f = -1.;
01016                   break;
01017                 case 11: // edge 2 points
01018                   if (elem->point(3) > elem->point(2))f = -1.;
01019                   break;
01020                 case 14: // edge 3 points
01021                   if (elem->point(0) > elem->point(3))f = -1.;
01022                   break;
01023 
01024                 default:
01025                   libmesh_error_msg("Invalid shape function index i = " << i);
01026                 }
01027 
01028 
01029               switch (j)
01030                 {
01031                   // d()/dxi
01032                 case 0:
01033                   return f*(FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i0[i], 0, xi)*
01034                             FE<1,SZABAB>::shape      (EDGE3, totalorder, i1[i],    eta));
01035 
01036                   // d()/deta
01037                 case 1:
01038                   return f*(FE<1,SZABAB>::shape      (EDGE3, totalorder, i0[i],    xi)*
01039                             FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i1[i], 0, eta));
01040 
01041                 default:
01042                   libmesh_error_msg("Invalid j = " << j);
01043                 }
01044             }
01045 
01046           default:
01047             libmesh_error_msg("Invalid element type = " << type);
01048           }
01049       }
01050 
01051 
01052 
01053 
01054       // 5th-order Szabo-Babuska.
01055     case FIFTH:
01056       {
01057         // Szabo-Babuska shape functions on the quadrilateral.
01058         switch (type)
01059           {
01060 
01061             // Szabo-Babuska shape functions on the triangle.
01062           case TRI6:
01063             {
01064               // Here we use finite differences to compute the derivatives!
01065               const Real eps = 1.e-6;
01066 
01067               libmesh_assert_less (i, 21);
01068               libmesh_assert_less (j, 2);
01069 
01070               switch (j)
01071                 {
01072                   //  d()/dxi
01073                 case 0:
01074                   {
01075                     const Point pp(p(0)+eps, p(1));
01076                     const Point pm(p(0)-eps, p(1));
01077 
01078                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
01079                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
01080                   }
01081 
01082                   // d()/deta
01083                 case 1:
01084                   {
01085                     const Point pp(p(0), p(1)+eps);
01086                     const Point pm(p(0), p(1)-eps);
01087 
01088                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
01089                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
01090                   }
01091 
01092                 default:
01093                   libmesh_error_msg("Invalid j = " << j);
01094                 }
01095             }
01096 
01097 
01098 
01099           case QUAD8:
01100           case QUAD9:
01101             {
01102               // Compute quad shape functions as a tensor-product
01103               const Real xi  = p(0);
01104               const Real eta = p(1);
01105 
01106               libmesh_assert_less (i, 36);
01107 
01108               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
01109               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 0, 0, 0, 0, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5, 2, 3, 4, 5};
01110               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 2, 3, 4, 5, 1, 1, 1, 1, 2, 3, 4, 5, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
01111 
01112               Real f=1.;
01113 
01114               switch(i)
01115                 {
01116                 case  5: // edge 0 points
01117                 case  7:
01118                   if (elem->point(0) > elem->point(1))f = -1.;
01119                   break;
01120                 case  9: // edge 1 points
01121                 case 11:
01122                   if (elem->point(1) > elem->point(2))f = -1.;
01123                   break;
01124                 case 13: // edge 2 points
01125                 case 15:
01126                   if (elem->point(3) > elem->point(2))f = -1.;
01127                   break;
01128                 case 14: // edge 3 points
01129                 case 19:
01130                   if (elem->point(0) > elem->point(3))f = -1.;
01131                   break;
01132 
01133                 default:
01134                   libmesh_error_msg("Invalid shape function index i = " << i);
01135                 }
01136 
01137 
01138               switch (j)
01139                 {
01140                   // d()/dxi
01141                 case 0:
01142                   return f*(FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i0[i], 0, xi)*
01143                             FE<1,SZABAB>::shape      (EDGE3, totalorder, i1[i],    eta));
01144 
01145                   // d()/deta
01146                 case 1:
01147                   return f*(FE<1,SZABAB>::shape      (EDGE3, totalorder, i0[i],    xi)*
01148                             FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i1[i], 0, eta));
01149 
01150                 default:
01151                   libmesh_error_msg("Invalid j = " << j);
01152                 }
01153             }
01154 
01155           default:
01156             libmesh_error_msg("Invalid element type = " << type);
01157           }
01158       }
01159 
01160 
01161       // 6th-order Szabo-Babuska.
01162     case SIXTH:
01163       {
01164         // Szabo-Babuska shape functions on the quadrilateral.
01165         switch (type)
01166           {
01167 
01168             // Szabo-Babuska shape functions on the triangle.
01169           case TRI6:
01170             {
01171               // Here we use finite differences to compute the derivatives!
01172               const Real eps = 1.e-6;
01173 
01174               libmesh_assert_less (i, 28);
01175               libmesh_assert_less (j, 2);
01176 
01177               switch (j)
01178                 {
01179                   //  d()/dxi
01180                 case 0:
01181                   {
01182                     const Point pp(p(0)+eps, p(1));
01183                     const Point pm(p(0)-eps, p(1));
01184 
01185                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
01186                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
01187                   }
01188 
01189                   // d()/deta
01190                 case 1:
01191                   {
01192                     const Point pp(p(0), p(1)+eps);
01193                     const Point pm(p(0), p(1)-eps);
01194 
01195                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
01196                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
01197                   }
01198 
01199                 default:
01200                   libmesh_error_msg("Invalid j = " << j);
01201                 }
01202             }
01203 
01204 
01205 
01206           case QUAD8:
01207           case QUAD9:
01208             {
01209               // Compute quad shape functions as a tensor-product
01210               const Real xi  = p(0);
01211               const Real eta = p(1);
01212 
01213               libmesh_assert_less (i, 49);
01214 
01215               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
01216               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6, 2, 3, 4, 5, 6};
01217               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6};
01218 
01219               Real f=1.;
01220 
01221               switch(i)
01222                 {
01223                 case  5: // edge 0 points
01224                 case  7:
01225                   if (elem->point(0) > elem->point(1))f = -1.;
01226                   break;
01227                 case 10: // edge 1 points
01228                 case 12:
01229                   if (elem->point(1) > elem->point(2))f = -1.;
01230                   break;
01231                 case 15: // edge 2 points
01232                 case 17:
01233                   if (elem->point(3) > elem->point(2))f = -1.;
01234                   break;
01235                 case 20: // edge 3 points
01236                 case 22:
01237                   if (elem->point(0) > elem->point(3))f = -1.;
01238                   break;
01239 
01240                 default:
01241                   libmesh_error_msg("Invalid shape function index i = " << i);
01242                 }
01243 
01244 
01245               switch (j)
01246                 {
01247                   // d()/dxi
01248                 case 0:
01249                   return f*(FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i0[i], 0, xi)*
01250                             FE<1,SZABAB>::shape      (EDGE3, totalorder, i1[i],    eta));
01251 
01252                   // d()/deta
01253                 case 1:
01254                   return f*(FE<1,SZABAB>::shape      (EDGE3, totalorder, i0[i],    xi)*
01255                             FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i1[i], 0, eta));
01256 
01257                 default:
01258                   libmesh_error_msg("Invalid j = " << j);
01259                 }
01260             }
01261 
01262           default:
01263             libmesh_error_msg("Invalid element type = " << type);
01264           }
01265       }
01266 
01267 
01268       // 7th-order Szabo-Babuska.
01269     case SEVENTH:
01270       {
01271         // Szabo-Babuska shape functions on the quadrilateral.
01272         switch (type)
01273           {
01274 
01275             // Szabo-Babuska shape functions on the triangle.
01276           case TRI6:
01277             {
01278               // Here we use finite differences to compute the derivatives!
01279               const Real eps = 1.e-6;
01280 
01281               libmesh_assert_less (i, 36);
01282               libmesh_assert_less (j, 2);
01283 
01284               switch (j)
01285                 {
01286                   //  d()/dxi
01287                 case 0:
01288                   {
01289                     const Point pp(p(0)+eps, p(1));
01290                     const Point pm(p(0)-eps, p(1));
01291 
01292                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
01293                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
01294                   }
01295 
01296                   // d()/deta
01297                 case 1:
01298                   {
01299                     const Point pp(p(0), p(1)+eps);
01300                     const Point pm(p(0), p(1)-eps);
01301 
01302                     return (FE<2,SZABAB>::shape(elem, order, i, pp) -
01303                             FE<2,SZABAB>::shape(elem, order, i, pm))/2./eps;
01304                   }
01305 
01306                 default:
01307                   libmesh_error_msg("Invalid j = " << j);
01308                 }
01309             }
01310 
01311 
01312 
01313           case QUAD8:
01314           case QUAD9:
01315             {
01316               // Compute quad shape functions as a tensor-product
01317               const Real xi  = p(0);
01318               const Real eta = p(1);
01319 
01320               libmesh_assert_less (i, 64);
01321 
01322               //                                0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
01323               static const unsigned int i0[] = {0, 1, 1, 0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7, 2, 3, 4, 5, 6, 7};
01324               static const unsigned int i1[] = {0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 6, 7, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 6, 7, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7};
01325 
01326               Real f=1.;
01327 
01328               switch(i)
01329                 {
01330                 case  5: // edge 0 points
01331                 case  7:
01332                 case  9:
01333                   if (elem->point(0) > elem->point(1))f = -1.;
01334                   break;
01335                 case 11: // edge 1 points
01336                 case 13:
01337                 case 15:
01338                   if (elem->point(1) > elem->point(2))f = -1.;
01339                   break;
01340                 case 17: // edge 2 points
01341                 case 19:
01342                 case 21:
01343                   if (elem->point(3) > elem->point(2))f = -1.;
01344                   break;
01345                 case 23: // edge 3 points
01346                 case 25:
01347                 case 27:
01348                   if (elem->point(0) > elem->point(3))f = -1.;
01349                   break;
01350 
01351                 default:
01352                   libmesh_error_msg("Invalid shape function index i = " << i);
01353                 }
01354 
01355 
01356               switch (j)
01357                 {
01358                   // d()/dxi
01359                 case 0:
01360                   return f*(FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i0[i], 0, xi)*
01361                             FE<1,SZABAB>::shape      (EDGE3, totalorder, i1[i],    eta));
01362 
01363                   // d()/deta
01364                 case 1:
01365                   return f*(FE<1,SZABAB>::shape      (EDGE3, totalorder, i0[i],    xi)*
01366                             FE<1,SZABAB>::shape_deriv(EDGE3, totalorder, i1[i], 0, eta));
01367 
01368                 default:
01369                   libmesh_error_msg("Invalid j = " << j);
01370                 }
01371             }
01372 
01373           default:
01374             libmesh_error_msg("Invalid element type = " << type);
01375           }
01376       }
01377 
01378 
01379 
01380       // by default throw an error;call the orientation-independent shape functions
01381     default:
01382       libmesh_error_msg("ERROR: Unsupported polynomial order!");
01383     }
01384 
01385   libmesh_error_msg("We'll never get here!");
01386   return 0.;
01387 }
01388 
01389 
01390 
01391 template <>
01392 Real FE<2,SZABAB>::shape_second_deriv(const ElemType,
01393                                       const Order,
01394                                       const unsigned int,
01395                                       const unsigned int,
01396                                       const Point&)
01397 {
01398   static bool warning_given = false;
01399 
01400   if (!warning_given)
01401     libMesh::err << "Second derivatives for Szabab elements "
01402                  << " are not yet implemented!"
01403                  << std::endl;
01404 
01405   warning_given = true;
01406   return 0.;
01407 }
01408 
01409 
01410 
01411 template <>
01412 Real FE<2,SZABAB>::shape_second_deriv(const Elem*,
01413                                       const Order,
01414                                       const unsigned int,
01415                                       const unsigned int,
01416                                       const Point&)
01417 {
01418   static bool warning_given = false;
01419 
01420   if (!warning_given)
01421     libMesh::err << "Second derivatives for Szabab elements "
01422                  << " are not yet implemented!"
01423                  << std::endl;
01424 
01425   warning_given = true;
01426   return 0.;
01427 }
01428 
01429 } // namespace libMesh
01430 
01431 
01432 #endif// LIBMESH_ENABLE_HIGHER_ORDER_SHAPES