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