MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/numerical/quadrature.h
Go to the documentation of this file.
00001 /************************************************************************
00002  * MechSys - Open Library for Mechanical Systems                        *
00003  * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand                   *
00004  * Copyright (C) 2009 Sergio Galindo                                    *
00005  *                                                                      *
00006  * This program is free software: you can redistribute it and/or modify *
00007  * it under the terms of the GNU General Public License as published by *
00008  * the Free Software Foundation, either version 3 of the License, or    *
00009  * any later version.                                                   *
00010  *                                                                      *
00011  * This program is distributed in the hope that it will be useful,      *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
00014  * GNU General Public License for more details.                         *
00015  *                                                                      *
00016  * You should have received a copy of the GNU General Public License    *
00017  * along with this program. If not, see <http://www.gnu.org/licenses/>  *
00018  ************************************************************************/
00019 
00020 #ifndef MECHSYS_QUADRATURE_H
00021 #define MECHSYS_QUADRATURE_H
00022 
00023 // STL
00024 #include <cmath>
00025 #include <cfloat> // for DBL_EPSILON
00026 
00027 // GSL
00028 #include <gsl/gsl_integration.h>
00029 
00030 namespace Numerical
00031 {
00032 
00034 enum QMethod
00035 {
00036     QNG_T, 
00037     QAGS_T 
00038 };
00039 
00044 template<typename Instance>
00045 class Quadrature
00046 {
00047 public:
00048     // Constants
00049     static int WORKSPACE_SIZE; 
00050 
00051     // Typedefs
00052     typedef double (Instance::*pFun) (double x) const; 
00053 
00055      Quadrature (Instance const * p2Inst, pFun p2Fun, QMethod method=QAGS_T,double EPSREL=100.0*DBL_EPSILON); // p2Fun == &F(x)
00056 
00058     ~Quadrature ();
00059 
00060     // Methods
00061     double Integrate (double a, double b);                          
00062     double CallFun   (double x)   { return (_p2inst->*_p2fun)(x); } 
00063     double LastError () const     { return _last_error;           } 
00064 
00065 private:
00066     Instance const            * _p2inst;     
00067     pFun                        _p2fun;      
00068     QMethod                     _method;     
00069     gsl_integration_workspace * _workspace;  
00070     double                      _epsabs;     
00071     double                      _epsrel;     
00072     double                      _last_error; 
00073     size_t                      _last_neval; 
00074 
00075 }; // class Quadrature
00076 
00077 template<typename Instance>
00078 int Quadrature<Instance>::WORKSPACE_SIZE = 10000;
00079 
00084 template<typename Instance>
00085 double __quadrature_call_fun__(double x, void *not_used_for_params)
00086 {
00087     Quadrature<Instance> * p2inst = static_cast<Quadrature<Instance>*>(not_used_for_params);
00088     return p2inst->CallFun(x);
00089 
00090 }
00091 
00092 
00094 
00095 
00096 template<typename Instance>
00097 inline Quadrature<Instance>::Quadrature(Instance const * p2Inst, pFun p2Fun, QMethod method, double EPSREL)
00098     : _p2inst     (p2Inst),
00099       _p2fun      (p2Fun),
00100       _method     (method),
00101       _epsabs     (EPSREL),
00102       _epsrel     (EPSREL),
00103       _last_error (-1),
00104       _last_neval (-1)
00105 {
00106     /* Each algorithm computes an approximation to a definite integral of the form,
00107      * 
00108      *      I = \int_a^b f(x) w(x) dx
00109      * 
00110      * where w(x) is a weight function (for general integrands w(x)=1).
00111      *
00112      * The algorithms are built on pairs of quadrature rules, a higher order
00113      * rule and a lower order rule.  The higher order rule is used to compute
00114      * the best approximation to an integral over a small range.  The
00115      * difference between the results of the higher order rule and the lower
00116      * order rule gives an estimate of the error in the approximation.
00117      *
00118      * The user provides absolute and relative error bounds (epsabs, epsrel) which
00119      * specify the following accuracy requirement
00120      * 
00121      *      |RESULT - I|  <= max(epsabs, epsrel |I|)
00122      * 
00123      * where RESULT is the numerical approximation obtained by the algorithm.
00124      *
00125      * The algorithms attempt to estimate the absolute error 
00126      * ABSERR = |RESULT - I| in such a way that the following inequality holds,
00127      * 
00128      *      |RESULT - I| <= ABSERR <= max(epsabs, epsrel |I|)
00129      * 
00130      * The routines will fail to converge if the error bounds are too
00131      * stringent, but always return the best approximation obtained up to that
00132      * stage.
00133      * 
00134      *    The algorithms in QUADPACK use a naming convention based on the
00135      * following letters,
00136      * 
00137      *      `Q' - quadrature routine
00138      * 
00139      *      `N' - non-adaptive integrator
00140      *      `A' - adaptive integrator
00141      * 
00142      *      `G' - general integrand (user-defined)
00143      *      `W' - weight function with integrand
00144      * 
00145      *      `S' - singularities can be more readily integrated
00146      *      `P' - points of special difficulty can be supplied
00147      *      `I' - infinite range of integration
00148      *      `O' - oscillatory weight function, cos or sin
00149      *      `F' - Fourier integral
00150      *      `C' - Cauchy principal value
00151      */
00152 
00153     _workspace = gsl_integration_workspace_alloc (WORKSPACE_SIZE);
00154 }
00155 
00156 template<typename Instance>
00157 inline Quadrature<Instance>::~Quadrature()
00158 {
00159     if (_workspace!=NULL) gsl_integration_workspace_free (_workspace);
00160 }
00161 
00162 template<typename Instance>
00163 inline double Quadrature<Instance>::Integrate(double a, double b)
00164 {
00165     // Function
00166     gsl_function f;
00167     f.function = &__quadrature_call_fun__<Instance>;
00168     f.params   = this;
00169 
00170     // Solve
00171     double result;
00172     switch (_method)
00173     {
00174         case QNG_T:
00175         {
00176             /* QNG non-adaptive Gauss-Kronrod integration
00177              *
00178              * The QNG algorithm is a non-adaptive procedure which uses fixed Gauss-Kronrod abscissae to sample the integrand at a
00179              * maximum of 87 points. It is provided for fast integration of smooth functions.
00180              *
00181              * Function: int gsl_integration_qng (const gsl_function * F, double A, double B, double EPSABS, double EPSREL,
00182              * double * RESULT, double * ABSERR, size_t * NEVAL)
00183              *
00184              * This function applies the Gauss-Kronrod 10-point, 21-point, 43-point and 87-point integration rules in succession
00185              * until an estimate of the integral of f over (a,b) is achieved within the desired absolute and relative error limits,
00186              * EPSABS and EPSREL. The function returns the final approximation, RESULT, an estimate of the absolute error, ABSERR
00187              * and the number of function evaluations used, NEVAL.  The Gauss-Kronrod rules are designed in such a way that each
00188              * rule uses all the results of its predecessors, in order to minimize the total number of function evaluations.
00189              */
00190 
00191             gsl_integration_qng (&f, a, b, _epsabs, _epsrel, &result, &_last_error, &_last_neval);
00192 
00193             break;
00194         }
00195         case QAGS_T:
00196         {
00197             /* QAGS adaptive integration with singularities
00198              *
00199              * The presence of an integrable singularity in the integration region causes an adaptive routine to concentrate new
00200              * subintervals around the singularity. As the subintervals decrease in size the successive approximations to the integral
00201              * converge in a limiting fashion. This approach to the limit can be accelerated using an extrapolation procedure. The
00202              * QAGS algorithm combines adaptive bisection with the Wynn epsilon-algorithm to speed up the integration of many types of
00203              * integrable singularities.
00204              *
00205              * Function: int gsl_integration_qags (const gsl_function * f, double a, double b, double epsabs, double epsrel, size_t
00206              * limit, gsl_integration_workspace * workspace, double * result, double * abserr)
00207              *
00208              * This function applies the Gauss-Kronrod 21-point integration rule adaptively until an estimate of the integral of f
00209              * over (a,b) is achieved within the desired absolute and relative error limits, epsabs and epsrel. The results are
00210              * extrapolated using the epsilon-algorithm, which accelerates the convergence of the integral in the presence of
00211              * discontinuities and integrable singularities. The function returns the final approximation from the extrapolation,
00212              * result, and an estimate of the absolute error, abserr. The subintervals and their results are stored in the memory
00213              * provided by workspace. The maximum number of subintervals is given by limit, which may not exceed the allocated size of
00214              * the workspace. 
00215              */
00216 
00217             gsl_integration_qags (&f, a, b, _epsabs, _epsrel, WORKSPACE_SIZE, _workspace, &result, &_last_error); 
00218 
00219             break;
00220         }
00221     };
00222 
00223     // Results
00224     return result;
00225 }
00226 
00227 }; // namespace Numerical
00228 
00229 #endif // MECHSYS_QUADRATURE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines