$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 // C++ inlcludes 00020 00021 // Local includes 00022 #include "libmesh/fe.h" 00023 #include "libmesh/elem.h" 00024 00025 00026 00027 00028 // Anonymous namespace for persistant variables. 00029 // This allows us to determine when the centroid needs 00030 // to be recalculated. 00031 namespace 00032 { 00033 using namespace libMesh; 00034 00035 static dof_id_type old_elem_id = DofObject::invalid_id; 00036 static libMesh::Point centroid; 00037 static Real max_distance; 00038 } 00039 00040 00041 namespace libMesh 00042 { 00043 00044 00045 template <> 00046 Real FE<1,XYZ>::shape(const ElemType, 00047 const Order, 00048 const unsigned int, 00049 const Point&) 00050 { 00051 libmesh_error_msg("XYZ polynomials require the element \n because the centroid is needed."); 00052 return 0.; 00053 } 00054 00055 00056 00057 template <> 00058 Real FE<1,XYZ>::shape(const Elem* elem, 00059 const Order libmesh_dbg_var(order), 00060 const unsigned int i, 00061 const Point& point_in) 00062 { 00063 libmesh_assert(elem); 00064 libmesh_assert_less_equal (i, order + elem->p_level()); 00065 00066 // Only recompute the centroid if the element 00067 // has changed from the last one we computed. 00068 // This avoids repeated centroid calculations 00069 // when called in succession with the same element. 00070 if (elem->id() != old_elem_id) 00071 { 00072 centroid = elem->centroid(); 00073 old_elem_id = elem->id(); 00074 max_distance = 0.; 00075 for (unsigned int p = 0; p < elem->n_nodes(); p++) 00076 { 00077 const Real distance = std::abs(centroid(0) - elem->point(p)(0)); 00078 max_distance = std::max(distance, max_distance); 00079 } 00080 } 00081 00082 // Using static globals for old_elem_id, etc. will fail 00083 // horribly with more than one thread. 00084 libmesh_assert_equal_to (libMesh::n_threads(), 1); 00085 00086 const Real x = point_in(0); 00087 const Real xc = centroid(0); 00088 const Real dx = (x - xc)/max_distance; 00089 00090 // monomials. since they are hierarchic we only need one case block. 00091 switch (i) 00092 { 00093 case 0: 00094 return 1.; 00095 00096 case 1: 00097 return dx; 00098 00099 case 2: 00100 return dx*dx; 00101 00102 case 3: 00103 return dx*dx*dx; 00104 00105 case 4: 00106 return dx*dx*dx*dx; 00107 00108 default: 00109 Real val = 1.; 00110 for (unsigned int index = 0; index != i; ++index) 00111 val *= dx; 00112 return val; 00113 } 00114 00115 libmesh_error_msg("We'll never get here!"); 00116 return 0.; 00117 00118 } 00119 00120 00121 00122 template <> 00123 Real FE<1,XYZ>::shape_deriv(const ElemType, 00124 const Order, 00125 const unsigned int, 00126 const unsigned int, 00127 const Point&) 00128 { 00129 libmesh_error_msg("XYZ polynomials require the element \nbecause the centroid is needed."); 00130 return 0.; 00131 } 00132 00133 00134 00135 template <> 00136 Real FE<1,XYZ>::shape_deriv(const Elem* elem, 00137 const Order libmesh_dbg_var(order), 00138 const unsigned int i, 00139 const unsigned int libmesh_dbg_var(j), 00140 const Point& point_in) 00141 { 00142 libmesh_assert(elem); 00143 libmesh_assert_less_equal (i, order + elem->p_level()); 00144 00145 // only d()/dxi in 1D! 00146 00147 libmesh_assert_equal_to (j, 0); 00148 00149 // Only recompute the centroid if the element 00150 // has changed from the last one we computed. 00151 // This avoids repeated centroid calculations 00152 // when called in succession with the same element. 00153 if (elem->id() != old_elem_id) 00154 { 00155 centroid = elem->centroid(); 00156 old_elem_id = elem->id(); 00157 max_distance = 0.; 00158 for (unsigned int p = 0; p < elem->n_nodes(); p++) 00159 { 00160 const Real distance = std::abs(centroid(0) - elem->point(p)(0)); 00161 max_distance = std::max(distance, max_distance); 00162 } 00163 } 00164 00165 // Using static globals for old_elem_id, etc. will fail 00166 // horribly with more than one thread. 00167 libmesh_assert_equal_to (libMesh::n_threads(), 1); 00168 00169 const Real x = point_in(0); 00170 const Real xc = centroid(0); 00171 const Real dx = (x - xc)/max_distance; 00172 00173 // monomials. since they are hierarchic we only need one case block. 00174 switch (i) 00175 { 00176 case 0: 00177 return 0.; 00178 00179 case 1: 00180 return 1.; 00181 00182 case 2: 00183 return 2.*dx/max_distance; 00184 00185 case 3: 00186 return 3.*dx*dx/max_distance; 00187 00188 case 4: 00189 return 4.*dx*dx*dx/max_distance; 00190 00191 default: 00192 Real val = i; 00193 for (unsigned int index = 1; index != i; ++index) 00194 val *= dx; 00195 return val/max_distance; 00196 } 00197 00198 libmesh_error_msg("We'll never get here!"); 00199 return 0.; 00200 } 00201 00202 00203 00204 template <> 00205 Real FE<1,XYZ>::shape_second_deriv(const ElemType, 00206 const Order, 00207 const unsigned int, 00208 const unsigned int, 00209 const Point&) 00210 { 00211 libmesh_error_msg("XYZ polynomials require the element \nbecause the centroid is needed."); 00212 return 0.; 00213 } 00214 00215 00216 00217 template <> 00218 Real FE<1,XYZ>::shape_second_deriv(const Elem* elem, 00219 const Order libmesh_dbg_var(order), 00220 const unsigned int i, 00221 const unsigned int libmesh_dbg_var(j), 00222 const Point& point_in) 00223 { 00224 libmesh_assert(elem); 00225 libmesh_assert_less_equal (i, order + elem->p_level()); 00226 00227 // only d2()/dxi2 in 1D! 00228 00229 libmesh_assert_equal_to (j, 0); 00230 00231 // Only recompute the centroid if the element 00232 // has changed from the last one we computed. 00233 // This avoids repeated centroid calculations 00234 // when called in succession with the same element. 00235 if (elem->id() != old_elem_id) 00236 { 00237 centroid = elem->centroid(); 00238 old_elem_id = elem->id(); 00239 max_distance = 0.; 00240 for (unsigned int p = 0; p < elem->n_nodes(); p++) 00241 { 00242 const Real distance = std::abs(centroid(0) - elem->point(p)(0)); 00243 max_distance = std::max(distance, max_distance); 00244 } 00245 } 00246 00247 // Using static globals for old_elem_id, etc. will fail 00248 // horribly with more than one thread. 00249 libmesh_assert_equal_to (libMesh::n_threads(), 1); 00250 00251 const Real x = point_in(0); 00252 const Real xc = centroid(0); 00253 const Real dx = (x - xc)/max_distance; 00254 const Real dist2 = pow(max_distance,2.); 00255 00256 // monomials. since they are hierarchic we only need one case block. 00257 switch (i) 00258 { 00259 case 0: 00260 case 1: 00261 return 0.; 00262 00263 case 2: 00264 return 2./dist2; 00265 00266 case 3: 00267 return 6.*dx/dist2; 00268 00269 case 4: 00270 return 12.*dx*dx/dist2; 00271 00272 default: 00273 Real val = 2.; 00274 for (unsigned int index = 2; index != i; ++index) 00275 val *= (index+1) * dx; 00276 return val/dist2; 00277 } 00278 00279 libmesh_error_msg("We'll never get here!"); 00280 return 0.; 00281 } 00282 00283 } // namespace libMesh