All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
RombIntSolver.h
Go to the documentation of this file.
1 #ifndef ROMBINTSOLVER_H
2 #define ROMBINTSOLVER_H 1
3 
4 #include <math.h>
5 #include "Colours.h"
6 
7 // Include Marlin
8 #include <streamlog/streamlog.h>
9 
10 /**
11 \addtogroup SiStripDigi SiStripDigi
12 @{
13 */
14 
15 namespace sistrip {
16 
17 #define EPS_R 1E-4
18 #define NSTEPSMAX_R 20
19 #define NSTEPSMIN_R 5
20 #define FCE(x) (_pTemplate->*_fce)(x)
21 
22 //! Double precision Romberg integration solver (Template class represents
23 //! class whose method is to be integrate!). The template class doesn't have
24 //! *.cpp file!
25 //!
26 //! @see Integrate
27 //!
28 //! @author Z. Drasal, Charles University in Prague
29 //!
30 
31 template <class T> class RombIntSolver {
32 
33  public:
34 
35 //!Constructor - sets function to be integrated
36  RombIntSolver(double (T::* fce)(double), T* pTemplate) : _eps(EPS_R),
38  _fce(fce), _pTemplate(pTemplate) {;}
39 
40 //!Constructor - sets function to be integrated and integration precision
41  RombIntSolver(double (T::* fce)(double), T* pTemplate, float eps) : _eps(eps),
43  _fce(fce), _pTemplate(pTemplate) {;}
44 
45 //!Destructor
47 
48 //!This method returns a definite integral of function fce calculated
49 //!in interval (a,b) using so-called Romberg algorithm. The algorithm
50 //!exploites a very general idea of Richardson's deffered approach to the
51 //!limit, where the function is integrated using the trapezium rule first
52 //!(with h subsequently set to (a-b), (a-b)/2, (a-b)/4) and then the result
53 //!is extrapolated to the limit. For n=0 (h=(a-b)) it corresponds to m=0;
54 //!for n=1 (h=(a-b)/2) it corresponds to m=0 and m=1; ..., where m represents
55 //!the m-th step to the limit (Richardson extrapolation).<br>
56 //!
57 //! Calculation (R(0,0); R(1,0)->R(1,1); R(2,0->R(2,1)->R(2,2)):<br>
58 //!
59 //! &nbsp;&nbsp; R(0,0) = 1/2*(b-a)*(f(a)+f(b)<br>
60 //! &nbsp;&nbsp; R(n,0) = 1/2*R(n-1,0) + h*Sum(i=1,2^(n-1)){f(a+(2*i-1)*h)}<br>
61 //!
62 //! &nbsp;&nbsp; R(n,m) ... m-th iteration - achieved precision O(h^(2^(m+1)))<br>
63 //! &nbsp;&nbsp; R(n,m) = R(n,m-1) + (R(n,m-1)-R(n-1,m-1))/(4^m-1)<br>
64 //!
65 //! Total relative precision (influenced by maximum number of steps permitted):<br>
66 //!
67 //! &nbsp;&nbsp; epsilon = |R(n,n) - R(n,n-1)|/R(n,n) <br>
68 //!
69 //!For more details see J.Stoer, R.Bulirsch: Introduction to Numerical Analysis,
70 //!chap. 2 and 3, 3rd ed., and <a href=http://www.nr.com/oldverswitcher.html>www.nr.com</a>
71 //!
72  double Integrate(double endPointA, double endPointB);
73 
74  protected:
75 
76 //!This method returns a definite integral of function fce in interval (a,b)
77 //!and is based on classical extended trapezium rule.
78 //!
79 //! Calculation (n-th iteration):
80 //!
81 //! &nbsp;&nbsp; Int(a,b){f(x)*dx} = h/2*[f(a)+f(b)] + h*Sum(i=1,n-1){f(a+i*h)} - O(h^2)
82 //!
83 //! &nbsp;&nbsp; I(n) = 1/2*I(n-1) + h*Sum(i=1,2^(n-1)){f(a+(2*i-1)*h)}<br>
84 //!
85 //!Where n=0 corresponds to h=(a-b), n=1 to h=(a-b)/2 and the error of the
86 //!aproximation can be derived from Euler-MacLaurin summation formula and is
87 //!following:<br>
88 //!
89 //! &nbsp;&nbsp; -B2*h^2/2!*(f'(b)-f'(a)) - B4*h^4/4!*(f'''(b)-f'''(a)) - ...
90 //!
91 //!For more details see J.Stoer, R.Bulirsch: Introduction to Numerical Analysis,
92 //!chap. 2 and 3, 3rd ed., and <a href=http://www.nr.com/oldverswitcher.html>www.nr.com</a>
93 //!
94  double TrapezRuleInt(int n);
95 
96  private:
97 
98  double _a;//!<Left integration endpoint
99  double _b;//!<Right integration endpoint
100 
101  float _eps;//!<Total integration precision (Caution: Don't overestimate this value!)
102 
103  int _nStepsMin;//!<Minimum number of integration steps permitted (Avoid spurious early convergence!)
104  int _nStepsMax;//!<Maximum number of integration steps permitted
105 
106  double (T::* _fce)(double);//!<Relative pointer to an integrated function
107 
108  T * _pTemplate;//!< Pointer to the template class
109 
110 }; // Class
111 
112 //
113 // Romberg method calculating a definite integral in interval (a,b)
114 //
115 template <class T>
116 double RombIntSolver<T>::Integrate(double endPointA, double endPointB)
117 {
118 // Set endpoints
119  _a = endPointA;
120  _b = endPointB;
121 
122 // Degree of refinement n, m, m4 = 4^m
123  int i, n, m, m4;
124 
125 // Integration sesult for given n, m
126  double R[NSTEPSMAX_R][NSTEPSMAX_R];
127 
128 // Calculate integral using Trapezium method
129  for (n=0; n<_nStepsMax; n++) {
130  R[n][0] = TrapezRuleInt(n);
131 
132 // std::cout << std::endl;
133 // std::cout << "Step n=" << n << "R[" << n << "][0]" << R[n][0];
134 
135  // Use Richardson approach to increase precision
136  for (m=1; m<=n; m++) {
137  for (m4=1, i=0; i<(2*m); i++) m4<<=1;
138  R[n][m] = R[n][m-1] + (R[n][m-1] - R[n-1][m-1])/(m4 - 1);
139 
140 // std::cout << std::endl;
141 // std::cout << "Step n,m=" << n << "," << m << "R[" << n << "]"
142 // << "[" << m << "]" <<R[n][m];
143  }
144 
145  // Find out precision
146  if ((n>=_nStepsMin)&&((fabs(R[n][n] - R[n][n-1])/R[n][n])<_eps)) return R[n][n];
147 // std::cout << std::endl;
148  }
149 
150  // Too many steps to obtain required precision
151  //std::cout << "Warning - Too many steps in Romberg integr., required "
152  // << "precision wasn't achieved" << std::endl;
153  streamlog_out(WARNING) << "Warning - Too many steps in Romberg integr., required "
154  << "precision wasn't achieved" << std::endl;
155 
156  return R[n][n];
157 }
158 
159 //
160 // Trapezium rule - calculates a definite integral in interval (a,b) - n-th iteration
161 //
162 template <class T>
164 {
165  static double trapSum = 0;
166  double x, h, h2, subSum;
167  int i, iN;
168 
169 // 1st iteration (n = 0)
170  if (n == 0) {
171  trapSum = 0.5 * (_b - _a) * (FCE(_a)+FCE(_b));
172 
173  return trapSum;
174  }
175 // n-th iteration
176  else {
177 
178  // Calculate iN = 2^n
179  for (iN=1, i=0; i<n; i++) iN<<=1;
180 
181  // Calculate h
182  h = (_b - _a)/iN;
183  h2= 2*h;
184 
185  // Calculate subSum (Add to trapSum values that hasn't been calculated yet)
186  x = _a + h;
187  for (subSum=0, i=0; i<(iN/2); i++, x+=h2) subSum += FCE(x);
188 
189  // Calculate final trapSum
190  trapSum = 0.5*trapSum + subSum*h;
191 
192  return trapSum;
193  }
194 }
195 
196 } // Namespace
197 
198 /** @} */
199 
200 #endif // ROMBINTSOLVER_H
#define FCE(x)
Definition: RombIntSolver.h:20
#define NSTEPSMAX_R
Definition: RombIntSolver.h:18
static const float m
int _nStepsMin
Minimum number of integration steps permitted (Avoid spurious early convergence!) ...
double TrapezRuleInt(int n)
This method returns a definite integral of function fce in interval (a,b) and is based on classical e...
double _b
Right integration endpoint.
Definition: RombIntSolver.h:99
RombIntSolver(double(T::*fce)(double), T *pTemplate)
Constructor - sets function to be integrated.
Definition: RombIntSolver.h:36
Double precision Romberg integration solver (Template class represents class whose method is to be in...
Definition: RombIntSolver.h:31
RombIntSolver(double(T::*fce)(double), T *pTemplate, float eps)
Constructor - sets function to be integrated and integration precision.
Definition: RombIntSolver.h:41
~RombIntSolver()
Destructor.
Definition: RombIntSolver.h:46
T * _pTemplate
Pointer to the template class.
float _eps
Total integration precision (Caution: Don&#39;t overestimate this value!)
int _nStepsMax
Maximum number of integration steps permitted.
static const float T
double _a
Left integration endpoint.
Definition: RombIntSolver.h:98
#define EPS_R
Definition: RombIntSolver.h:17
#define NSTEPSMIN_R
Definition: RombIntSolver.h:19
double(T::* _fce)(double)
Relative pointer to an integrated function.
double Integrate(double endPointA, double endPointB)
This method returns a definite integral of function fce calculated in interval (a,b) using so-called Romberg algorithm.