All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
inte_qawf_gsl.h
Go to the documentation of this file.
1 /*
2  -------------------------------------------------------------------
3 
4  Copyright (C) 2006-2014, Jerry Gagelman
5  and Andrew W. Steiner
6 
7  This file is part of O2scl.
8 
9  O2scl is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13 
14  O2scl is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with O2scl. If not, see <http://www.gnu.org/licenses/>.
21 
22  -------------------------------------------------------------------
23 */
24 #ifndef O2SCL_GSL_INTE_QAWF_H
25 #define O2SCL_GSL_INTE_QAWF_H
26 
27 /** \file inte_qawf_gsl.h
28  \brief File defining \ref o2scl::inte_qawf_gsl_sin and
29  \ref o2scl::inte_qawf_gsl_cos
30 */
31 
32 #include <o2scl/inte.h>
33 #include <o2scl/inte_qawo_gsl.h>
34 #include <o2scl/inte_qagiu_gsl.h>
35 
36 #ifndef DOXYGEN_NO_O2NS
37 namespace o2scl {
38 #endif
39 
40  /** \brief Adaptive integration for oscillatory integrals (GSL)
41 
42  The Fourier integral
43  \f[
44  \int_a^{\infty} f(x) \sin(\omega x)~dx
45  \f]
46  is computed for some frequency parameter \f$ \omega \f$,
47  stored in \ref inte_qawo_gsl_sin::omega .
48 
49  The integral is computed using the same method as \ref
50  inte_qawo_gsl_sin and \ref inte_qawo_gsl_cos over each of the
51  subintervals,
52  \f{eqnarray*}{
53  C_1 &=& [a, a+c] \\
54  C_2 &=& [a+c, a+2c] \\
55  &\vdots & \\
56  C_k &=& [a +(k-1)c,\, a+kc],
57  \f}
58  where \f$ c = (2\mathrm{floor}(|\omega|)+1)\pi/|\omega|\f$. This
59  width is chosen to cover an odd number of periods so that the
60  contributions from the intervals alternate in sign and are
61  monotonically decreasing when \f$ f \f$ is positive and
62  monotonically decreasing. The sum of this sequence of
63  contributions is accelerated using the \f$ \varepsilon \f$
64  algorithm.
65 
66  The algorithm uses zero for the relative tolerance \ref
67  inte::tol_rel and attempts to compute the integral to an
68  overall absolute tolerance set by \ref inte::tol_abs. The
69  following strategy is used: on each interval \f$ C_k\f$, the
70  algorithm tries to achieve the tolerance
71  \f[
72  \mathrm{TOL}_k = u_k\cdot \epsilon_{\mathrm{abs}}
73  \f]
74  where \f$ u_k = (1-p)p^{k-1} \f$ and \f$ p = 0.9\f$. The sum of
75  the geometric series of contributions from each interval gives
76  an overall tolerance of \f$ \epsilon_{\mathrm{abs}}\f$. If the
77  integration of a subinterval leads to difficulties then the accu
78  racy requirement for subsequent intervals is relaxed,
79  \f[
80  \mathrm{TOL}_k =
81  u_k\cdot \max\{\epsilon_{\mathrm{abs}}, E_1, \ldots, E_{k-1} \}
82  \f]
83  where \f$ E_k\f$ is the estimated error on the interval \f$ C_k\f$.
84 
85  See \ref gslinte_subsect in the User's guide for general
86  information about the GSL integration classes.
87 
88  When verbose output is enabled, this class outputs information
89  from both the subintegrations performed by \ref
90  inte_qawo_gsl_sin and the overall integration progress in this
91  class.
92 
93  \todo More documentation and examples for the
94  qawf, qawo and qawc integrators.
95  */
96  template<class func_t> class inte_qawf_gsl_sin :
97  public inte_qawo_gsl_sin<func_t> {
98 
99  public:
100 
102  }
103 
104  virtual ~inte_qawf_gsl_sin() {}
105 
106  /** \brief Integrate function \c func from \c a to \c b and place
107  the result in \c res and the error in \c err
108  */
109  virtual int integ_err(func_t &func, double a, double b,
110  double &res, double &err) {
111 
112  this->otable=gsl_integration_qawo_table_alloc
113  (this->omega,1.0,GSL_INTEG_SINE,this->n_levels);
114  this->cyclew=new inte_workspace_gsl;
115  this->cyclew->allocate(this->w->limit);
116 
117  int status=qawf(func,a,this->tol_abs,&res,&err);
118 
119  gsl_integration_qawo_table_free(this->otable);
120  this->cyclew->free();
121  delete this->cyclew;
122 
123  return status;
124  }
125 
126 #ifndef DOXYGEN_INTERNAL
127 
128  protected:
129 
130  /// The integration workspace
132 
133  /** \brief The full GSL integration routine called by integ_err()
134  */
135  int qawf(func_t &func, const double a,
136  const double epsabs, double *result, double *abserr) {
137 
138  double area, errsum;
139  double res_ext, err_ext;
140  double correc, total_error = 0.0, truncation_error;
141 
142  size_t ktmin = 0;
143  size_t iteration = 0;
144 
146 
147  double cycle;
148  //double omega = this->otable->omega;
149 
150  const double p = 0.9;
151  double factor = 1;
152  double initial_eps, eps;
153  int error_type = 0;
154 
155  /* Initialize results */
156 
157  this->w->initialise(a,a);
158 
159  *result = 0;
160  *abserr = 0;
161 
162  size_t limit=this->w->limit;
163  /*
164  if (limit > this->w->limit) {
165  std::string estr="Iteration limit exceeds workspace ";
166  estr+="in inte_qawf_gsl::qawf().";
167  O2SCL_ERR(estr.c_str(),exc_einval);
168  }
169  */
170 
171  /* Test on accuracy */
172 
173  if (epsabs <= 0) {
174  std::string estr="The absolute tolerance must be positive ";
175  estr+="in inte_qawf_gsl::qawf().";
176  O2SCL_ERR(estr.c_str(),exc_ebadtol);
177  }
178 
179  if (this->omega == 0.0) {
180  if (this->otable->sine == GSL_INTEG_SINE) {
181  /* The function sin(w x) f(x) is always zero for w = 0 */
182 
183  *result = 0;
184  *abserr = 0;
185 
186  return success;
187  } else {
188  /* The function cos(w x) f(x) is always f(x) for w = 0 */
189 
191 
192  int status=iu.integ_err(func,a,0.0,*result,*abserr);
193 
194  return status;
195  }
196  }
197 
198  if (epsabs > GSL_DBL_MIN / (1 - p)) {
199  eps = epsabs * (1 - p);
200  } else {
201  eps = epsabs;
202  }
203 
204  initial_eps = eps;
205 
206  area = 0;
207  errsum = 0;
208 
209  res_ext = 0;
210  err_ext = GSL_DBL_MAX;
211  correc = 0;
212 
213  cycle = (2 * floor (fabs (this->omega)) + 1) *
214  M_PI / fabs (this->omega);
215 
216  gsl_integration_qawo_table_set_length (this->otable, cycle);
217 
218  this->initialise_table (&table);
219 
220  for (iteration = 0; iteration < limit; iteration++) {
221  double area1, error1, reseps, erreps;
222 
223  double a1 = a + iteration * cycle;
224  double b1 = a1 + cycle;
225 
226  double epsabs1 = eps * factor;
227 
228  int status=this->qawo(func,a1,epsabs1,0.0,cyclew,this->otable,
229  &area1,&error1);
230 
231  this->w->append_interval (a1, b1, area1, error1);
232 
233  factor *= p;
234 
235  area = area + area1;
236  errsum = errsum + error1;
237 
238  /* estimate the truncation error as 50 times the final term */
239 
240  truncation_error = 50 * fabs (area1);
241 
242  total_error = errsum + truncation_error;
243 
244  if (total_error < epsabs && iteration > 4) {
245  goto compute_result;
246  }
247 
248  if (error1 > correc) {
249  correc = error1;
250  }
251 
252  if (status) {
253  eps = GSL_MAX_DBL (initial_eps, correc * (1.0 - p));
254  }
255 
256  if (status && total_error < 10 * correc && iteration > 3) {
257  goto compute_result;
258  }
259 
260  this->append_table (&table, area);
261 
262  if (table.n < 2) {
263  continue;
264  }
265 
266  this->qelg (&table, &reseps, &erreps);
267 
268  ktmin++;
269 
270  if (ktmin >= 15 && err_ext < 0.001 * total_error) {
271  error_type = 4;
272  }
273 
274  if (erreps < err_ext) {
275  ktmin = 0;
276  err_ext = erreps;
277  res_ext = reseps;
278 
279  if (err_ext + 10 * correc <= epsabs)
280  break;
281  if (err_ext <= epsabs && 10 * correc >= epsabs)
282  break;
283  }
284 
285  if (this->verbose>0) {
286  std::cout << "inte_qawf_gsl Iter: " << iteration;
287  std::cout.setf(std::ios::showpos);
288  std::cout << " Res: " << area;
289  std::cout.unsetf(std::ios::showpos);
290  std::cout << " Err: " << total_error
291  << " Tol: " << epsabs << std::endl;
292  if (this->verbose>1) {
293  char ch;
294  std::cout << "Press a key and type enter to continue. " ;
295  std::cin >> ch;
296  }
297  }
298 
299  }
300 
301  if (iteration == limit) error_type = 1;
302 
303  if (err_ext == GSL_DBL_MAX)
304  goto compute_result;
305 
306  err_ext = err_ext + 10 * correc;
307 
308  *result = res_ext;
309  *abserr = err_ext;
310 
311  if (error_type == 0) {
312  return success ;
313  }
314 
315  if (res_ext != 0.0 && area != 0.0) {
316  if (err_ext / fabs (res_ext) > errsum / fabs (area))
317  goto compute_result;
318  } else if (err_ext > errsum) {
319  goto compute_result;
320  } else if (area == 0.0) {
321  goto return_error;
322  }
323 
324  if (error_type == 4) {
325  err_ext = err_ext + truncation_error;
326  }
327 
328  goto return_error;
329 
330  compute_result:
331 
332  *result = area;
333  *abserr = total_error;
334 
335  return_error:
336 
337  if (error_type > 2)
338  error_type--;
339 
340  if (error_type == 0) {
341  return success;
342  } else if (error_type == 1) {
343  std::string estr="Number of iterations was insufficient ";
344  estr+=" in inte_qawf_gsl::qawf().";
345  O2SCL_ERR(estr.c_str(),exc_emaxiter);
346  } else if (error_type == 2) {
347  std::string estr="Roundoff error prevents tolerance ";
348  estr+="from being achieved in inte_qawf_gsl::qawf().";
349  O2SCL_ERR(estr.c_str(),exc_eround);
350  } else if (error_type == 3) {
351  std::string estr="Bad integrand behavior ";
352  estr+=" in inte_qawf_gsl::qawf().";
353  O2SCL_ERR(estr.c_str(),exc_esing);
354  } else if (error_type == 4) {
355  std::string estr="Roundoff error detected in extrapolation table ";
356  estr+="in inte_qawf_gsl::qawf().";
357  O2SCL_ERR(estr.c_str(),exc_eround);
358  } else if (error_type == 5) {
359  std::string estr="Integral is divergent or slowly convergent ";
360  estr+="in inte_qawf_gsl::qawf().";
361  O2SCL_ERR(estr.c_str(),exc_ediverge);
362  } else {
363  std::string estr="Could not integrate function in inte_qawf_gsl";
364  estr+="::qawf() (it may have returned a non-finite result).";
365  O2SCL_ERR(estr.c_str(),exc_efailed);
366  }
367  }
368 
369  /// Add the oscillating part to the integrand
370  virtual double transform(double t, func_t &func) {
371  return func(t)*sin(this->omega*t);
372  }
373 
374 #endif
375 
376  /// Return string denoting type ("inte_qawf_gsl_sin")
377  const char *type() { return "inte_qawf_gsl_sin"; }
378 
379  };
380 
381  /** \brief Adaptive integration a function with finite limits of
382  integration (GSL)
383 
384  The Fourier integral
385  \f[
386  \int_a^{\infty} f(x) \cos(\omega x)~dx
387  \f]
388  is computed for some frequency parameter \f$ \omega \f$ .
389 
390  This class is exactly analogous to \ref inte_qawf_gsl_sin .
391  See that class documentation for more details.
392  */
393  template<class func_t> class inte_qawf_gsl_cos :
394  public inte_qawf_gsl_sin<func_t> {
395 
396  public:
397 
399  }
400 
401  virtual ~inte_qawf_gsl_cos() {}
402 
403  /** \brief Integrate function \c func from \c a to \c b and place
404  the result in \c res and the error in \c err
405  */
406  virtual int integ_err(func_t &func, double a, double b,
407  double &res, double &err) {
408 
409  this->otable=gsl_integration_qawo_table_alloc
410  (this->omega,b-a,GSL_INTEG_COSINE,this->n_levels);
411  this->cyclew=new inte_workspace_gsl;
412  this->cyclew->allocate(this->w->limit);
413 
414  int status=this->qawf(func,a,this->tol_abs,&res,&err);
415 
416  gsl_integration_qawo_table_free(this->otable);
417  this->cyclew->free();
418  delete this->cyclew;
419 
420  return status;
421 
422  }
423 
424 #ifndef DOXYGEN_INTERNAL
425 
426  protected:
427 
428  /// Add the oscillating part to the integrand
429  virtual double transform(double t, func_t &func) {
430  return func(t)*cos(this->omega*t);
431  }
432 
433 #endif
434 
435  /// Return string denoting type ("inte_qawf_gsl_cos")
436  const char *type() { return "inte_qawf_gsl_cos"; }
437 
438  };
439 
440 #ifndef DOXYGEN_NO_O2NS
441 }
442 #endif
443 
444 #endif
Integration workspace for the GSL integrators.
int qawo(func_t &func, const double a, const double epsabs, const double epsrel, inte_workspace_gsl *loc_w, gsl_integration_qawo_table *wf, double *result, double *abserr)
The full GSL integration routine called by integ_err()
void initialise_table(struct extrapolation_table *table)
Initialize the table.
Data table table class.
Definition: table.h:47
double omega
The user-specified frequency (default 1.0)
Definition: inte_qawo_gsl.h:72
virtual int integ_err(func_t &func, double a, double b, double &res, double &err)
Integrate function func from a to b and place the result in res and the error in err.
Adaptive integration a function with finite limits of integration (GSL)
void append_table(struct extrapolation_table *table, double y)
Append a result to the table.
apparent singularity detected
Definition: err_hnd.h:93
exceeded max number of iterations
Definition: err_hnd.h:73
const char * type()
Return string denoting type ("inte_qawf_gsl_sin")
virtual int integ_err(func_t &func, double a, double b, double &res, double &err)
Integrate function func from a to b and place the result in res and the error in err.
size_t n_levels
The number of bisection levels (default 10)
Definition: inte_qawo_gsl.h:75
generic failure
Definition: err_hnd.h:61
inte_workspace_gsl * cyclew
The integration workspace.
double tol_abs
The maximum absolute uncertainty in the value of the integral (default )
Definition: inte.h:73
Integrate a function over the interval (GSL)
int initialise(double a, double b)
Initialize the workspace for an integration with limits a and b.
virtual int integ_err(func_t &func, double a, double b, double &res, double &err)
Integrate a function over the interval giving result res and error err.
int allocate(size_t sz)
Allocate a workspace.
#define O2SCL_ERR(d, n)
Set an error with message d and code n.
Definition: err_hnd.h:273
void append_interval(double a1, double b1, double area1, double error1)
Push a new interval to the workspace stack.
void qelg(struct extrapolation_table *table, double *result, double *abserr)
Determines the limit of a given sequence of approximations.
Adaptive integration for oscillatory integrals (GSL)
Definition: inte_qawf_gsl.h:96
inte_workspace_gsl * w
The integration workspace.
A structure for extrapolation for inte_qags_gsl.
const char * type()
Return string denoting type ("inte_qawf_gsl_cos")
size_t n
Index of new element in the first column.
size_t limit
Maximum number of subintervals allocated.
user specified an invalid tolerance
Definition: err_hnd.h:77
Success.
Definition: err_hnd.h:47
int free()
Free allocated workspace memory.
virtual double transform(double t, func_t &func)
Add the oscillating part to the integrand.
Adaptive integration for oscillatory integrals (GSL)
Definition: inte_qawo_gsl.h:59
gsl_integration_qawo_table * otable
The integration workspace.
Definition: inte_qawo_gsl.h:99
int verbose
Verbosity.
Definition: inte.h:60
virtual double transform(double t, func_t &func)
Add the oscillating part to the integrand.
failed because of roundoff error
Definition: err_hnd.h:87
integral or series is divergent
Definition: err_hnd.h:95
int qawf(func_t &func, const double a, const double epsabs, double *result, double *abserr)
The full GSL integration routine called by integ_err()

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..