fe_hermite.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/elem.h" 00022 #include "libmesh/fe.h" 00023 #include "libmesh/fe_interface.h" 00024 00025 namespace libMesh 00026 { 00027 00028 // ------------------------------------------------------------ 00029 // Hermite-specific implementations 00030 00031 // Anonymous namespace for local helper functions 00032 namespace { 00033 00034 void hermite_nodal_soln(const Elem* elem, 00035 const Order order, 00036 const std::vector<Number>& elem_soln, 00037 std::vector<Number>& nodal_soln, 00038 unsigned Dim) 00039 { 00040 const unsigned int n_nodes = elem->n_nodes(); 00041 00042 const ElemType elem_type = elem->type(); 00043 00044 nodal_soln.resize(n_nodes); 00045 00046 const Order totalorder = static_cast<Order>(order + elem->p_level()); 00047 00048 // FEType object to be passed to various FEInterface functions below. 00049 FEType fe_type(totalorder, HERMITE); 00050 00051 const unsigned int n_sf = 00052 // FE<Dim,T>::n_shape_functions(elem_type, totalorder); 00053 FEInterface::n_shape_functions(Dim, fe_type, elem_type); 00054 00055 std::vector<Point> refspace_nodes; 00056 FEBase::get_refspace_nodes(elem_type,refspace_nodes); 00057 libmesh_assert_equal_to (refspace_nodes.size(), n_nodes); 00058 00059 for (unsigned int n=0; n<n_nodes; n++) 00060 { 00061 libmesh_assert_equal_to (elem_soln.size(), n_sf); 00062 00063 // Zero before summation 00064 nodal_soln[n] = 0; 00065 00066 // u_i = Sum (alpha_i phi_i) 00067 for (unsigned int i=0; i<n_sf; i++) 00068 nodal_soln[n] += elem_soln[i] * 00069 // FE<Dim,T>::shape(elem, order, i, mapped_point); 00070 FEInterface::shape(Dim, fe_type, elem, i, refspace_nodes[n]); 00071 } 00072 } // hermite_nodal_soln() 00073 00074 00075 00076 unsigned int hermite_n_dofs(const ElemType t, const Order o) 00077 { 00078 libmesh_assert_greater (o, 2); 00079 // Piecewise (bi/tri)cubic C1 Hermite splines 00080 switch (t) 00081 { 00082 case NODEELEM: 00083 return 1; 00084 case EDGE2: 00085 libmesh_assert_less (o, 4); 00086 case EDGE3: 00087 return (o+1); 00088 00089 case QUAD4: 00090 case QUAD8: 00091 libmesh_assert_less (o, 4); 00092 case QUAD9: 00093 return ((o+1)*(o+1)); 00094 00095 case HEX8: 00096 case HEX20: 00097 libmesh_assert_less (o, 4); 00098 case HEX27: 00099 return ((o+1)*(o+1)*(o+1)); 00100 00101 default: 00102 { 00103 #ifdef DEBUG 00104 libMesh::err << "ERROR: Bad ElemType = " << t 00105 << " for " << o << "th order approximation!" 00106 << std::endl; 00107 #endif 00108 libmesh_error(); 00109 } 00110 } 00111 00112 libmesh_error(); 00113 return 0; 00114 } // hermite_n_dofs() 00115 00116 00117 00118 00119 unsigned int hermite_n_dofs_at_node(const ElemType t, 00120 const Order o, 00121 const unsigned int n) 00122 { 00123 libmesh_assert_greater (o, 2); 00124 // Piecewise (bi/tri)cubic C1 Hermite splines 00125 switch (t) 00126 { 00127 case NODEELEM: 00128 return 1; 00129 case EDGE2: 00130 case EDGE3: 00131 { 00132 switch (n) 00133 { 00134 case 0: 00135 case 1: 00136 return 2; 00137 case 2: 00138 // Interior DoFs are carried on Elems 00139 // return (o-3); 00140 return 0; 00141 00142 default: 00143 libmesh_error(); 00144 } 00145 } 00146 00147 case QUAD4: 00148 libmesh_assert_less (o, 4); 00149 case QUAD8: 00150 case QUAD9: 00151 { 00152 switch (n) 00153 { 00154 // Vertices 00155 case 0: 00156 case 1: 00157 case 2: 00158 case 3: 00159 return 4; 00160 // Edges 00161 case 4: 00162 case 5: 00163 case 6: 00164 case 7: 00165 return (2*(o-3)); 00166 case 8: 00167 // Interior DoFs are carried on Elems 00168 // return ((o-3)*(o-3)); 00169 return 0; 00170 00171 default: 00172 libmesh_error(); 00173 } 00174 } 00175 00176 case HEX8: 00177 case HEX20: 00178 libmesh_assert_less (o, 4); 00179 case HEX27: 00180 { 00181 switch (n) 00182 { 00183 // Vertices 00184 case 0: 00185 case 1: 00186 case 2: 00187 case 3: 00188 case 4: 00189 case 5: 00190 case 6: 00191 case 7: 00192 return 8; 00193 // Edges 00194 case 8: 00195 case 9: 00196 case 10: 00197 case 11: 00198 case 12: 00199 case 13: 00200 case 14: 00201 case 15: 00202 case 16: 00203 case 17: 00204 case 18: 00205 case 19: 00206 return (4*(o-3)); 00207 // Faces 00208 case 20: 00209 case 21: 00210 case 22: 00211 case 23: 00212 case 24: 00213 case 25: 00214 return (2*(o-3)*(o-3)); 00215 case 26: 00216 // Interior DoFs are carried on Elems 00217 // return ((o-3)*(o-3)*(o-3)); 00218 return 0; 00219 00220 default: 00221 libmesh_error(); 00222 } 00223 } 00224 00225 default: 00226 { 00227 #ifdef DEBUG 00228 libMesh::err << "ERROR: Bad ElemType = " << t 00229 << " for " << o << "th order approximation!" 00230 << std::endl; 00231 #endif 00232 libmesh_error(); 00233 } 00234 00235 } 00236 00237 libmesh_error(); 00238 00239 return 0; 00240 } // hermite_n_dofs_at_node() 00241 00242 00243 00244 unsigned int hermite_n_dofs_per_elem(const ElemType t, 00245 const Order o) 00246 { 00247 libmesh_assert_greater (o, 2); 00248 00249 switch (t) 00250 { 00251 case NODEELEM: 00252 return 0; 00253 case EDGE2: 00254 case EDGE3: 00255 return (o-3); 00256 case QUAD4: 00257 libmesh_assert_less (o, 4); 00258 case QUAD8: 00259 case QUAD9: 00260 return ((o-3)*(o-3)); 00261 case HEX8: 00262 libmesh_assert_less (o, 4); 00263 case HEX20: 00264 case HEX27: 00265 return ((o-3)*(o-3)*(o-3)); 00266 00267 default: 00268 { 00269 #ifdef DEBUG 00270 libMesh::err << "ERROR: Bad ElemType = " << t 00271 << " for " << o << "th order approximation!" 00272 << std::endl; 00273 #endif 00274 libmesh_error(); 00275 } 00276 } 00277 00278 // Will never get here... 00279 libmesh_error(); 00280 return 0; 00281 } // hermite_n_dofs_per_elem() 00282 00283 00284 } // anonymous namespace 00285 00286 00287 00288 00289 // Do full-specialization of nodal_soln() function for every 00290 // dimension, instead of explicit instantiation at the end of this 00291 // file. 00292 // This could be macro-ified so that it fits on one line... 00293 template <> 00294 void FE<0,HERMITE>::nodal_soln(const Elem* elem, 00295 const Order order, 00296 const std::vector<Number>& elem_soln, 00297 std::vector<Number>& nodal_soln) 00298 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); } 00299 00300 template <> 00301 void FE<1,HERMITE>::nodal_soln(const Elem* elem, 00302 const Order order, 00303 const std::vector<Number>& elem_soln, 00304 std::vector<Number>& nodal_soln) 00305 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); } 00306 00307 template <> 00308 void FE<2,HERMITE>::nodal_soln(const Elem* elem, 00309 const Order order, 00310 const std::vector<Number>& elem_soln, 00311 std::vector<Number>& nodal_soln) 00312 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); } 00313 00314 template <> 00315 void FE<3,HERMITE>::nodal_soln(const Elem* elem, 00316 const Order order, 00317 const std::vector<Number>& elem_soln, 00318 std::vector<Number>& nodal_soln) 00319 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); } 00320 00321 00322 00323 00324 // Do full-specialization for every dimension, instead 00325 // of explicit instantiation at the end of this function. 00326 // This could be macro-ified. 00327 template <> unsigned int FE<0,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); } 00328 template <> unsigned int FE<1,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); } 00329 template <> unsigned int FE<2,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); } 00330 template <> unsigned int FE<3,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); } 00331 00332 // Do full-specialization for every dimension, instead 00333 // of explicit instantiation at the end of this function. 00334 template <> unsigned int FE<0,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); } 00335 template <> unsigned int FE<1,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); } 00336 template <> unsigned int FE<2,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); } 00337 template <> unsigned int FE<3,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); } 00338 00339 // Full specialization of n_dofs_per_elem() function for every dimension. 00340 template <> unsigned int FE<0,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); } 00341 template <> unsigned int FE<1,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); } 00342 template <> unsigned int FE<2,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); } 00343 template <> unsigned int FE<3,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); } 00344 00345 // Hermite FEMs are C^1 continuous 00346 template <> FEContinuity FE<0,HERMITE>::get_continuity() const { return C_ONE; } 00347 template <> FEContinuity FE<1,HERMITE>::get_continuity() const { return C_ONE; } 00348 template <> FEContinuity FE<2,HERMITE>::get_continuity() const { return C_ONE; } 00349 template <> FEContinuity FE<3,HERMITE>::get_continuity() const { return C_ONE; } 00350 00351 // Hermite FEMs are hierarchic 00352 template <> bool FE<0,HERMITE>::is_hierarchic() const { return true; } 00353 template <> bool FE<1,HERMITE>::is_hierarchic() const { return true; } 00354 template <> bool FE<2,HERMITE>::is_hierarchic() const { return true; } 00355 template <> bool FE<3,HERMITE>::is_hierarchic() const { return true; } 00356 00357 00358 #ifdef LIBMESH_ENABLE_AMR 00359 // compute_constraints() specializations are only needed for 2 and 3D 00360 template <> 00361 void FE<2,HERMITE>::compute_constraints (DofConstraints &constraints, 00362 DofMap &dof_map, 00363 const unsigned int variable_number, 00364 const Elem* elem) 00365 { compute_proj_constraints(constraints, dof_map, variable_number, elem); } 00366 00367 template <> 00368 void FE<3,HERMITE>::compute_constraints (DofConstraints &constraints, 00369 DofMap &dof_map, 00370 const unsigned int variable_number, 00371 const Elem* elem) 00372 { compute_proj_constraints(constraints, dof_map, variable_number, elem); } 00373 #endif // #ifdef LIBMESH_ENABLE_AMR 00374 00375 // Hermite FEM shapes need reinit 00376 template <> bool FE<0,HERMITE>::shapes_need_reinit() const { return true; } 00377 template <> bool FE<1,HERMITE>::shapes_need_reinit() const { return true; } 00378 template <> bool FE<2,HERMITE>::shapes_need_reinit() const { return true; } 00379 template <> bool FE<3,HERMITE>::shapes_need_reinit() const { return true; } 00380 00381 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:46 UTC
Hosted By: