fe_bernstein.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 00020 // Local includes 00021 #include "libmesh/libmesh_config.h" 00022 #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES 00023 00024 #include "libmesh/fe.h" 00025 #include "libmesh/elem.h" 00026 #include "libmesh/fe_interface.h" 00027 00028 namespace libMesh 00029 { 00030 00031 // ------------------------------------------------------------ 00032 // Bernstein-specific implementations, Steffen Petersen 2005 00033 00034 // Anonymous namespace for local helper functions 00035 namespace { 00036 00037 void bernstein_nodal_soln(const Elem* elem, 00038 const Order order, 00039 const std::vector<Number>& elem_soln, 00040 std::vector<Number>& nodal_soln, 00041 unsigned Dim) 00042 { 00043 const unsigned int n_nodes = elem->n_nodes(); 00044 00045 const ElemType elem_type = elem->type(); 00046 00047 nodal_soln.resize(n_nodes); 00048 00049 const Order totalorder = static_cast<Order>(order + elem->p_level()); 00050 00051 // FEType object to be passed to various FEInterface functions below. 00052 FEType fe_type(totalorder, BERNSTEIN); 00053 00054 switch (totalorder) 00055 { 00056 // Constant shape functions 00057 case CONSTANT: 00058 { 00059 libmesh_assert_equal_to (elem_soln.size(), 1); 00060 00061 const Number val = elem_soln[0]; 00062 00063 for (unsigned int n=0; n<n_nodes; n++) 00064 nodal_soln[n] = val; 00065 00066 return; 00067 } 00068 00069 00070 // For other bases do interpolation at the nodes 00071 // explicitly. 00072 case FIRST: 00073 case SECOND: 00074 case THIRD: 00075 case FOURTH: 00076 case FIFTH: 00077 case SIXTH: 00078 { 00079 00080 const unsigned int n_sf = 00081 // FE<Dim,T>::n_shape_functions(elem_type, totalorder); 00082 FEInterface::n_shape_functions(Dim, fe_type, elem_type); 00083 00084 std::vector<Point> refspace_nodes; 00085 FEBase::get_refspace_nodes(elem_type,refspace_nodes); 00086 libmesh_assert_equal_to (refspace_nodes.size(), n_nodes); 00087 00088 for (unsigned int n=0; n<n_nodes; n++) 00089 { 00090 libmesh_assert_equal_to (elem_soln.size(), n_sf); 00091 00092 // Zero before summation 00093 nodal_soln[n] = 0; 00094 00095 // u_i = Sum (alpha_i phi_i) 00096 for (unsigned int i=0; i<n_sf; i++) 00097 nodal_soln[n] += elem_soln[i] * 00098 // FE<Dim,T>::shape(elem, order, i, mapped_point); 00099 FEInterface::shape(Dim, fe_type, elem, i, refspace_nodes[n]); 00100 } 00101 00102 return; 00103 } 00104 00105 default: 00106 { 00107 libmesh_error(); 00108 return; 00109 } 00110 } 00111 00112 00113 // How did we get here? 00114 libmesh_error(); 00115 return; 00116 } // bernstein_nodal_soln() 00117 00118 00119 00120 unsigned int bernstein_n_dofs(const ElemType t, const Order o) 00121 { 00122 switch (t) 00123 { 00124 case NODEELEM: 00125 return 1; 00126 case EDGE2: 00127 case EDGE3: 00128 return (o+1); 00129 case QUAD4: 00130 libmesh_assert_less (o, 2); 00131 case QUAD8: 00132 { 00133 if (o == 1) 00134 return 4; 00135 else if (o == 2) 00136 return 8; 00137 else 00138 libmesh_error(); 00139 } 00140 case QUAD9: 00141 return ((o+1)*(o+1)); 00142 case HEX8: 00143 libmesh_assert_less (o, 2); 00144 case HEX20: 00145 { 00146 if (o == 1) 00147 return 8; 00148 else if (o == 2) 00149 return 20; 00150 else 00151 libmesh_error(); 00152 } 00153 case HEX27: 00154 return ((o+1)*(o+1)*(o+1)); 00155 case TRI3: 00156 libmesh_assert_less (o, 2); 00157 case TRI6: 00158 return ((o+1)*(o+2)/2); 00159 case TET4: 00160 libmesh_assert_less (o, 2); 00161 case TET10: 00162 { 00163 libmesh_assert_less (o, 3); 00164 return ((o+1)*(o+2)*(o+3)/6); 00165 } 00166 default: 00167 libmesh_error(); 00168 } 00169 00170 libmesh_error(); 00171 return 0; 00172 } // bernstein_n_dofs() 00173 00174 00175 00176 00177 unsigned int bernstein_n_dofs_at_node(const ElemType t, 00178 const Order o, 00179 const unsigned int n) 00180 { 00181 switch (t) 00182 { 00183 case NODEELEM: 00184 return 1; 00185 00186 case EDGE2: 00187 case EDGE3: 00188 switch (n) 00189 { 00190 case 0: 00191 case 1: 00192 return 1; 00193 case 2: 00194 libmesh_assert (o>1); 00195 return (o-1); 00196 default: 00197 libmesh_error(); 00198 } 00199 case TRI6: 00200 switch (n) 00201 { 00202 case 0: 00203 case 1: 00204 case 2: 00205 return 1; 00206 00207 case 3: 00208 case 4: 00209 case 5: 00210 return (o-1); 00211 // Internal DoFs are associated with the elem, not its nodes 00212 default: 00213 libmesh_error(); 00214 } 00215 case QUAD8: 00216 libmesh_assert_less (n, 8); 00217 libmesh_assert_less (o, 3); 00218 case QUAD9: 00219 { 00220 switch (n) 00221 { 00222 case 0: 00223 case 1: 00224 case 2: 00225 case 3: 00226 return 1; 00227 00228 case 4: 00229 case 5: 00230 case 6: 00231 case 7: 00232 return (o-1); 00233 00234 // Internal DoFs are associated with the elem, not its nodes 00235 case 8: 00236 return 0; 00237 00238 default: 00239 libmesh_error(); 00240 } 00241 } 00242 case HEX8: 00243 libmesh_assert_less (n, 8); 00244 libmesh_assert_less (o, 2); 00245 case HEX20: 00246 libmesh_assert_less (n, 20); 00247 libmesh_assert_less (o, 3); 00248 case HEX27: 00249 switch (n) 00250 { 00251 case 0: 00252 case 1: 00253 case 2: 00254 case 3: 00255 case 4: 00256 case 5: 00257 case 6: 00258 case 7: 00259 return 1; 00260 00261 case 8: 00262 case 9: 00263 case 10: 00264 case 11: 00265 case 12: 00266 case 13: 00267 case 14: 00268 case 15: 00269 case 16: 00270 case 17: 00271 case 18: 00272 case 19: 00273 return (o-1); 00274 00275 case 20: 00276 case 21: 00277 case 22: 00278 case 23: 00279 case 24: 00280 case 25: 00281 return ((o-1)*(o-1)); 00282 00283 // Internal DoFs are associated with the elem, not its nodes 00284 case 26: 00285 return 0; 00286 00287 default: 00288 libmesh_error(); 00289 } 00290 case TET4: 00291 libmesh_assert_less (n, 4); 00292 libmesh_assert_less (o, 2); 00293 case TET10: 00294 libmesh_assert_less (o, 3); 00295 libmesh_assert_less (n, 10); 00296 switch (n) 00297 { 00298 case 0: 00299 case 1: 00300 case 2: 00301 case 3: 00302 return 1; 00303 00304 case 4: 00305 case 5: 00306 case 6: 00307 case 7: 00308 case 8: 00309 case 9: 00310 return (o-1); 00311 00312 default: 00313 libmesh_error(); 00314 } 00315 00316 default: 00317 libmesh_error(); 00318 00319 } 00320 00321 libmesh_error(); 00322 return 0; 00323 } // bernstein_n_dofs_at_node() 00324 00325 00326 00327 00328 unsigned int bernstein_n_dofs_per_elem(const ElemType t, const Order o) 00329 { 00330 switch (t) 00331 { 00332 case NODEELEM: 00333 case EDGE2: 00334 case EDGE3: 00335 return 0; 00336 case TRI3: 00337 case QUAD4: 00338 return 0; 00339 case TRI6: 00340 return ((o-1)*(o-2)/2); 00341 case QUAD8: 00342 if (o <= 2) 00343 return 0; 00344 case QUAD9: 00345 return ((o-1)*(o-1)); 00346 case HEX8: 00347 libmesh_assert_less (o, 2); 00348 case HEX20: 00349 libmesh_assert_less (o, 3); 00350 return 0; 00351 case HEX27: 00352 return ((o-1)*(o-1)*(o-1)); 00353 case TET4: 00354 libmesh_assert_less (o, 2); 00355 case TET10: 00356 libmesh_assert_less (o, 3); 00357 return 0; 00358 default: 00359 libmesh_error(); 00360 } 00361 00362 libmesh_error(); 00363 return 0; 00364 } // bernstein_n_dofs_per_elem 00365 00366 } // anonymous namespace 00367 00368 00369 00370 00371 // Do full-specialization of nodal_soln() function for every 00372 // dimension, instead of explicit instantiation at the end of this 00373 // file. 00374 // This could be macro-ified so that it fits on one line... 00375 template <> 00376 void FE<0,BERNSTEIN>::nodal_soln(const Elem* elem, 00377 const Order order, 00378 const std::vector<Number>& elem_soln, 00379 std::vector<Number>& nodal_soln) 00380 { bernstein_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); } 00381 00382 template <> 00383 void FE<1,BERNSTEIN>::nodal_soln(const Elem* elem, 00384 const Order order, 00385 const std::vector<Number>& elem_soln, 00386 std::vector<Number>& nodal_soln) 00387 { bernstein_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); } 00388 00389 template <> 00390 void FE<2,BERNSTEIN>::nodal_soln(const Elem* elem, 00391 const Order order, 00392 const std::vector<Number>& elem_soln, 00393 std::vector<Number>& nodal_soln) 00394 { bernstein_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); } 00395 00396 template <> 00397 void FE<3,BERNSTEIN>::nodal_soln(const Elem* elem, 00398 const Order order, 00399 const std::vector<Number>& elem_soln, 00400 std::vector<Number>& nodal_soln) 00401 { bernstein_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); } 00402 00403 00404 // Full specialization of n_dofs() function for every dimension 00405 template <> unsigned int FE<0,BERNSTEIN>::n_dofs(const ElemType t, const Order o) { return bernstein_n_dofs(t, o); } 00406 template <> unsigned int FE<1,BERNSTEIN>::n_dofs(const ElemType t, const Order o) { return bernstein_n_dofs(t, o); } 00407 template <> unsigned int FE<2,BERNSTEIN>::n_dofs(const ElemType t, const Order o) { return bernstein_n_dofs(t, o); } 00408 template <> unsigned int FE<3,BERNSTEIN>::n_dofs(const ElemType t, const Order o) { return bernstein_n_dofs(t, o); } 00409 00410 // Full specialization of n_dofs_at_node() function for every dimension. 00411 template <> unsigned int FE<0,BERNSTEIN>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return bernstein_n_dofs_at_node(t, o, n); } 00412 template <> unsigned int FE<1,BERNSTEIN>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return bernstein_n_dofs_at_node(t, o, n); } 00413 template <> unsigned int FE<2,BERNSTEIN>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return bernstein_n_dofs_at_node(t, o, n); } 00414 template <> unsigned int FE<3,BERNSTEIN>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return bernstein_n_dofs_at_node(t, o, n); } 00415 00416 // Full specialization of n_dofs_per_elem() function for every dimension. 00417 template <> unsigned int FE<0,BERNSTEIN>::n_dofs_per_elem(const ElemType t, const Order o) { return bernstein_n_dofs_per_elem(t, o); } 00418 template <> unsigned int FE<1,BERNSTEIN>::n_dofs_per_elem(const ElemType t, const Order o) { return bernstein_n_dofs_per_elem(t, o); } 00419 template <> unsigned int FE<2,BERNSTEIN>::n_dofs_per_elem(const ElemType t, const Order o) { return bernstein_n_dofs_per_elem(t, o); } 00420 template <> unsigned int FE<3,BERNSTEIN>::n_dofs_per_elem(const ElemType t, const Order o) { return bernstein_n_dofs_per_elem(t, o); } 00421 00422 // Bernstein FEMs are C^0 continuous 00423 template <> FEContinuity FE<0,BERNSTEIN>::get_continuity() const { return C_ZERO; } 00424 template <> FEContinuity FE<1,BERNSTEIN>::get_continuity() const { return C_ZERO; } 00425 template <> FEContinuity FE<2,BERNSTEIN>::get_continuity() const { return C_ZERO; } 00426 template <> FEContinuity FE<3,BERNSTEIN>::get_continuity() const { return C_ZERO; } 00427 00428 // Bernstein FEMs are not hierarchic 00429 template <> bool FE<0,BERNSTEIN>::is_hierarchic() const { return false; } 00430 template <> bool FE<1,BERNSTEIN>::is_hierarchic() const { return false; } 00431 template <> bool FE<2,BERNSTEIN>::is_hierarchic() const { return false; } 00432 template <> bool FE<3,BERNSTEIN>::is_hierarchic() const { return false; } 00433 00434 // Bernstein shapes need reinit only for approximation orders >= 3, 00435 // but we might reach that with p refinement 00436 template <> bool FE<0,BERNSTEIN>::shapes_need_reinit() const { return true; } 00437 template <> bool FE<1,BERNSTEIN>::shapes_need_reinit() const { return true; } 00438 template <> bool FE<2,BERNSTEIN>::shapes_need_reinit() const { return true; } 00439 template <> bool FE<3,BERNSTEIN>::shapes_need_reinit() const { return true; } 00440 00441 } // namespace libMesh 00442 00443 #endif //LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: