GaussianQuadratureRule.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include <cmath>
00037 
00038 #include "GaussianQuadratureRule.hpp"
00039 #include "Exception.hpp"
00040 #include "UblasCustomFunctions.hpp"
00041 
00042 template<unsigned ELEMENT_DIM>
00043 const ChastePoint<ELEMENT_DIM>& GaussianQuadratureRule<ELEMENT_DIM>::rGetQuadPoint(unsigned index) const
00044 {
00045     assert(index < mNumQuadPoints);
00046     return mPoints[index];
00047 }
00048 
00049 template<unsigned ELEMENT_DIM>
00050 double GaussianQuadratureRule<ELEMENT_DIM>::GetWeight(unsigned index) const
00051 {
00052     assert(index < mNumQuadPoints);
00053     return mWeights[index];
00054 }
00055 
00056 template<unsigned ELEMENT_DIM>
00057 unsigned GaussianQuadratureRule<ELEMENT_DIM>::GetNumQuadPoints() const
00058 {
00059     return mNumQuadPoints;
00060 }
00061 
00067 template<>
00068 GaussianQuadratureRule<0>::GaussianQuadratureRule(unsigned quadratureOrder)
00069 {
00070     mNumQuadPoints = 1;
00071     mWeights.push_back(1);
00072     mPoints.push_back(ChastePoint<0>());
00073 }
00074 
00080 template<>
00081 GaussianQuadratureRule<1>::GaussianQuadratureRule(unsigned quadratureOrder)
00082 {
00083     switch (quadratureOrder)
00084     {
00085         case 0:
00086         case 1: // 1d, 1st order
00087                 // 1 point rule
00088             mWeights.push_back(1);
00089             mPoints.push_back(ChastePoint<1>(0.5));
00090             break;
00091         case 2:
00092         case 3: // 1d, 3rd order
00093                 // 2 point rule
00094             mWeights.push_back(0.5);
00095             mWeights.push_back(0.5);
00096             {
00097                 double sqrt_one_third = sqrt(1.0/3.0);
00098                 mPoints.push_back(ChastePoint<1>((-sqrt_one_third+1.0)/2.0));
00099                 mPoints.push_back(ChastePoint<1>((sqrt_one_third+1.0)/2.0));
00100             }
00101             break;
00102         case 4:
00103         case 5: // 1d, 5th order
00104                 // 3 point rule
00105             mWeights.push_back(5.0/18.0);
00106             mWeights.push_back(4.0/9.0);
00107             mWeights.push_back(5.0/18.0);
00108 
00109             {
00110                 double sqrt_three_fifths = sqrt(3.0/5.0);
00111                 mPoints.push_back(ChastePoint<1>((-sqrt_three_fifths+1.0)/2.0));
00112                 mPoints.push_back(ChastePoint<1>(0.5));
00113                 mPoints.push_back(ChastePoint<1>((sqrt_three_fifths+1.0)/2.0));
00114             }
00115             break;
00116          default:
00117             EXCEPTION("Gauss quadrature order not supported.");
00118     }
00119     assert(mPoints.size() == mWeights.size());
00120     mNumQuadPoints = mPoints.size();
00121 }
00122 
00129 template<>
00130 GaussianQuadratureRule<2>::GaussianQuadratureRule(unsigned quadratureOrder)
00131 {
00132     double one_third = 1.0/3.0;
00133     double one_sixth = 1.0/6.0;
00134     double two_thirds = 2.0/3.0;
00135     switch (quadratureOrder)
00136     {
00137         case 0: // 2d, 0th order
00138         case 1: // 2d, 1st order
00139                 // 1 point rule
00140             mWeights.push_back(0.5);
00141             mPoints.push_back(ChastePoint<2>(one_third, one_third));
00142             break;
00143 
00144         case 2: // 2d, 2nd order
00145                 // 3 point rule
00146             mWeights.push_back(one_sixth);
00147             mWeights.push_back(one_sixth);
00148             mWeights.push_back(one_sixth);
00149 
00150             mPoints.push_back(ChastePoint<2>(two_thirds, one_sixth));
00151             mPoints.push_back(ChastePoint<2>(one_sixth,  one_sixth));
00152             mPoints.push_back(ChastePoint<2>(one_sixth,  two_thirds));
00153             break;
00154 
00155         case 3: // 2d, 3rd order - derived by hand and using a Macsyma script to solve the cubic
00156                 //                60*x^3  - 60*x^2  + 15*x - 1;
00157                 // 6 point rule
00158             {
00159                 double w = 1.0/12.0;
00160                 mWeights.push_back(w);
00161                 mWeights.push_back(w);
00162                 mWeights.push_back(w);
00163                 mWeights.push_back(w);
00164                 mWeights.push_back(w);
00165                 mWeights.push_back(w);
00166 
00167                 double inverse_tan = atan(0.75);
00168                 double cos_third = cos(inverse_tan/3.0);
00169                 double sin_third = sin(inverse_tan/3.0);
00170                 // a = 0.23193336461755
00171                 double a =   sin_third/(2*sqrt(3.0)) - cos_third/6.0 + 1.0/3.0;
00172                 // b = 0.10903901046622
00173                 double b = - sin_third/(2*sqrt(3.0)) - cos_third/6.0 + 1.0/3.0;
00174                 // c = 0.659028
00175                 double c = cos_third/3.0 + 1.0/3.0;
00176 
00177                 mPoints.push_back(ChastePoint<2>(a, b));
00178                 mPoints.push_back(ChastePoint<2>(a, c));
00179                 mPoints.push_back(ChastePoint<2>(b, a));
00180                 mPoints.push_back(ChastePoint<2>(b, c));
00181                 mPoints.push_back(ChastePoint<2>(c, a));
00182                 mPoints.push_back(ChastePoint<2>(c, b));
00183             }
00184             break;
00185         default:
00186             EXCEPTION("Gauss quadrature order not supported.");
00187     }
00188     assert(mPoints.size() == mWeights.size());
00189     mNumQuadPoints = mPoints.size();
00190 }
00191 
00197 template<>
00198 GaussianQuadratureRule<3>::GaussianQuadratureRule(unsigned quadratureOrder)
00199 {
00200     switch (quadratureOrder)
00201     {
00202         case 0: // 3d, 0th order
00203         case 1: // 3d, 1st order
00204                 // 1 point rule
00205             mWeights.push_back(1.0/6.0);
00206             mPoints.push_back(ChastePoint<3>(0.25, 0.25, 0.25));
00207             break;
00208 
00209         case 2: //2nd order
00210                 // 4 point rule
00211             {
00212                 double sqrt_fifth = 1.0/sqrt(5.0);
00213                 double a = (1.0 + 3.0*sqrt_fifth)/4.0; //0.585410196624969;
00214                 double b = (1.0 - sqrt_fifth)/4.0; //0.138196601125011;
00215                 double w = 1.0/24.0;
00216 
00217                 mWeights.push_back(w);
00218                 mWeights.push_back(w);
00219                 mWeights.push_back(w);
00220                 mWeights.push_back(w);
00221 
00222                 mPoints.push_back(ChastePoint<3>(a,b,b));
00223                 mPoints.push_back(ChastePoint<3>(b,a,b));
00224                 mPoints.push_back(ChastePoint<3>(b,b,a));
00225                 mPoints.push_back(ChastePoint<3>(b,b,b));
00226             }
00227             break;
00228 
00229         case 3: // 3d, 3rd order
00230             // 8 point rule
00231             /* The main options were
00232              *  5-point rule.  Commonly published rule has four symmetric points and
00233              *                 a negative weight in the centre.  We would like to avoid
00234              *                 negative weight (certainly for interpolation.
00235              *  8-point rule.  Uses two sets of symmetric points (as 4 point rule with a,b and then with c,d).
00236              *                 This one is hard to derive a closed form solution to.
00237              */
00238             {
00239                 double root_seventeen = sqrt(17.0);
00240                 double root_term = sqrt(1022.0-134.0*root_seventeen);
00241                 double b = (55.0 - 3.0*root_seventeen + root_term)/196; //b = 0.328055
00242                 double d = (55.0 - 3.0*root_seventeen - root_term)/196; //d = 0.106952
00243 
00244                 double a = 1.0 - 3.0*b; // a = 0.0158359
00245                 double c = 1.0 - 3.0*d; // c = 0.679143
00246 
00247                 // w1 = 0.023088 (= 0.138528/6)
00248                 double w1 = (20.0*d*d - 10.0*d + 1.0)/(240.0*(2.0*d*d - d - 2.0*b*b + b)); // w1 = 0.0362942
00249                 double w2 = 1.0/24.0 - w1; // w2 = 0.0185787 (=0.111472/6)
00250 
00251                 mWeights.push_back(w1);
00252                 mWeights.push_back(w1);
00253                 mWeights.push_back(w1);
00254                 mWeights.push_back(w1);
00255 
00256                 mWeights.push_back(w2);
00257                 mWeights.push_back(w2);
00258                 mWeights.push_back(w2);
00259                 mWeights.push_back(w2);
00260 
00261                 mPoints.push_back(ChastePoint<3>(a, b, b));
00262                 mPoints.push_back(ChastePoint<3>(b, a, b));
00263                 mPoints.push_back(ChastePoint<3>(b, b, a));
00264                 mPoints.push_back(ChastePoint<3>(b, b, b));
00265 
00266                 mPoints.push_back(ChastePoint<3>(c, d, d));
00267                 mPoints.push_back(ChastePoint<3>(d, c, d));
00268                 mPoints.push_back(ChastePoint<3>(d, d, c));
00269                 mPoints.push_back(ChastePoint<3>(d, d, d));
00270 
00271             }
00272 break;
00273 
00274         default:
00275             EXCEPTION("Gauss quadrature order not supported.");
00276     }
00277     assert(mPoints.size() == mWeights.size());
00278     mNumQuadPoints = mPoints.size();
00279 }
00280 
00281 template<unsigned ELEMENT_DIM>
00282 GaussianQuadratureRule<ELEMENT_DIM>::GaussianQuadratureRule(unsigned quadratureOrder)
00283 {
00284     EXCEPTION("Gauss quadrature rule not available for this dimension.");
00285 }
00286 
00288 // Explicit instantiation
00290 
00291 template class GaussianQuadratureRule<0>;
00292 template class GaussianQuadratureRule<1>;
00293 template class GaussianQuadratureRule<2>;
00294 template class GaussianQuadratureRule<3>;
00295 template class GaussianQuadratureRule<4>;

Generated by  doxygen 1.6.2