$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 l2_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, L2_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 } // l2_hierarchic_nodal_soln() 00099 00100 00101 00102 00103 unsigned int l2_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 case QUAD8: 00115 case QUAD9: 00116 return ((o+1)*(o+1)); 00117 case HEX8: 00118 case HEX20: 00119 case HEX27: 00120 return ((o+1)*(o+1)*(o+1)); 00121 case TRI6: 00122 return ((o+1)*(o+2)/2); 00123 case INVALID_ELEM: 00124 return 0; 00125 default: 00126 libmesh_error_msg("ERROR: Invalid ElemType " << Utility::enum_to_string(t) << " selected for L2_HIERARCHIC FE family!"); 00127 } 00128 00129 libmesh_error_msg("We'll never get here!"); 00130 return 0; 00131 } // l2_hierarchic_n_dofs() 00132 00133 00134 } // anonymous namespace 00135 00136 00137 00138 00139 // Do full-specialization of nodal_soln() function for every 00140 // dimension, instead of explicit instantiation at the end of this 00141 // file. 00142 // This could be macro-ified so that it fits on one line... 00143 template <> 00144 void FE<0,L2_HIERARCHIC>::nodal_soln(const Elem* elem, 00145 const Order order, 00146 const std::vector<Number>& elem_soln, 00147 std::vector<Number>& nodal_soln) 00148 { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); } 00149 00150 template <> 00151 void FE<1,L2_HIERARCHIC>::nodal_soln(const Elem* elem, 00152 const Order order, 00153 const std::vector<Number>& elem_soln, 00154 std::vector<Number>& nodal_soln) 00155 { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); } 00156 00157 template <> 00158 void FE<2,L2_HIERARCHIC>::nodal_soln(const Elem* elem, 00159 const Order order, 00160 const std::vector<Number>& elem_soln, 00161 std::vector<Number>& nodal_soln) 00162 { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); } 00163 00164 template <> 00165 void FE<3,L2_HIERARCHIC>::nodal_soln(const Elem* elem, 00166 const Order order, 00167 const std::vector<Number>& elem_soln, 00168 std::vector<Number>& nodal_soln) 00169 { l2_hierarchic_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); } 00170 00171 // Full specialization of n_dofs() function for every dimension 00172 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00173 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00174 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00175 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00176 00177 // Full specialization of n_dofs_at_node() function for every dimension. 00178 // Discontinuous L2 elements only have interior nodes 00179 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; } 00180 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; } 00181 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; } 00182 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; } 00183 00184 // Full specialization of n_dofs_per_elem() function for every dimension. 00185 template <> unsigned int FE<0,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00186 template <> unsigned int FE<1,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00187 template <> unsigned int FE<2,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00188 template <> unsigned int FE<3,L2_HIERARCHIC>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_hierarchic_n_dofs(t, o); } 00189 00190 // L2 Hierarchic FEMs are C^0 continuous 00191 template <> FEContinuity FE<0,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; } 00192 template <> FEContinuity FE<1,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; } 00193 template <> FEContinuity FE<2,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; } 00194 template <> FEContinuity FE<3,L2_HIERARCHIC>::get_continuity() const { return DISCONTINUOUS; } 00195 00196 // L2 Hierarchic FEMs are hierarchic (duh!) 00197 template <> bool FE<0,L2_HIERARCHIC>::is_hierarchic() const { return true; } 00198 template <> bool FE<1,L2_HIERARCHIC>::is_hierarchic() const { return true; } 00199 template <> bool FE<2,L2_HIERARCHIC>::is_hierarchic() const { return true; } 00200 template <> bool FE<3,L2_HIERARCHIC>::is_hierarchic() const { return true; } 00201 00202 #ifdef LIBMESH_ENABLE_AMR 00203 // compute_constraints() is a NOOP for DISCONTINOUS FE's 00204 template <> 00205 void FE<2,L2_HIERARCHIC>::compute_constraints (DofConstraints &, 00206 DofMap &, 00207 const unsigned int, 00208 const Elem*) 00209 { } 00210 00211 template <> 00212 void FE<3,L2_HIERARCHIC>::compute_constraints (DofConstraints &, 00213 DofMap &, 00214 const unsigned int, 00215 const Elem*) 00216 { } 00217 #endif // #ifdef LIBMESH_ENABLE_AMR 00218 00219 // L2-Hierarchic FEM shapes need reinit 00220 template <> bool FE<0,L2_HIERARCHIC>::shapes_need_reinit() const { return true; } 00221 template <> bool FE<1,L2_HIERARCHIC>::shapes_need_reinit() const { return true; } 00222 template <> bool FE<2,L2_HIERARCHIC>::shapes_need_reinit() const { return true; } 00223 template <> bool FE<3,L2_HIERARCHIC>::shapes_need_reinit() const { return true; } 00224 00225 } // namespace libMesh