$extrastylesheet
fe_nedelec_one_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 // C++ inlcludes
00020 
00021 // Local includes
00022 #include "libmesh/fe.h"
00023 #include "libmesh/elem.h"
00024 
00025 namespace libMesh
00026 {
00027 
00028 template <>
00029 RealGradient FE<2,NEDELEC_ONE>::shape(const ElemType,
00030                                       const Order,
00031                                       const unsigned int,
00032                                       const Point&)
00033 {
00034   libmesh_error_msg("Nedelec elements require the element type \nbecause edge orientation is needed.");
00035   return RealGradient();
00036 }
00037 
00038 
00039 // An excellent discussion of Nedelec shape functions is given in
00040 // http://www.dealii.org/developer/reports/nedelec/nedelec.pdf
00041 template <>
00042 RealGradient FE<2,NEDELEC_ONE>::shape(const Elem* elem,
00043                                       const Order order,
00044                                       const unsigned int i,
00045                                       const Point& p)
00046 {
00047 #if LIBMESH_DIM > 1
00048   libmesh_assert(elem);
00049 
00050   const Order total_order = static_cast<Order>(order + elem->p_level());
00051 
00052   switch (total_order)
00053     {
00054     case FIRST:
00055       {
00056         switch (elem->type())
00057           {
00058           case QUAD8:
00059           case QUAD9:
00060             {
00061               libmesh_assert_less (i, 4);
00062 
00063               const Real xi  = p(0);
00064               const Real eta = p(1);
00065 
00066               // Even with a loose inverse_map tolerance we ought to
00067               // be nearly on the element interior in master
00068               // coordinates
00069               libmesh_assert_less_equal ( std::fabs(xi), 1.0+10*TOLERANCE );
00070               libmesh_assert_less_equal ( std::fabs(eta), 1.0+10*TOLERANCE );
00071 
00072               switch(i)
00073                 {
00074                 case 0:
00075                   {
00076                     if( elem->point(0) > elem->point(1) )
00077                       return RealGradient( -0.25*(1.0-eta), 0.0 );
00078                     else
00079                       return RealGradient( 0.25*(1.0-eta), 0.0 );
00080                   }
00081                 case 1:
00082                   {
00083                     if( elem->point(1) > elem->point(2) )
00084                       return RealGradient( 0.0, -0.25*(1.0+xi) );
00085                     else
00086                       return RealGradient( 0.0, 0.25*(1.0+xi) );
00087                   }
00088 
00089                 case 2:
00090                   {
00091                     if( elem->point(2) > elem->point(3) )
00092                       return RealGradient( 0.25*(1.0+eta), 0.0 );
00093                     else
00094                       return RealGradient( -0.25*(1.0+eta), 0.0 );
00095                   }
00096                 case 3:
00097                   {
00098                     if( elem->point(3) > elem->point(0) )
00099                       return RealGradient( 0.0, -0.25*(xi-1.0) );
00100                     else
00101                       return RealGradient( 0.0, 0.25*(xi-1.0) );
00102                   }
00103 
00104                 default:
00105                   libmesh_error_msg("Invalid i = " << i);
00106                 }
00107 
00108               return RealGradient();
00109             }
00110 
00111           case TRI6:
00112             {
00113               const Real xi  = p(0);
00114               const Real eta = p(1);
00115 
00116               libmesh_assert_less (i, 3);
00117 
00118               switch(i)
00119                 {
00120                 case 0:
00121                   {
00122                     if( elem->point(0) > elem->point(1) )
00123                       return RealGradient( -1.0+eta, -xi );
00124                     else
00125                       return RealGradient( 1.0-eta, xi );
00126                   }
00127                 case 1:
00128                   {
00129                     if( elem->point(1) > elem->point(2) )
00130                       return RealGradient( eta, -xi );
00131                     else
00132                       return RealGradient( -eta, xi );
00133                   }
00134 
00135                 case 2:
00136                   {
00137                     if( elem->point(2) > elem->point(0) )
00138                       return RealGradient( eta, -xi+1.0 );
00139                     else
00140                       return RealGradient( -eta, xi-1.0 );
00141                   }
00142 
00143                 default:
00144                   libmesh_error_msg("Invalid i = " << i);
00145                 }
00146             }
00147 
00148           default:
00149             libmesh_error_msg("ERROR: Unsupported 2D element type!: " << elem->type());
00150           }
00151       }
00152 
00153       // unsupported order
00154     default:
00155       libmesh_error_msg("ERROR: Unsupported 2D FE order!: " << total_order);
00156     }
00157 #endif // LIBMESH_DIM > 1
00158 
00159   libmesh_error_msg("We'll never get here!");
00160   return RealGradient();
00161 }
00162 
00163 
00164 
00165 template <>
00166 RealGradient FE<2,NEDELEC_ONE>::shape_deriv(const ElemType,
00167                                             const Order,
00168                                             const unsigned int,
00169                                             const unsigned int,
00170                                             const Point&)
00171 {
00172   libmesh_error_msg("Nedelec elements require the element type \nbecause edge orientation is needed.");
00173   return RealGradient();
00174 }
00175 
00176 
00177 
00178 template <>
00179 RealGradient FE<2,NEDELEC_ONE>::shape_deriv(const Elem* elem,
00180                                             const Order order,
00181                                             const unsigned int i,
00182                                             const unsigned int j,
00183                                             const Point&)
00184 {
00185 #if LIBMESH_DIM > 1
00186   libmesh_assert(elem);
00187   libmesh_assert_less (j, 2);
00188 
00189   const Order total_order = static_cast<Order>(order + elem->p_level());
00190 
00191   switch (total_order)
00192     {
00193       // linear Lagrange shape functions
00194     case FIRST:
00195       {
00196         switch (elem->type())
00197           {
00198           case QUAD8:
00199           case QUAD9:
00200             {
00201               libmesh_assert_less (i, 4);
00202 
00203               switch (j)
00204                 {
00205                   // d()/dxi
00206                 case 0:
00207                   {
00208                     switch(i)
00209                       {
00210                       case 0:
00211                       case 2:
00212                         return RealGradient();
00213                       case 1:
00214                         {
00215                           if( elem->point(1) > elem->point(2) )
00216                             return RealGradient( 0.0, -0.25 );
00217                           else
00218                             return RealGradient( 0.0, 0.25 );
00219                         }
00220                       case 3:
00221                         {
00222                           if( elem->point(3) > elem->point(0) )
00223                             return RealGradient( 0.0, -0.25 );
00224                           else
00225                             return RealGradient( 0.0, 0.25 );
00226                         }
00227                       default:
00228                         libmesh_error_msg("Invalid i = " << i);
00229                       }
00230                   } // j=0
00231 
00232                   // d()/deta
00233                 case 1:
00234                   {
00235                     switch(i)
00236                       {
00237                       case 1:
00238                       case 3:
00239                         return RealGradient();
00240                       case 0:
00241                         {
00242                           if( elem->point(0) > elem->point(1) )
00243                             return RealGradient( 0.25 );
00244                           else
00245                             return RealGradient( -0.25 );
00246                         }
00247                       case 2:
00248                         {
00249                           if( elem->point(2) > elem->point(3) )
00250                             return RealGradient( 0.25 );
00251                           else
00252                             return RealGradient( -0.25 );
00253                         }
00254                       default:
00255                         libmesh_error_msg("Invalid i = " << i);
00256                       }
00257                   } // j=1
00258 
00259                 default:
00260                   libmesh_error_msg("Invalid j = " << j);
00261                 }
00262 
00263               return RealGradient();
00264             }
00265 
00266           case TRI6:
00267             {
00268               libmesh_assert_less (i, 3);
00269 
00270               // Account for edge flipping
00271               Real f = 1.0;
00272 
00273               switch(i)
00274                 {
00275                 case 0:
00276                   {
00277                     if( elem->point(0) > elem->point(1) )
00278                       f = -1.0;
00279                     break;
00280                   }
00281                 case 1:
00282                   {
00283                     if( elem->point(1) > elem->point(2) )
00284                       f = -1.0;
00285                     break;
00286                   }
00287                 case 2:
00288                   {
00289                     if( elem->point(2) > elem->point(0) )
00290                       f = -1.0;
00291                     break;
00292                   }
00293                 default:
00294                   libmesh_error_msg("Invalid i = " << i);
00295                 }
00296 
00297               switch (j)
00298                 {
00299                   // d()/dxi
00300                 case 0:
00301                   {
00302                     return RealGradient( 0.0, f*1.0);
00303                   }
00304                   // d()/deta
00305                 case 1:
00306                   {
00307                     return RealGradient( f*(-1.0) );
00308                   }
00309                 default:
00310                   libmesh_error_msg("Invalid j = " << j);
00311                 }
00312             }
00313 
00314           default:
00315             libmesh_error_msg("ERROR: Unsupported 2D element type!: " << elem->type());
00316           }
00317       }
00318       // unsupported order
00319     default:
00320       libmesh_error_msg("ERROR: Unsupported 2D FE order!: " << total_order);
00321     }
00322 #endif // LIBMESH_DIM > 1
00323 
00324   libmesh_error_msg("We'll never get here!");
00325   return RealGradient();
00326 }
00327 
00328 
00329 
00330 
00331 template <>
00332 RealGradient FE<2,NEDELEC_ONE>::shape_second_deriv(const ElemType,
00333                                                    const Order,
00334                                                    const unsigned int,
00335                                                    const unsigned int,
00336                                                    const Point&)
00337 {
00338   libmesh_error_msg("Nedelec elements require the element type \nbecause edge orientation is needed.");
00339   return RealGradient();
00340 }
00341 
00342 
00343 
00344 template <>
00345 RealGradient FE<2,NEDELEC_ONE>::shape_second_deriv(const Elem* elem,
00346                                                    const Order order,
00347                                                    const unsigned int libmesh_dbg_var(i),
00348                                                    const unsigned int libmesh_dbg_var(j),
00349                                                    const Point&)
00350 {
00351 #if LIBMESH_DIM > 1
00352   libmesh_assert(elem);
00353 
00354   // j = 0 ==> d^2 phi / dxi^2
00355   // j = 1 ==> d^2 phi / dxi deta
00356   // j = 2 ==> d^2 phi / deta^2
00357   libmesh_assert_less (j, 3);
00358 
00359   const Order total_order = static_cast<Order>(order + elem->p_level());
00360 
00361   switch (total_order)
00362     {
00363       // linear Lagrange shape functions
00364     case FIRST:
00365       {
00366         switch (elem->type())
00367           {
00368           case QUAD8:
00369           case QUAD9:
00370             {
00371               libmesh_assert_less (i, 4);
00372               // All second derivatives for linear quads are zero.
00373               return RealGradient();
00374             }
00375 
00376           case TRI6:
00377             {
00378               libmesh_assert_less (i, 3);
00379               // All second derivatives for linear triangles are zero.
00380               return RealGradient();
00381             }
00382 
00383           default:
00384             libmesh_error_msg("ERROR: Unsupported 2D element type!: " << elem->type());
00385 
00386           } // end switch (type)
00387       } // end case FIRST
00388 
00389       // unsupported order
00390     default:
00391       libmesh_error_msg("ERROR: Unsupported 2D FE order!: " << total_order);
00392 
00393     } // end switch (order)
00394 
00395 #endif // LIBMESH_DIM > 1
00396 
00397   libmesh_error_msg("We'll never get here!");
00398   return RealGradient();
00399 }
00400 
00401 } // namespace libMesh