$extrastylesheet
fe_bernstein_shape_1D.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 // Local includes
00021 #include "libmesh/libmesh_config.h"
00022 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
00023 
00024 #include <cstdlib> // *must* precede <cmath> for proper std:abs() on PGI, Sun Studio CC
00025 #include <cmath>
00026 
00027 #include "libmesh/libmesh_common.h"
00028 #include "libmesh/fe.h"
00029 #include "libmesh/elem.h"
00030 #include "libmesh/utility.h"
00031 
00032 
00033 namespace libMesh
00034 {
00035 
00036 
00037 template <>
00038 Real FE<1,BERNSTEIN>::shape(const ElemType,
00039                             const Order order,
00040                             const unsigned int i,
00041                             const Point& p)
00042 {
00043   const Real xi = p(0);
00044   using Utility::pow;
00045 
00046   switch (order)
00047     {
00048     case FIRST:
00049 
00050       switch(i)
00051         {
00052         case 0:
00053           return (1.-xi)/2.;
00054         case 1:
00055           return (1.+xi)/2.;
00056         default:
00057           libmesh_error_msg("Invalid shape function index i = " << i);
00058         }
00059 
00060     case SECOND:
00061 
00062       switch(i)
00063         {
00064         case 0:
00065           return (1./4.)*pow<2>(1.-xi);
00066         case 1:
00067           return (1./4.)*pow<2>(1.+xi);
00068         case 2:
00069           return (1./2.)*(1.-xi)*(1.+xi);
00070         default:
00071           libmesh_error_msg("Invalid shape function index i = " << i);
00072         }
00073 
00074     case THIRD:
00075 
00076       switch(i)
00077         {
00078         case 0:
00079           return (1./8.)*pow<3>(1.-xi);
00080         case 1:
00081           return (1./8.)*pow<3>(1.+xi);
00082         case 2:
00083           return (3./8.)*(1.+xi)*pow<2>(1.-xi);
00084         case 3:
00085           return (3./8.)*pow<2>(1.+xi)*(1.-xi);
00086         default:
00087           libmesh_error_msg("Invalid shape function index i = " << i);
00088         }
00089 
00090     case FOURTH:
00091 
00092       switch(i)
00093         {
00094         case 0:
00095           return (1./16.)*pow<4>(1.-xi);
00096         case 1:
00097           return (1./16.)*pow<4>(1.+xi);
00098         case 2:
00099           return (1./ 4.)*(1.+xi)*pow<3>(1.-xi);
00100         case 3:
00101           return (3./ 8.)*pow<2>(1.+xi)*pow<2>(1.-xi);
00102         case 4:
00103           return (1./ 4.)*pow<3>(1.+xi)*(1.-xi);
00104         default:
00105           libmesh_error_msg("Invalid shape function index i = " << i);
00106         }
00107 
00108 
00109     case FIFTH:
00110 
00111       switch(i)
00112         {
00113         case 0:
00114           return (1./32.)*pow<5>(1.-xi);
00115         case 1:
00116           return (1./32.)*pow<5>(1.+xi);
00117         case 2:
00118           return (5./32.)*(1.+xi)*pow<4>(1.-xi);
00119         case 3:
00120           return (5./16.)*pow<2>(1.+xi)*pow<3>(1.-xi);
00121         case 4:
00122           return (5./16.)*pow<3>(1.+xi)*pow<2>(1.-xi);
00123         case 5:
00124           return (5./32.)*pow<4>(1.+xi)*(1.-xi);
00125         default:
00126           libmesh_error_msg("Invalid shape function index i = " << i);
00127         }
00128 
00129 
00130     case SIXTH:
00131 
00132       switch (i)
00133         {
00134         case 0:
00135           return ( 1./64.)*pow<6>(1.-xi);
00136         case 1:
00137           return ( 1./64.)*pow<6>(1.+xi);
00138         case 2:
00139           return ( 3./32.)*(1.+xi)*pow<5>(1.-xi);
00140         case 3:
00141           return (15./64.)*pow<2>(1.+xi)*pow<4>(1.-xi);
00142         case 4:
00143           return ( 5./16.)*pow<3>(1.+xi)*pow<3>(1.-xi);
00144         case 5:
00145           return (15./64.)*pow<4>(1.+xi)*pow<2>(1.-xi);
00146         case 6:
00147           return ( 3./32.)*pow<5>(1.+xi)*(1.-xi);
00148         default:
00149           libmesh_error_msg("Invalid shape function index i = " << i);
00150         }
00151 
00152     default:
00153       {
00154         libmesh_assert (order>6);
00155 
00156         // Use this for arbitrary orders.
00157         // Note that this implementation is less efficient.
00158         const int p_order = static_cast<unsigned int>(order);
00159         const int m       = p_order-i+1;
00160         const int n       = (i-1);
00161 
00162         unsigned int binomial_p_i = 1;
00163 
00164         // the binomial coefficient (p choose n)
00165         if (i>1)
00166           binomial_p_i = Utility::factorial(p_order)
00167             / (Utility::factorial(n)*Utility::factorial(p_order-n));
00168 
00169 
00170         switch(i)
00171           {
00172           case 0:
00173             return binomial_p_i * std::pow((1-xi)/2,static_cast<int>(p_order));
00174           case 1:
00175             return binomial_p_i * std::pow((1+xi)/2,static_cast<int>(p_order));
00176           default:
00177             {
00178               return binomial_p_i * std::pow((1+xi)/2,n)
00179                 * std::pow((1-xi)/2,m);
00180             }
00181           }
00182       }
00183     }
00184 
00185   libmesh_error_msg("We'll never get here!");
00186   return 0.;
00187 }
00188 
00189 
00190 
00191 template <>
00192 Real FE<1,BERNSTEIN>::shape(const Elem* elem,
00193                             const Order order,
00194                             const unsigned int i,
00195                             const Point& p)
00196 {
00197   libmesh_assert(elem);
00198 
00199   return FE<1,BERNSTEIN>::shape(elem->type(), static_cast<Order>(order + elem->p_level()), i, p);
00200 }
00201 
00202 
00203 
00204 template <>
00205 Real FE<1,BERNSTEIN>::shape_deriv(const ElemType,
00206                                   const Order order,
00207                                   const unsigned int i,
00208                                   const unsigned int libmesh_dbg_var(j),
00209                                   const Point& p)
00210 {
00211   // only d()/dxi in 1D!
00212 
00213   libmesh_assert_equal_to (j, 0);
00214 
00215   const Real xi = p(0);
00216 
00217   using Utility::pow;
00218 
00219   switch (order)
00220     {
00221     case FIRST:
00222 
00223       switch(i)
00224         {
00225         case 0:
00226           return -.5;
00227         case 1:
00228           return .5;
00229         default:
00230           libmesh_error_msg("Invalid shape function index i = " << i);
00231         }
00232 
00233     case SECOND:
00234 
00235       switch(i)
00236         {
00237         case 0:
00238           return (xi-1.)*.5;
00239         case 1:
00240           return (xi+1.)*.5;
00241         case 2:
00242           return -xi;
00243         default:
00244           libmesh_error_msg("Invalid shape function index i = " << i);
00245         }
00246 
00247     case THIRD:
00248 
00249       switch(i)
00250         {
00251         case 0:
00252           return -0.375*pow<2>(1.-xi);
00253         case 1:
00254           return  0.375*pow<2>(1.+xi);
00255         case 2:
00256           return -0.375 -.75*xi +1.125*pow<2>(xi);
00257         case 3:
00258           return  0.375 -.75*xi -1.125*pow<2>(xi);
00259         default:
00260           libmesh_error_msg("Invalid shape function index i = " << i);
00261         }
00262 
00263     case FOURTH:
00264 
00265       switch(i)
00266         {
00267         case 0:
00268           return -0.25*pow<3>(1.-xi);
00269         case 1:
00270           return  0.25*pow<3>(1.+xi);
00271         case 2:
00272           return -0.5 +1.5*pow<2>(xi)-pow<3>(xi);
00273         case 3:
00274           return  1.5*(pow<3>(xi)-xi);
00275         case 4:
00276           return  0.5 -1.5*pow<2>(xi)-pow<3>(xi);
00277         default:
00278           libmesh_error_msg("Invalid shape function index i = " << i);
00279         }
00280 
00281     case FIFTH:
00282 
00283       switch(i)
00284         {
00285         case 0:
00286           return -(5./32.)*pow<4>(xi-1.);
00287         case 1:
00288           return  (5./32.)*pow<4>(xi+1.);
00289         case 2:
00290           return  (5./32.)*pow<4>(1.-xi)         -(5./8.)*(1.+xi)*pow<3>(1.-xi);
00291         case 3:
00292           return  (5./ 8.)*(1.+xi)*pow<3>(1.-xi) -(15./16.)*pow<2>(1.+xi)*pow<2>(1.-xi);
00293         case 4:
00294           return -(5./ 8.)*pow<3>(1.+xi)*(1.-xi) +(15./16.)*pow<2>(1.+xi)*pow<2>(1.-xi);
00295         case 5:
00296           return  (5./ 8.)*pow<3>(1.+xi)*(1.-xi) -(5./32.)*pow<4>(1.+xi);
00297         default:
00298           libmesh_error_msg("Invalid shape function index i = " << i);
00299         }
00300 
00301     case SIXTH:
00302 
00303       switch(i)
00304         {
00305         case 0:
00306           return -( 3./32.)*pow<5>(1.-xi);
00307         case 1:
00308           return  ( 3./32.)*pow<5>(1.+xi);
00309         case 2:
00310           return  ( 3./32.)*pow<5>(1.-xi)-(15./32.)*(1.+xi)*pow<4>(1.-xi);
00311         case 3:
00312           return  (15./32.)*(1.+xi)*pow<4>(1.-xi)-(15./16.)*pow<2>(1.+xi)*pow<3>(1.-xi);
00313         case 4:
00314           return -(15./ 8.)*xi +(15./4.)*pow<3>(xi)-(15./8.)*pow<5>(xi);
00315         case 5:
00316           return -(15./32.)*(1.-xi)*pow<4>(1.+xi)+(15./16.)*pow<2>(1.-xi)*pow<3>(1.+xi);
00317         case 6:
00318           return  (15./32.)*pow<4>(1.+xi)*(1.-xi)-(3./32.)*pow<5>(1.+xi);
00319         default:
00320           libmesh_error_msg("Invalid shape function index i = " << i);
00321         }
00322 
00323 
00324     default:
00325       {
00326         libmesh_assert (order>6);
00327 
00328         // Use this for arbitrary orders
00329         const int p_order = static_cast<unsigned int>(order);
00330         const int m       = p_order-(i-1);
00331         const int n       = (i-1);
00332 
00333         unsigned int binomial_p_i = 1;
00334 
00335         // the binomial coefficient (p choose n)
00336         if (i>1)
00337           binomial_p_i = Utility::factorial(p_order)
00338             / (Utility::factorial(n)*Utility::factorial(p_order-n));
00339 
00340 
00341 
00342         switch(i)
00343           {
00344           case 0:
00345             return binomial_p_i * (-1./2.) * p_order * std::pow((1-xi)/2,static_cast<int>(p_order-1));
00346           case 1:
00347             return binomial_p_i * ( 1./2.) * p_order * std::pow((1+xi)/2,static_cast<int>(p_order-1));
00348 
00349           default:
00350             {
00351               return binomial_p_i * (1./2. * n * std::pow((1+xi)/2,n-1) * std::pow((1-xi)/2,m)
00352                                      - 1./2. * m * std::pow((1+xi)/2,n)   * std::pow((1-xi)/2,m-1));
00353             }
00354           }
00355       }
00356 
00357     }
00358 
00359   libmesh_error_msg("We'll never get here!");
00360   return 0.;
00361 }
00362 
00363 
00364 
00365 template <>
00366 Real FE<1,BERNSTEIN>::shape_deriv(const Elem* elem,
00367                                   const Order order,
00368                                   const unsigned int i,
00369                                   const unsigned int j,
00370                                   const Point& p)
00371 {
00372   libmesh_assert(elem);
00373 
00374   return FE<1,BERNSTEIN>::shape_deriv(elem->type(),
00375                                       static_cast<Order>(order + elem->p_level()), i, j, p);
00376 }
00377 
00378 
00379 
00380 template <>
00381 Real FE<1,BERNSTEIN>::shape_second_deriv(const ElemType,
00382                                          const Order,
00383                                          const unsigned int,
00384                                          const unsigned int,
00385                                          const Point&)
00386 {
00387   static bool warning_given = false;
00388 
00389   if (!warning_given)
00390     libMesh::err << "Second derivatives for Bernstein elements "
00391                  << "are not yet implemented!"
00392                  << std::endl;
00393 
00394   warning_given = true;
00395   return 0.;
00396 }
00397 
00398 
00399 
00400 
00401 template <>
00402 Real FE<1,BERNSTEIN>::shape_second_deriv(const Elem*,
00403                                          const Order,
00404                                          const unsigned int,
00405                                          const unsigned int,
00406                                          const Point&)
00407 {
00408   static bool warning_given = false;
00409 
00410   if (!warning_given)
00411     libMesh::err << "Second derivatives for Bernstein elements "
00412                  << "are not yet implemented!"
00413                  << std::endl;
00414 
00415   warning_given = true;
00416   return 0.;
00417 }
00418 
00419 } // namespace libMesh
00420 
00421 
00422 #endif //LIBMESH_ENABLE_HIGHER_ORDER_SHAPES