$extrastylesheet
fe_hierarchic.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 // 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