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