$extrastylesheet
fe_clough.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 
00027 namespace libMesh
00028 {
00029 
00030 // ------------------------------------------------------------
00031 // Clough-specific implementations
00032 
00033 // Anonymous namespace for local helper functions
00034 namespace {
00035 
00036 void clough_nodal_soln(const Elem* elem,
00037                        const Order order,
00038                        const std::vector<Number>& elem_soln,
00039                        std::vector<Number>&       nodal_soln,
00040                        unsigned Dim)
00041 {
00042   const unsigned int n_nodes = elem->n_nodes();
00043 
00044   const ElemType elem_type = elem->type();
00045 
00046   nodal_soln.resize(n_nodes);
00047 
00048   const Order totalorder = static_cast<Order>(order + elem->p_level());
00049 
00050   // FEType object to be passed to various FEInterface functions below.
00051   FEType fe_type(totalorder, CLOUGH);
00052 
00053   switch (totalorder)
00054     {
00055       // Piecewise cubic shape functions with linear flux edges
00056     case SECOND:
00057       // Piecewise cubic shape functions
00058     case THIRD:
00059       {
00060 
00061         const unsigned int n_sf =
00062           // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
00063           FEInterface::n_shape_functions(Dim, fe_type, elem_type);
00064 
00065         std::vector<Point> refspace_nodes;
00066         FEBase::get_refspace_nodes(elem_type,refspace_nodes);
00067         libmesh_assert_equal_to (refspace_nodes.size(), n_nodes);
00068 
00069         for (unsigned int n=0; n<n_nodes; n++)
00070           {
00071             libmesh_assert_equal_to (elem_soln.size(), n_sf);
00072 
00073             // Zero before summation
00074             nodal_soln[n] = 0;
00075 
00076             // u_i = Sum (alpha_i phi_i)
00077             for (unsigned int i=0; i<n_sf; i++)
00078               nodal_soln[n] += elem_soln[i] *
00079                 // FE<Dim,T>::shape(elem, order, i, mapped_point);
00080                 FEInterface::shape(Dim, fe_type, elem, i, refspace_nodes[n]);
00081           }
00082 
00083         return;
00084       }
00085 
00086     default:
00087       libmesh_error_msg("ERROR: Invalid total order " << totalorder);
00088     }
00089 } // clough_nodal_soln()
00090 
00091 
00092 
00093 
00094 unsigned int clough_n_dofs(const ElemType t, const Order o)
00095 {
00096   if (t == INVALID_ELEM)
00097     return 0;
00098 
00099   switch (o)
00100     {
00101       // Piecewise cubic shape functions with linear flux edges
00102     case SECOND:
00103       {
00104         switch (t)
00105           {
00106           case TRI6:
00107             return 9;
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       // Piecewise cubic Clough-Tocher element
00114     case THIRD:
00115       {
00116         switch (t)
00117           {
00118           case TRI6:
00119             return 12;
00120 
00121           default:
00122             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
00123           }
00124       }
00125 
00126     default:
00127       libmesh_error_msg("ERROR: Invalid Order " << Utility::enum_to_string(o) << " selected for CLOUGH FE family!");
00128     }
00129 
00130   libmesh_error_msg("We'll never get here!");
00131   return 0;
00132 } // clough_n_dofs()
00133 
00134 
00135 
00136 
00137 
00138 unsigned int clough_n_dofs_at_node(const ElemType t,
00139                                    const Order o,
00140                                    const unsigned int n)
00141 {
00142   switch (o)
00143     {
00144       // Piecewise cubic shape functions with linear flux edges
00145     case SECOND:
00146       {
00147         switch (t)
00148           {
00149             // The 2D Clough-Tocher defined on a 6-noded triangle
00150           case TRI6:
00151             {
00152               switch (n)
00153                 {
00154                 case 0:
00155                 case 1:
00156                 case 2:
00157                   return 3;
00158 
00159                 case 3:
00160                 case 4:
00161                 case 5:
00162                   return 0;
00163 
00164                 default:
00165                   libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TRI6!");
00166                 }
00167             }
00168 
00169           default:
00170             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
00171           }
00172       }
00173       // The third-order clough shape functions
00174     case THIRD:
00175       {
00176         switch (t)
00177           {
00178             // The 2D Clough-Tocher defined on a 6-noded triangle
00179           case TRI6:
00180             {
00181               switch (n)
00182                 {
00183                 case 0:
00184                 case 1:
00185                 case 2:
00186                   return 3;
00187 
00188                 case 3:
00189                 case 4:
00190                 case 5:
00191                   return 1;
00192 
00193                 default:
00194                   libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TRI6!");
00195                 }
00196             }
00197 
00198           default:
00199             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
00200           }
00201       }
00202     default:
00203       libmesh_error_msg("ERROR: Invalid Order " << Utility::enum_to_string(o) << " selected for CLOUGH FE family!");
00204     }
00205 
00206   libmesh_error_msg("We'll never get here!");
00207   return 0;
00208 } // clough_n_dofs_at_node()
00209 
00210 
00211 
00212 
00213 unsigned int clough_n_dofs_per_elem(const ElemType t, const Order o)
00214 {
00215   switch (o)
00216     {
00217       // Piecewise cubic shape functions with linear flux edges
00218     case SECOND:
00219       // The third-order Clough-Tocher shape functions
00220     case THIRD:
00221       {
00222         switch (t)
00223           {
00224             // The 2D clough defined on a 6-noded triangle
00225           case TRI6:
00226             return 0;
00227 
00228           default:
00229             libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
00230           }
00231       }
00232 
00233     default:
00234       libmesh_error_msg("ERROR: Invalid Order " << Utility::enum_to_string(o) << " selected for CLOUGH FE family!");
00235     }
00236 
00237   libmesh_error_msg("We'll never get here!");
00238   return 0;
00239 } // clough_n_dofs_per_elem()
00240 
00241 } // anonymous
00242 
00243 
00244 
00245 
00246   // Do full-specialization of nodal_soln() function for every
00247   // dimension, instead of explicit instantiation at the end of this
00248   // file.
00249   // This could be macro-ified so that it fits on one line...
00250 template <>
00251 void FE<0,CLOUGH>::nodal_soln(const Elem* elem,
00252                               const Order order,
00253                               const std::vector<Number>& elem_soln,
00254                               std::vector<Number>& nodal_soln)
00255 { clough_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }
00256 
00257 template <>
00258 void FE<1,CLOUGH>::nodal_soln(const Elem* elem,
00259                               const Order order,
00260                               const std::vector<Number>& elem_soln,
00261                               std::vector<Number>& nodal_soln)
00262 { clough_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }
00263 
00264 template <>
00265 void FE<2,CLOUGH>::nodal_soln(const Elem* elem,
00266                               const Order order,
00267                               const std::vector<Number>& elem_soln,
00268                               std::vector<Number>& nodal_soln)
00269 { clough_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }
00270 
00271 template <>
00272 void FE<3,CLOUGH>::nodal_soln(const Elem* elem,
00273                               const Order order,
00274                               const std::vector<Number>& elem_soln,
00275                               std::vector<Number>& nodal_soln)
00276 { clough_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }
00277 
00278 
00279 // Full specialization of n_dofs() function for every dimension
00280 template <> unsigned int FE<0,CLOUGH>::n_dofs(const ElemType t, const Order o) { return clough_n_dofs(t, o); }
00281 template <> unsigned int FE<1,CLOUGH>::n_dofs(const ElemType t, const Order o) { return clough_n_dofs(t, o); }
00282 template <> unsigned int FE<2,CLOUGH>::n_dofs(const ElemType t, const Order o) { return clough_n_dofs(t, o); }
00283 template <> unsigned int FE<3,CLOUGH>::n_dofs(const ElemType t, const Order o) { return clough_n_dofs(t, o); }
00284 
00285 
00286 // Full specialization of n_dofs_at_node() function for every dimension.
00287 template <> unsigned int FE<0,CLOUGH>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return clough_n_dofs_at_node(t, o, n); }
00288 template <> unsigned int FE<1,CLOUGH>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return clough_n_dofs_at_node(t, o, n); }
00289 template <> unsigned int FE<2,CLOUGH>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return clough_n_dofs_at_node(t, o, n); }
00290 template <> unsigned int FE<3,CLOUGH>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return clough_n_dofs_at_node(t, o, n); }
00291 
00292 // Full specialization of n_dofs_per_elem() function for every dimension.
00293 template <> unsigned int FE<0,CLOUGH>::n_dofs_per_elem(const ElemType t, const Order o) { return clough_n_dofs_per_elem(t, o); }
00294 template <> unsigned int FE<1,CLOUGH>::n_dofs_per_elem(const ElemType t, const Order o) { return clough_n_dofs_per_elem(t, o); }
00295 template <> unsigned int FE<2,CLOUGH>::n_dofs_per_elem(const ElemType t, const Order o) { return clough_n_dofs_per_elem(t, o); }
00296 template <> unsigned int FE<3,CLOUGH>::n_dofs_per_elem(const ElemType t, const Order o) { return clough_n_dofs_per_elem(t, o); }
00297 
00298 // Clough FEMs are C^1 continuous
00299 template <> FEContinuity FE<0,CLOUGH>::get_continuity() const { return C_ONE; }
00300 template <> FEContinuity FE<1,CLOUGH>::get_continuity() const { return C_ONE; }
00301 template <> FEContinuity FE<2,CLOUGH>::get_continuity() const { return C_ONE; }
00302 template <> FEContinuity FE<3,CLOUGH>::get_continuity() const { return C_ONE; }
00303 
00304 // Clough FEMs are not (currently) hierarchic
00305 template <> bool FE<0,CLOUGH>::is_hierarchic() const { return false; } // FIXME - this will be changed
00306 template <> bool FE<1,CLOUGH>::is_hierarchic() const { return false; } // FIXME - this will be changed
00307 template <> bool FE<2,CLOUGH>::is_hierarchic() const { return false; } // FIXME - this will be changed
00308 template <> bool FE<3,CLOUGH>::is_hierarchic() const { return false; } // FIXME - this will be changed
00309 
00310 #ifdef LIBMESH_ENABLE_AMR
00311 // compute_constraints() specializations are only needed for 2 and 3D
00312 template <>
00313 void FE<2,CLOUGH>::compute_constraints (DofConstraints &constraints,
00314                                         DofMap &dof_map,
00315                                         const unsigned int variable_number,
00316                                         const Elem* elem)
00317 { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
00318 
00319 template <>
00320 void FE<3,CLOUGH>::compute_constraints (DofConstraints &constraints,
00321                                         DofMap &dof_map,
00322                                         const unsigned int variable_number,
00323                                         const Elem* elem)
00324 { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
00325 #endif // #ifdef LIBMESH_ENABLE_AMR
00326 
00327 // Clough FEM shapes need reinit
00328 template <> bool FE<0,CLOUGH>::shapes_need_reinit() const { return true; }
00329 template <> bool FE<1,CLOUGH>::shapes_need_reinit() const { return true; }
00330 template <> bool FE<2,CLOUGH>::shapes_need_reinit() const { return true; }
00331 template <> bool FE<3,CLOUGH>::shapes_need_reinit() const { return true; }
00332 
00333 } // namespace libMesh