fe_hermite_shape_2D.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 #include "libmesh/number_lookups.h" 00025 00026 #ifdef LIBMESH_HAVE_TBB_API 00027 #include "tbb/enumerable_thread_specific.h" 00028 #endif 00029 00030 00031 // Anonymous namespace for persistant variables. 00032 // This allows us to cache the global-to-local mapping transformation 00033 // This caching is turned off when TBB is enabled... 00034 namespace 00035 { 00036 using namespace libMesh; 00037 00038 #ifndef LIBMESH_HAVE_TBB_API 00039 static dof_id_type old_elem_id = libMesh::invalid_uint; 00040 // Mapping functions - derivatives at each dofpt 00041 std::vector<std::vector<Real> > dxdxi(2, std::vector<Real>(2, 0)); 00042 #else //LIBMESH_HAVE_TBB_API 00043 static tbb::enumerable_thread_specific< dof_id_type > old_elem_id_tls; 00044 static tbb::enumerable_thread_specific<std::vector<std::vector<Real> > > dxdxi_tls; 00045 #endif //LIBMESH_HAVE_TBB_API 00046 00047 00048 // Compute the static coefficients for an element 00049 void hermite_compute_coefs(const Elem* elem) 00050 { 00051 #ifndef LIBMESH_HAVE_TBB_API 00052 // Coefficients are cached from old elements 00053 // ... except that we can't be sure that a renumbering didn't 00054 // cause the first element id in a new assembly to match the 00055 // last element id in an old assembly ... 00056 // if (elem->id() == old_elem_id) 00057 // return; 00058 00059 old_elem_id = elem->id(); 00060 #else 00061 bool old_elem_id_exists = false; 00062 dof_id_type & old_elem_id = old_elem_id_tls.local(old_elem_id_exists); 00063 00064 if(!old_elem_id_exists) 00065 old_elem_id = libMesh::invalid_uint; 00066 00067 // Coefficients are cached from old elements 00068 // ... except that we can't be sure that a renumbering didn't 00069 // cause the first element id in a new assembly to match the 00070 // last element id in an old assembly ... 00071 // if (elem->id() == old_elem_id) 00072 // return; 00073 00074 old_elem_id = elem->id(); 00075 00076 bool dxdxi_exists = false; 00077 std::vector< std::vector<Real> > & dxdxi = dxdxi_tls.local(dxdxi_exists); 00078 00079 // This allows us to just resize this once per thread 00080 if(!dxdxi_exists) 00081 { 00082 dxdxi.resize(2); 00083 for(unsigned int i=0; i<2; i++) 00084 dxdxi[i].resize(2); 00085 } 00086 #endif //LIBMESH_HAVE_TBB_API 00087 00088 #ifdef DEBUG 00089 std::vector<Real> dxdeta(2), dydxi(2); 00090 #endif //DEBUG 00091 const Order mapping_order (elem->default_order()); 00092 const ElemType mapping_elem_type (elem->type()); 00093 const int n_mapping_shape_functions = 00094 FE<2,LAGRANGE>::n_shape_functions(mapping_elem_type, 00095 mapping_order); 00096 00097 std::vector<Point> dofpt; 00098 dofpt.push_back(Point(-1,-1)); 00099 dofpt.push_back(Point(1,1)); 00100 00101 for (int p = 0; p != 2; ++p) 00102 { 00103 dxdxi[0][p] = 0; 00104 dxdxi[1][p] = 0; 00105 #ifdef DEBUG 00106 dxdeta[p] = 0; 00107 dydxi[p] = 0; 00108 #endif 00109 for (int i = 0; i != n_mapping_shape_functions; ++i) 00110 { 00111 const Real ddxi = FE<2,LAGRANGE>::shape_deriv 00112 (mapping_elem_type, mapping_order, i, 0, dofpt[p]); 00113 const Real ddeta = FE<2,LAGRANGE>::shape_deriv 00114 (mapping_elem_type, mapping_order, i, 1, dofpt[p]); 00115 00116 dxdxi[0][p] += elem->point(i)(0) * ddxi; 00117 dxdxi[1][p] += elem->point(i)(1) * ddeta; 00118 // dxdeta and dydxi should be 0! 00119 #ifdef DEBUG 00120 dxdeta[p] += elem->point(i)(0) * ddeta; 00121 dydxi[p] += elem->point(i)(1) * ddxi; 00122 #endif 00123 } 00124 // No singular elements! 00125 libmesh_assert(dxdxi[0][p]); 00126 libmesh_assert(dxdxi[1][p]); 00127 // No non-rectilinear or non-axis-aligned elements! 00128 #ifdef DEBUG 00129 libmesh_assert_less (std::abs(dxdeta[p]), 1e-9); 00130 libmesh_assert_less (std::abs(dydxi[p]), 1e-9); 00131 #endif 00132 } 00133 } 00134 00135 00136 00137 Real hermite_bases_2D 00138 (std::vector<unsigned int> &bases1D, 00139 const std::vector<std::vector<Real> > &dxdxi, 00140 const Order &o, 00141 unsigned int i) 00142 { 00143 bases1D.clear(); 00144 bases1D.resize(2,0); 00145 Real coef = 1.0; 00146 00147 unsigned int e = o-3; 00148 00149 // Nodes 00150 if (i < 16) 00151 { 00152 switch (i / 4) 00153 { 00154 case 0: 00155 break; 00156 case 1: 00157 bases1D[0] = 1; 00158 break; 00159 case 2: 00160 bases1D[0] = 1; 00161 bases1D[1] = 1; 00162 break; 00163 case 3: 00164 bases1D[1] = 1; 00165 break; 00166 } 00167 00168 unsigned int basisnum = i%4; 00169 switch (basisnum) 00170 { 00171 case 0: // DoF = value at node 00172 coef = 1.0; 00173 break; 00174 case 1: // DoF = x derivative at node 00175 coef = dxdxi[0][bases1D[0]]; 00176 bases1D[0] += 2; break; 00177 case 2: // DoF = y derivative at node 00178 coef = dxdxi[1][bases1D[1]]; 00179 bases1D[1] += 2; break; 00180 case 3: // DoF = xy derivative at node 00181 coef = dxdxi[0][bases1D[0]] * dxdxi[1][bases1D[1]]; 00182 bases1D[0] += 2; bases1D[1] += 2; break; 00183 default: 00184 libmesh_error(); 00185 } 00186 } 00187 // Edges 00188 else if (i < 16 + 4*2*e) 00189 { 00190 unsigned int basisnum = (i - 16) % (2*e); 00191 switch ((i - 16) / (2*e)) 00192 { 00193 case 0: 00194 bases1D[0] = basisnum/2 + 4; 00195 bases1D[1] = basisnum%2*2; 00196 if (basisnum%2) 00197 coef = dxdxi[1][0]; 00198 break; 00199 case 1: 00200 bases1D[0] = basisnum%2*2 + 1; 00201 bases1D[1] = basisnum/2 + 4; 00202 if (basisnum%2) 00203 coef = dxdxi[0][1]; 00204 break; 00205 case 2: 00206 bases1D[0] = basisnum/2 + 4; 00207 bases1D[1] = basisnum%2*2 + 1; 00208 if (basisnum%2) 00209 coef = dxdxi[1][1]; 00210 break; 00211 case 3: 00212 bases1D[0] = basisnum%2*2; 00213 bases1D[1] = basisnum/2 + 4; 00214 if (basisnum%2) 00215 coef = dxdxi[0][0]; 00216 break; 00217 default: 00218 libmesh_error(); 00219 } 00220 } 00221 // Interior 00222 else 00223 { 00224 unsigned int basisnum = i - 16 - 8*e; 00225 bases1D[0] = square_number_row[basisnum]+4; 00226 bases1D[1] = square_number_column[basisnum]+4; 00227 } 00228 00229 // No singular elements 00230 libmesh_assert(coef); 00231 return coef; 00232 } 00233 00234 } // end anonymous namespace 00235 00236 00237 namespace libMesh 00238 { 00239 00240 00241 template <> 00242 Real FE<2,HERMITE>::shape(const ElemType, 00243 const Order, 00244 const unsigned int, 00245 const Point&) 00246 { 00247 libMesh::err << "Hermite elements require the real element\n" 00248 << "to construct gradient-based degrees of freedom." 00249 << std::endl; 00250 00251 libmesh_error(); 00252 return 0.; 00253 } 00254 00255 00256 00257 template <> 00258 Real FE<2,HERMITE>::shape(const Elem* elem, 00259 const Order order, 00260 const unsigned int i, 00261 const Point& p) 00262 { 00263 libmesh_assert(elem); 00264 00265 hermite_compute_coefs(elem); 00266 00267 #ifdef LIBMESH_HAVE_TBB_API 00268 std::vector<std::vector<Real> > & dxdxi = dxdxi_tls.local(); 00269 #endif // LIBMESH_HAVE_TBB_API 00270 00271 const ElemType type = elem->type(); 00272 00273 const Order totalorder = static_cast<Order>(order + elem->p_level()); 00274 00275 switch (type) 00276 { 00277 case QUAD4: 00278 libmesh_assert_less (totalorder, 4); 00279 case QUAD8: 00280 case QUAD9: 00281 { 00282 libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u)); 00283 00284 std::vector<unsigned int> bases1D; 00285 00286 Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i); 00287 00288 return coef * FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) * 00289 FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)); 00290 } 00291 default: 00292 libMesh::err << "ERROR: Unsupported element type!" << std::endl; 00293 libmesh_error(); 00294 } 00295 00296 libmesh_error(); 00297 return 0.; 00298 } 00299 00300 00301 00302 template <> 00303 Real FE<2,HERMITE>::shape_deriv(const ElemType, 00304 const Order, 00305 const unsigned int, 00306 const unsigned int, 00307 const Point&) 00308 { 00309 libMesh::err << "Hermite elements require the real element\n" 00310 << "to construct gradient-based degrees of freedom." 00311 << std::endl; 00312 00313 libmesh_error(); 00314 return 0.; 00315 } 00316 00317 00318 00319 template <> 00320 Real FE<2,HERMITE>::shape_deriv(const Elem* elem, 00321 const Order order, 00322 const unsigned int i, 00323 const unsigned int j, 00324 const Point& p) 00325 { 00326 libmesh_assert(elem); 00327 libmesh_assert (j == 0 || j == 1); 00328 00329 hermite_compute_coefs(elem); 00330 00331 #ifdef LIBMESH_HAVE_TBB_API 00332 std::vector<std::vector<Real> > & dxdxi = dxdxi_tls.local(); 00333 #endif // LIBMESH_HAVE_TBB_API 00334 00335 const ElemType type = elem->type(); 00336 00337 const Order totalorder = static_cast<Order>(order + elem->p_level()); 00338 00339 switch (type) 00340 { 00341 case QUAD4: 00342 libmesh_assert_less (totalorder, 4); 00343 case QUAD8: 00344 case QUAD9: 00345 { 00346 libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u)); 00347 00348 std::vector<unsigned int> bases1D; 00349 00350 Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i); 00351 00352 switch (j) 00353 { 00354 case 0: 00355 return coef * 00356 FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) * 00357 FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)); 00358 case 1: 00359 return coef * 00360 FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) * 00361 FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)); 00362 default: 00363 libmesh_error(); 00364 } 00365 } 00366 default: 00367 libMesh::err << "ERROR: Unsupported element type!" << std::endl; 00368 libmesh_error(); 00369 } 00370 00371 libmesh_error(); 00372 return 0.; 00373 } 00374 00375 00376 00377 template <> 00378 Real FE<2,HERMITE>::shape_second_deriv(const Elem* elem, 00379 const Order order, 00380 const unsigned int i, 00381 const unsigned int j, 00382 const Point& p) 00383 { 00384 libmesh_assert(elem); 00385 libmesh_assert (j == 0 || j == 1 || j == 2); 00386 00387 hermite_compute_coefs(elem); 00388 00389 #ifdef LIBMESH_HAVE_TBB_API 00390 std::vector<std::vector<Real> > & dxdxi = dxdxi_tls.local(); 00391 #endif // LIBMESH_HAVE_TBB_API 00392 00393 const ElemType type = elem->type(); 00394 00395 const Order totalorder = static_cast<Order>(order + elem->p_level()); 00396 00397 switch (type) 00398 { 00399 case QUAD4: 00400 libmesh_assert_less (totalorder, 4); 00401 case QUAD8: 00402 case QUAD9: 00403 { 00404 libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u)); 00405 00406 std::vector<unsigned int> bases1D; 00407 00408 Real coef = hermite_bases_2D(bases1D, dxdxi, totalorder, i); 00409 00410 switch (j) 00411 { 00412 case 0: 00413 return coef * 00414 FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[0],p(0)) * 00415 FEHermite<1>::hermite_raw_shape(bases1D[1],p(1)); 00416 case 1: 00417 return coef * 00418 FEHermite<1>::hermite_raw_shape_deriv(bases1D[0],p(0)) * 00419 FEHermite<1>::hermite_raw_shape_deriv(bases1D[1],p(1)); 00420 case 2: 00421 return coef * 00422 FEHermite<1>::hermite_raw_shape(bases1D[0],p(0)) * 00423 FEHermite<1>::hermite_raw_shape_second_deriv(bases1D[1],p(1)); 00424 default: 00425 libmesh_error(); 00426 } 00427 } 00428 default: 00429 libMesh::err << "ERROR: Unsupported element type!" << std::endl; 00430 libmesh_error(); 00431 } 00432 00433 libmesh_error(); 00434 return 0.; 00435 } 00436 00437 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: