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