$extrastylesheet
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