![]() |
Object-oriented Scientific Computing Library: Version 0.910
|
Several classes integrate arbitrary one-dimensional functions
cos(x)
or sin(x)
: gsl_inte_qawo_cos and gsl_inte_qawo_sin
All of these classes are children of inte, and the relative and absolute tolerances are stored in inte::tol_rel and inte::tol_abs, respectively.
For the GSL-based integration routines, the variables inte::tol_abs and inte::tol_rel have the same role as the quantities usually denoted in the GSL integration routines by epsabs
and epsrel
. In particular, the integration classes attempt to ensure that
and returns an error to attempt to ensure that
where I
is the integral to be evaluated. Even when the corresponding descendant of inte::integ() returns success, these inequalities may fail for sufficiently difficult functions. All of the GSL integration routines except for gsl_inte_qng use a workspace given in gsl_inte_table which holds the results of the various subdivisions of the original interval. The size of this workspace (and thus then number of subdivisions) can be controlled with gsl_inte_table::set_wkspace().
The GSL routines were originally based on QUADPACK, which is available at http://www.netlib.org/quadpack .
For adaptive GSL integration classes, the type of Gauss-Kronrod quadrature rule that is used to approximate the integral and estimate the error of a subinterval is set by gsl_inte_kronrod::set_rule().
There are two competing factors that can slow down an adaptive integration algorithm: (1) each evaluation of the integrand can be numerically expensive, depending on how the function is defined, and (2) the process of subdividing regions and recalculating values is almost always numerically expensive in its own right. For integrands that are very smooth (e.g., analytic functions), a high-order Gauss-Kronrod rule (e.g., 61-point) will achieve the desired error tolerance with relatively few subdivisions. For integrands with discontinuities or singular derivatives, a low-order rule (e.g., 15-point) is often more efficient.
The number of subdivisions of the integration region is limited by the size of the workspace, set in gsl_inte_kronrod::set_limit(). The number of subdivisions required for the most recent call to inte::integ() or inte::integ_err() is given in inte::last_iter. This number will always be less than or equal to the workspace size.
The error messages given by the adaptive GSL integration routines tend to follow a standard form and are documented here. There are several error messages which indicate improper usage and cause the error handler to be called regardless of the value of inte::err_nonconv :
"Iteration limit exceeds workspace in
class::function()."
[gsl_einval]"Could not integrate function in class::function() (it
may have returned a non-finite result)."
[gsl_efailed] This often occurs when the user-specified function returns inf
or nan
."Tolerance cannot be achieved with given value of tol_abs
and tol_rel in class::function()."
[gsl_ebadtol] "Cannot integrate with singularity on endpoint in
gsl_inte_qawc::qawc()."
[gsl_einval] The class gsl_inte_qawc cannot handle the case when a singularity is one of the endpoints of the integration.There are also convergence errors which will call the error handler unless inte::err_nonconv is false:
"Cannot reach tolerance because of roundoff error on first
attempt in class::function()."
[gsl_eround] "A maximum of 1 iteration was insufficient in
class::function()."
[gsl_emaxiter] "Bad integrand behavior in class::function()."
[gsl_esing] "Maximum number of subdivisions 'value' reached in
class::function()."
[gsl_emaxiter] "Roundoff error prevents tolerance from being achieved in
class::function()."
[gsl_eround] "Roundoff error detected in extrapolation table in
gsl_inte_singular::qags()."
[gsl_eround] "Integral is divergent or slowly convergent in
gsl_inte_singular::qags()."
[gsl_ediverge] "Exceeded limit of trigonometric table in
gsl_inte_qawo_sin()::qawo()."
[gsl_etable] Multi-dimensional hypercubic integration is performed by composite_inte, the sole descendant of multi_inte. composite_inte allows you to specify a set of one-dimensional integration routines (objects of type inte) and apply them to a multi-dimensional problem.
General multi-dimensional integration is performed by comp_gen_inte, the sole descendant of gen_inte. The user is allowed to specify a upper and lower limits which are functions of the variables for integrations which have not yet been performed, i.e. the n-dimensional integral
Again, one specifies a set of inte objects to apply to each variable to be integrated over.
Monte Carlo integration is also provided (see Monte Carlo Integration).
This example computes the integral with gsl_inte_qagi, the integral
with gsl_inte_qagiu, the integral
with gsl_inte_qagil, and the integral
with both gsl_inte_qag and cern_adapt, and compares the computed results with the exact results.
/* Example: ex_inte.cpp ------------------------------------------------------------------- An example to demonstrate numerical integration. */ #include <cmath> #include <o2scl/test_mgr.h> #include <o2scl/constants.h> #include <o2scl/funct.h> #include <o2scl/gsl_inte_qag.h> #include <o2scl/gsl_inte_qagi.h> #include <o2scl/gsl_inte_qagiu.h> #include <o2scl/gsl_inte_qagil.h> #include <o2scl/cern_adapt.h> using namespace std; using namespace o2scl; using namespace o2scl_const; class cl { public: // We'll use this to count the number of function // evaulations required by the integration routines int nf; // A function to be integrated double integrand(double x) { nf++; return exp(-x*x); } // Another function to be integrated double integrand2(double x) { nf++; return sin(2.0*x)+0.5; } }; int main(void) { cl acl; test_mgr t; t.set_output_level(1); funct_mfptr<cl> f1(&acl,&cl::integrand); funct_mfptr<cl> f2(&acl,&cl::integrand2); // We don't need to specify the function type in the integration // objects, because we're using the default function type (type // funct). gsl_inte_qag<> g; gsl_inte_qagi<> gi; gsl_inte_qagiu<> gu; gsl_inte_qagil<> gl; cern_adapt<> ca; // The result and the uncertainty double res, err; // An integral from -infinity to +infinity (the limits are ignored) acl.nf=0; int ret1=gi.integ_err(f1,0.0,0.0,res,err); cout << "gsl_inte_qagi: " << endl; cout << "Return value: " << ret1 << endl; cout << "Result: " << res << " Uncertainty: " << err << endl; cout << "Number of iterations: " << gi.last_iter << endl; cout << "Number of function evaluations: " << acl.nf << endl; cout << endl; t.test_rel(res,sqrt(pi),1.0e-8,"inte 1"); // An integral from 0 to +infinity (the second limit argument is // ignored in the line below) acl.nf=0; gu.integ_err(f1,0.0,0.0,res,err); cout << "gsl_inte_qagiu: " << endl; cout << "Return value: " << ret1 << endl; cout << "Result: " << res << " Uncertainty: " << err << endl; cout << "Number of iterations: " << gu.last_iter << endl; cout << "Number of function evaluations: " << acl.nf << endl; cout << endl; t.test_rel(res,sqrt(pi)/2.0,1.0e-8,"inte 2"); // An integral from -infinity to zero (the first limit argument is // ignored in the line below) acl.nf=0; gl.integ_err(f1,0.0,0.0,res,err); cout << "gsl_inte_qagil: " << endl; cout << "Return value: " << ret1 << endl; cout << "Result: " << res << " Uncertainty: " << err << endl; cout << "Number of iterations: " << gl.last_iter << endl; cout << "Number of function evaluations: " << acl.nf << endl; cout << endl; t.test_rel(res,sqrt(pi)/2.0,1.0e-8,"inte 3"); // An integral from 0 to 1 with the GSL integrator acl.nf=0; g.integ_err(f2,0.0,1.0,res,err); cout << "gsl_inte_qag: " << endl; cout << "Return value: " << ret1 << endl; cout << "Result: " << res << " Uncertainty: " << err << endl; cout << "Number of iterations: " << g.last_iter << endl; cout << "Number of function evaluations: " << acl.nf << endl; cout << endl; t.test_rel(res,0.5+sin(1.0)*sin(1.0),1.0e-8,"inte 4"); // The same integral with the CERNLIB integrator acl.nf=0; ca.integ_err(f2,0.0,1.0,res,err); cout << "cern_adapt: " << endl; cout << "Return value: " << ret1 << endl; cout << "Result: " << res << " Uncertainty: " << err << endl; cout << "Number of iterations: " << ca.last_iter << endl; cout << "Number of function evaluations: " << acl.nf << endl; cout << endl; t.test_rel(res,0.5+sin(1.0)*sin(1.0),1.0e-8,"inte 5"); t.report(); return 0; } // End of example
Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).