CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
DefiniteIntegral.cc
Go to the documentation of this file.
1// -*- C++ -*-
2// $Id: DefiniteIntegral.cc,v 1.6 2010/06/16 18:22:01 garren Exp $
3
4#include "CLHEP/GenericFunctions/AbsFunction.hh"
5#include "CLHEP/GenericFunctions/DefiniteIntegral.hh"
6
7#include <cmath>
8#include <iostream>
9#include <vector>
10#include <stdexcept>
11
12namespace Genfun {
13
14
16
17 //
18 // This class has limited visibility its functions, data,
19 // and nested classes are all public:
20 //
21
22 public:
23
25
26 public:
27
28 // Constructorctor:
30
31 // Destructor:
32 virtual ~QuadratureRule() {};
33
34 // Integrate at the j^th level of refinement:
35 virtual double integrate(const AbsFunction & function,
36 double a,
37 double b,
38 unsigned int j) const=0;
39
40 // Return the step multiplier:
41 virtual unsigned int stepMultiplier () const=0;
42
43 // Return the number of function calls:
44 virtual unsigned int numFunctionCalls() const =0;
45
46 };
47
49
50 public:
51
52 // Constructor:
53 TrapezoidQuadratureRule():retVal(0),nFunctionCalls(0) {};
54
55 // Destructor:
57
58 // Integrate at the j^th level of refinement:
59 virtual double integrate(const AbsFunction & function,
60 double a,
61 double b,
62 unsigned int j) const;
63
64 // The step is doubled at each level of refinement:
65 virtual unsigned int stepMultiplier () const {return 2;}
66
67 // Returns number of function calls:
68 virtual unsigned int numFunctionCalls() const {return nFunctionCalls;};
69
70 private:
71
72 mutable double retVal;
73 mutable unsigned int nFunctionCalls;
74
75 };
76
78
79 public:
80
81 // Constructor:
82 XtMidpointQuadratureRule():retVal(0),nFunctionCalls(0) {};
83
84 // Destructorctor:
86
87 // Integrate at the j^th level of refinement:
88 virtual double integrate(const AbsFunction & function,
89 double a,
90 double b,
91 unsigned int j) const;
92
93 // The step is tripled at each level of refinement:
94 virtual unsigned int stepMultiplier () const {return 3;}
95
96 // Returns number of function calls:
97 virtual unsigned int numFunctionCalls() const {return nFunctionCalls;};
98
99 private:
100
101 mutable double retVal;
102 mutable unsigned int nFunctionCalls;
103 };
104
105 double a; // lower limit of integration
106 double b; // upper limit of integration
107 DefiniteIntegral::Type type; // open or closed
108 mutable unsigned int nFunctionCalls; // bookkeeping
109 unsigned int MAXITER; // Max no of step doubling, tripling, etc.
110 double EPS; // Target precision
111 unsigned int K; // Minimum order =2*5=10
112
113 // Polynomial interpolation with Neville's method:
114 void polint(std::vector<double>::iterator xArray, std::vector<double>::iterator yArray, double x, double & y, double & deltay) const;
115
116 };
117
118
119 DefiniteIntegral::DefiniteIntegral(double a, double b, Type type):
120 c(new Clockwork()) {
121 c->a = a;
122 c->b = b;
123 c->type = type;
124 c->nFunctionCalls = 0;
125 c->MAXITER = type==OPEN ? 20 : 14;
126 c->EPS = 1.0E-6;
127 c->K = 5;
128 }
129
131 delete c;
132 }
133
135 :AbsFunctional(right), c(new Clockwork(*right.c)) {
136 }
137
139 if (this!=&right) {
140 delete c;
141 c = new Clockwork(*right.c);
142 }
143 return *this;
144 }
145
147 c->EPS=eps;
148 }
149
150 void DefiniteIntegral::setMaxIter(unsigned int maxIter) {
151 c->MAXITER=maxIter;
152 }
153
154 void DefiniteIntegral::setMinOrder(unsigned int minOrder) {
155 c->K=(minOrder+1)/2;
156 }
157
158 double DefiniteIntegral::operator [] (const AbsFunction & function) const {
159
160 const Clockwork::QuadratureRule * rule = c->type==OPEN ?
163 double xMult=rule->stepMultiplier();
164
165 c->nFunctionCalls=0;
166 std::vector<double> s(c->MAXITER+2),h(c->MAXITER+2);
167 h[1]=1.0;
168 for (unsigned int j=1;j<=c->MAXITER;j++) {
169 s[j]=rule->integrate(function, c->a, c->b, j);
171 if (j>=c->K) {
172 double ss(0.), dss(0.);
173 c->polint(h.begin()+j-c->K,s.begin()+j-c->K,0.0,ss, dss);
174 if (fabs(dss) <= c->EPS*fabs(ss)) {
175 delete rule;
176 return ss;
177 }
178 }
179 s[j+1]=s[j];
180 h[j+1]=h[j]/xMult/xMult;
181 }
182 delete rule;
183 throw std::runtime_error("DefiniteIntegral: too many steps. No convergence");
184 return 0.0; // Never get here.
185 }
186
187 void DefiniteIntegral::Clockwork::polint(std::vector<double>::iterator xArray, std::vector<double>::iterator yArray, double x, double & y, double & deltay) const {
188 double dif = fabs(x-xArray[1]),dift;
189 std::vector<double> cc(K+1),d(K+1);
190 unsigned int ns=1;
191 for (unsigned int i=1;i<=K;i++) {
192 dift=fabs(x-xArray[i]);
193 if (dift<dif) {
194 ns=i;
195 dif=dift;
196 }
197 cc[i]=d[i]=yArray[i];
198 }
199 y = yArray[ns--];
200 for (unsigned int m=1;m<K;m++) {
201 for (unsigned int i=1;i<=K-m;i++) {
202 double ho = xArray[i]-x;
203 double hp= xArray[i+m]-x;
204 double w=cc[i+1]-d[i];
205 double den=ho-hp;
206 if (den==0)
207 std::cerr
208 << "Error in polynomial extrapolation"
209 << std::endl;
210 den=w/den;
211 d[i]=hp*den;
212 cc[i]=ho*den;
213 }
214 deltay = 2*ns < (K-m) ? cc[ns+1]: d[ns--];
215 y += deltay;
216 }
217 }
218
220 return c->nFunctionCalls;
221 }
222
223 // Quadrature rules:
224 double DefiniteIntegral::Clockwork::TrapezoidQuadratureRule::integrate(const AbsFunction & function, double aa, double bb, unsigned int n) const {
225 unsigned int it, j;
226 if (n==1) {
227 retVal = 0.5*(bb-aa)*(function(aa)+function(bb));
228 nFunctionCalls+=2;
229 }
230 else {
231 for (it=1,j=1;j<n-1;j++) it <<=1;
232 double tnm=it;
233 double del = (bb-aa)/tnm;
234 double x=aa+0.5*del;
235 double sum;
236 for (sum=0.0,j=1;j<=it;j++,x+=del) {
237 sum +=function(x);
238 nFunctionCalls++;
239 }
240 retVal = 0.5*(retVal+(bb-aa)*sum/tnm);
241 }
242 return retVal;
243 }
244
245 // Quadrature rules:
246 double DefiniteIntegral::Clockwork::XtMidpointQuadratureRule::integrate(const AbsFunction & function, double aa, double bb, unsigned int n) const {
247 unsigned int it, j;
248 if (n==1) {
249 retVal = (bb-aa)*(function((aa+bb)/2.0));
250 nFunctionCalls+=1;
251 }
252 else {
253 for (it=1,j=1;j<n-1;j++) it *=3;
254 double tnm=it;
255 double del = (bb-aa)/(3.0*tnm);
256 double ddel = del+del;
257 double x=aa+0.5*del;
258 double sum=0;
259 for (j=1;j<=it;j++) {
260 sum +=function(x);
261 x+=ddel;
262 sum +=function(x);
263 x+=del;
264 nFunctionCalls+=2;
265 }
266 retVal = (retVal+(bb-aa)*sum/tnm)/3.0;
267 }
268 return retVal;
269 }
270
271
272
273} // namespace Genfun
virtual unsigned int stepMultiplier() const =0
virtual unsigned int numFunctionCalls() const =0
virtual double integrate(const AbsFunction &function, double a, double b, unsigned int j) const =0
virtual double integrate(const AbsFunction &function, double a, double b, unsigned int j) const
virtual double integrate(const AbsFunction &function, double a, double b, unsigned int j) const
void polint(std::vector< double >::iterator xArray, std::vector< double >::iterator yArray, double x, double &y, double &deltay) const
DefiniteIntegral(double a, double b, Type=CLOSED)
void setMinOrder(unsigned int order)
virtual double operator[](const AbsFunction &function) const
unsigned int numFunctionCalls() const
DefiniteIntegral & operator=(const DefiniteIntegral &)
void setMaxIter(unsigned int maxIter)
Definition: Abs.hh:14