All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
inte_adapt_cern.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2014, Andrew W. Steiner
5 
6  This file is part of O2scl.
7 
8  O2scl is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  O2scl is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
20 
21  -------------------------------------------------------------------
22 */
23 /** \file inte_adapt_cern.h
24  \brief File defining \ref o2scl::inte_adapt_cern
25 */
26 #ifndef O2SCL_CERN_ADAPT_H
27 #define O2SCL_CERN_ADAPT_H
28 
29 #include <o2scl/inte.h>
30 #include <o2scl/inte_gauss56_cern.h>
31 #include <o2scl/string_conv.h>
32 
33 #ifndef DOXYGEN_NO_O2NS
34 namespace o2scl {
35 #endif
36 
37  /** \brief Adaptive integration (CERNLIB)
38 
39  Uses a base integration object (default is \ref inte_gauss56_cern) to
40  perform adaptive integration by automatically subdividing the
41  integration interval. At each step, the interval with the
42  largest absolute uncertainty is divided in half. The routine
43  succeeds if the absolute tolerance is less than \ref tol_abs or
44  if the relative tolerance is less than \ref tol_rel, i.e.
45  \f[
46  \mathrm{err}\leq\mathrm{tol\_abs}~\mathrm{or}~
47  \mathrm{err}\leq\mathrm{tol\_rel}\cdot|I|
48  \f]
49  where \f$ I \f$ is the current estimate for the integral and \f$
50  \mathrm{err} \f$ is the current estimate for the uncertainty. If
51  the number of subdivisions exceeds the template parameter \c
52  nsub, the error handler is called, since the integration may not
53  have been successful. The number of subdivisions used in the
54  last integration can be obtained from get_nsubdivisions().
55 
56  The template parameter \c nsub, is the maximum number of
57  subdivisions. It is automatically set to 100 in the original
58  CERNLIB routine, and defaults to 100 here. The default base
59  integration object is of type \ref inte_gauss56_cern. This is the
60  CERNLIB default, but can be modified by calling set_inte().
61 
62  This class is based on the CERNLIB routines RADAPT and
63  DADAPT which are documented at
64  http://wwwasdoc.web.cern.ch/wwwasdoc/shortwrupsdir/d102/top.html
65 
66  \future
67  - Allow user to set the initial subdivisions?
68  - It might be interesting to directly compare the performance
69  of this class to \ref o2scl::inte_qag_gsl .
70  - There is a fixme entry in the code which could be resolved.
71  - Output the point where most subdividing was required?
72  */
73  template<class func_t=funct11, size_t nsub=100>
74  class inte_adapt_cern : public inte<func_t> {
75 
76 #ifndef DOXYGEN_INTERNAL
77 
78  protected:
79 
80  /// Lower end of subdivision
81  double xlo[nsub];
82 
83  /// High end of subdivision
84  double xhi[nsub];
85 
86  /// Value of integral for subdivision
87  double tval[nsub];
88 
89  /// Squared error for subdivision
90  double ters[nsub];
91 
92  /// Previous number of subdivisions
94 
95  /// The base integration object
97 
98 #endif
99 
100  public:
101 
102  inte_adapt_cern() {
103  nsubdiv=1;
104  prev_subdiv=0;
105 
106  it=&def_inte;
107  }
108 
109  /// \name Basic usage
110  //@{
111  /** \brief Integrate function \c func from \c a to \c b
112  giving result \c res and error \c err
113  */
114  virtual int integ_err(func_t &func, double a, double b,
115  double &res, double &err) {
116 
117  double tvals=0.0, terss, xlob, xhib, yhib=0.0, te, root=0.0;
118  int i, nsubdivd;
119 
120  if (nsubdiv==0) {
121  if (prev_subdiv==0) {
122  // If the previous binning was requested, but
123  // there is no previous binning stored, then
124  // just shift to automatic binning
125  nsubdivd=1;
126  } else {
127  tvals=0.0;
128  terss=0.0;
129  for(i=0;i<prev_subdiv;i++) {
130  it->integ_err(func,xlo[i],xhi[i],tval[i],te);
131  ters[i]=te*te;
132  tvals+=tval[i];
133  terss+=ters[i];
134  }
135  err=sqrt(2.0*terss);
136  res=tvals;
137  return 0;
138  }
139  }
140 
141  // Ensure we're not asking for too many divisions
142  if (nsub<nsubdiv) {
143  nsubdivd=nsub;
144  } else {
145  nsubdivd=nsubdiv;
146  }
147 
148  // Compute the initial set of intervals and integral values
149  xhib=a;
150  double bin=(b-a)/((double)nsubdivd);
151  for(i=0;i<nsubdivd;i++) {
152  xlo[i]=xhib;
153  xlob=xlo[i];
154  xhi[i]=xhib+bin;
155  if (i==nsubdivd-1) xhi[i]=b;
156  xhib=xhi[i];
157  it->integ_err(func,xlob,xhib,tval[i],te);
158  ters[i]=te*te;
159  }
160  prev_subdiv=nsubdivd;
161 
162  for(size_t iter=1;iter<=nsub;iter++) {
163 
164  // Compute the total value of the integrand
165  // and the squared uncertainty
166  tvals=tval[0];
167  terss=ters[0];
168  for(i=1;i<prev_subdiv;i++) {
169  tvals+=tval[i];
170  terss+=ters[i];
171  }
172 
173  // Output iteration information
174  if (this->verbose>0) {
175  std::cout << "inte_adapt_cern Iter: " << iter;
176  std::cout.setf(std::ios::showpos);
177  std::cout << " Res: " << tvals;
178  std::cout.unsetf(std::ios::showpos);
179  std::cout << " Err: " << sqrt(2.0*terss);
180  if (this->tol_abs>this->tol_rel*fabs(tvals)) {
181  std::cout << " Tol: " << this->tol_abs << std::endl;
182  } else {
183  std::cout << " Tol: " << this->tol_rel*fabs(tvals) << std::endl;
184  }
185  if (this->verbose>1) {
186  char ch;
187  std::cout << "Press a key and type enter to continue. " ;
188  std::cin >> ch;
189  }
190  }
191 
192  // See if we're finished
193  root=sqrt(2.0*terss);
194  if (root<=this->tol_abs || root<=this->tol_rel*fabs(tvals)) {
195  res=tvals;
196  err=root;
197  this->last_iter=iter;
198  return 0;
199  }
200 
201  // Test if we've run out of intervals
202  if (prev_subdiv==nsub) {
203  res=tvals;
204  err=root;
205  this->last_iter=iter;
206  std::string s="Reached maximum number ("+itos(nsub)+
207  ") of subdivisions in inte_adapt_cern::integ_err().";
208  O2SCL_CONV_RET(s.c_str(),exc_etable,this->err_nonconv);
209  }
210 
211  // Find the subdivision with the largest error
212  double bige=ters[0];
213  int ibig=0;
214  for(i=1;i<prev_subdiv;i++) {
215  if (ters[i]>bige) {
216  bige=ters[i];
217  ibig=i;
218  }
219  }
220 
221  // Subdivide that subdivision further
222  xhi[prev_subdiv]=xhi[ibig];
223  double xnew=(xlo[ibig]+xhi[ibig])/2.0;
224  xhi[ibig]=xnew;
225  xlo[prev_subdiv]=xnew;
226  it->integ_err(func,xlo[ibig],xhi[ibig],tval[ibig],te);
227  ters[ibig]=te*te;
228  it->integ_err(func,xlo[prev_subdiv],
229  xhi[prev_subdiv],tval[prev_subdiv],te);
230  ters[prev_subdiv]=te*te;
231  prev_subdiv++;
232 
233  }
234 
235  // FIXME: Should we set an error here, or does this
236  // only happen if we happen to need exactly nsub
237  // intervals?
238  res=tvals;
239  err=root;
240  return 0;
241  }
242  //@}
243 
244  /// \name Integration object
245  //@{
246  /// Set the base integration object to use
248  it=&i;
249  return 0;
250  }
251 
252  /// Default integration object
254  //@}
255 
256  /// \name Subdivisions
257  //@{
258  /** \brief Number of subdivisions
259 
260  The options are
261  - 0: Use previous binning and do not subdivide further \n
262  - 1: Automatic - adapt until tolerance is attained (default) \n
263  - n: (n>1) split first in n equal subdivisions, then adapt
264  until tolerance is obtained.
265  */
266  size_t nsubdiv;
267 
268  /// Return the number of subdivisions used in the last integration
269  size_t get_nsubdivisions() {
270  return prev_subdiv;
271  }
272 
273  /// Return the ith subdivision
274  int get_ith_subdivision(size_t i, double &xlow, double &xhigh,
275  double &value, double &errsq) {
276  if (i<prev_subdiv) {
277  xlow=xlo[i];
278  xhigh=xhi[i];
279  value=tval[i];
280  errsq=ters[i];
281  }
282  return 0;
283  }
284 
285  /// Return all of the subdivisions
286  template<class vec_t>
287  int get_subdivisions(vec_t &xlow, vec_t &xhigh, vec_t &value,
288  vec_t &errsq) {
289 
290  for(int i=0;i<prev_subdiv;i++) {
291  xlow[i]=xlo[i];
292  xhigh[i]=xhi[i];
293  value[i]=tval[i];
294  errsq[i]=ters[i];
295  }
296  return 0;
297  }
298  //@}
299 
300  };
301 
302 #ifndef DOXYGEN_NO_O2NS
303 }
304 #endif
305 
306 #endif
inte_gauss56_cern< func_t > def_inte
Default integration object.
int prev_subdiv
Previous number of subdivisions.
#define O2SCL_CONV_RET(d, n, b)
Set a "convergence" error and return the error value.
Definition: err_hnd.h:292
double xhi[nsub]
High end of subdivision.
virtual int integ_err(func_t &func, double a, double b, double &res, double &err)
Integrate function func from a to b giving result res and error err.
Adaptive integration (CERNLIB)
inte< func_t > * it
The base integration object.
size_t last_iter
The most recent number of iterations taken.
Definition: inte.h:63
bool err_nonconv
If true, call the error handler if the routine does not converge or reach the desired tolerance (defa...
Definition: inte.h:81
table table limit exceeded
Definition: err_hnd.h:103
size_t get_nsubdivisions()
Return the number of subdivisions used in the last integration.
double tol_abs
The maximum absolute uncertainty in the value of the integral (default )
Definition: inte.h:73
int get_ith_subdivision(size_t i, double &xlow, double &xhigh, double &value, double &errsq)
Return the ith subdivision.
One-dimensional solver [abstract base].
Definition: root.h:46
Base integration class [abstract base].
Definition: inte.h:44
5,6-point Gaussian quadrature (CERNLIB)
int set_inte(inte< func_t > &i)
Set the base integration object to use.
double ters[nsub]
Squared error for subdivision.
double tval[nsub]
Value of integral for subdivision.
size_t nsubdiv
Number of subdivisions.
double xlo[nsub]
Lower end of subdivision.
double tol_rel
The maximum relative uncertainty in the value of the integral (default )
Definition: inte.h:68
std::string itos(int x)
Convert an integer to a string.
int verbose
Verbosity.
Definition: inte.h:60
int get_subdivisions(vec_t &xlow, vec_t &xhigh, vec_t &value, vec_t &errsq)
Return all of the subdivisions.

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).
Hosted at Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads..