1 #ifndef _utl_Integrator_h_
2 #define _utl_Integrator_h_
4 #include <utl/PolynomialInterpolation.h>
5 #include <utl/ErrorLogger.h>
71 template<
class Functor>
75 Integrator(Functor& functor,
const double accuracy = 1e-5)
90 const int order = 5,
const int maxIterations = 20)
93 const double delta = b -
a;
95 std::vector<double> tInt(maxIterations+1);
96 std::vector<double> tStep(maxIterations+1);
97 double oldInt = tInt[0] = GetBoxAverage(a, delta, 2);
100 for (i = 1; i < order; ++i) {
102 tStep[i] = delta / (1 << (2*i));
106 double extrapolation = 1e10;
107 for ( ; i <= maxIterations; ++i) {
109 tStep[i] = delta / (1 << (2*i));
110 const int first = i - order + 1;
114 if (fabs(residual) <= eps*fabs(extrapolation))
115 return delta*extrapolation;
118 WARNING(
"Maximal level limit reached, result is not accurate.");
119 return delta*extrapolation;
125 const int minLevel = 4,
const int maxLevel = 20)
128 const double delta = b -
a;
129 double trapezAverage = GetBoxAverage(a, delta, 2);
132 for (level = 1; level < minLevel; ++level)
135 double trapezOld = trapezAverage;
137 double simpsonOld = (4./3)*trapezAverage - (1./3)*trapezOld;
139 for ( ; level <= maxLevel; ++level) {
140 trapezOld = trapezAverage;
142 const double simpsonAverage = (4./3)*trapezAverage - (1./3)*trapezOld;
143 if (fabs(simpsonAverage - simpsonOld) <
fAccuracy*fabs(simpsonAverage) ||
144 (!simpsonAverage && !simpsonOld))
145 return delta*simpsonAverage;
146 simpsonOld = simpsonAverage;
149 WARNING(
"Maximal level limit reached, result is not accurate.");
150 return delta*simpsonOld;
156 const int minLevel = 4,
const int maxLevel = 20)
159 const double delta = b -
a;
160 double average = GetBoxAverage(a, delta, 2);
162 for (level = 1; level <= minLevel; ++level)
164 for ( ; level <= maxLevel; ++level) {
165 const double old = average;
167 if (fabs(average - old) <
fAccuracy*fabs(average) || (!average && !old))
168 return delta*average;
171 WARNING(
"Maximal level limit reached, result is not accurate.");
172 return delta*average;
204 const double a,
const double delta,
const int level)
207 const int n = 1 << (level - 1);
208 const double step = delta/
n;
209 return 0.5*(previousApproximation +
210 GetBoxAverage(a+0.5*step, step, n));
215 GetBoxAverage(
const double start,
const double step,
const int n)
219 for (
int i = 0; i <
n; ++i) {
220 const double x = start + i*step;
233 template<
class Functor>
242 template<
class Functor,
unsigned int dim>
255 const int order = 5,
const int maxIterations = 20)
258 for (
unsigned int k = 0; k < dim; ++k)
261 const double delta = b -
a;
263 std::vector<double> tInt[dim];
264 for (
unsigned int k = 0; k < dim; ++k)
265 tInt[k].resize(maxIterations+1);
266 std::vector<double> tStep(maxIterations+1);
268 GetBoxAverage(oldInt, a, delta, 2);
269 for (
unsigned int k = 0; k < dim; ++k)
270 tInt[k][0] = oldInt[k];
273 for (i = 1; i < order; ++i) {
275 for (
unsigned int k = 0; k < dim; ++k)
276 tInt[k][i] = oldInt[k];
277 tStep[i] = delta / (1 << (2*i));
281 for (
unsigned int k = 0; k < dim; ++k)
283 for ( ; i <= maxIterations; ++i) {
285 for (
unsigned int k = 0; k < dim; ++k)
286 tInt[k][i] = oldInt[k];
287 tStep[i] = delta / (1 << (2*i));
288 const int first = i - order + 1;
290 unsigned int nAccepted = 0;
291 for (
unsigned int k = 0; k < dim; ++k) {
295 if (fabs(residual) <= eps*fabs(result[k]))
298 if (nAccepted == dim) {
299 for (
unsigned int k = 0; k < dim; ++k)
305 WARNING(
"Maximal level limit reached, result is not accurate.");
306 for (
unsigned int k = 0; k < dim; ++k)
313 const double a,
const double delta,
const int level)
316 const int n = 1 << (level - 1);
317 const double step = delta/n;
319 GetBoxAverage(add, a+0.5*step, step, n);
320 for (
unsigned int k = 0; k < dim; ++k)
321 previousApproximation[k] = 0.5*(previousApproximation[k] + add[k]);
326 GetBoxAverage(
double*
const sum,
const double start,
const double step,
const int n)
329 for (
unsigned int k = 0; k < dim; ++k)
333 for (
int i = 0; i < n; ++i) {
334 const double x = start + i*step;
336 for (
unsigned int k = 0; k < dim; ++k)
340 for (
unsigned int k = 0; k < dim; ++k)
void SetAccuracy(const double accuracy)
final accuracy goal of the integration
double GetTrapezoidalAverage(const double previousApproximation, const double a, const double delta, const int level) const
Calculates succsessive approximations to the function average.
Class for integration of functions with one independent parameter.
void GetTrapezoidalAverage(double *const previousApproximation, const double a, const double delta, const int level) const
double GetTrapezoidalIntegral(const double a, const double b, const int minLevel=4, const int maxLevel=20) const
basic trapezoidal integration
void GetIntegral(double *const result, const double a, const double b, const int order=5, const int maxIterations=20) const
Romberg integration, for details see utl::Integrator.
Integrator(Functor &functor, const double accuracy=1e-5)
double GetSimpsonIntegral(const double a, const double b, const int minLevel=4, const int maxLevel=20) const
Simpson improvement build on top of the trapezoidal integration.
void SetAccuracy(const double accuracy)
final accuracy goal of the integration
double GetIntegral(const double a, const double b) const
call this method when you do not care about the specific implementation
#define WARNING(message)
Macro for logging warning messages.
VectorIntegrator(Functor &functor, const double accuracy=1e-5)
double PolynomialInterpolation(const unsigned int n, const double px[], const double py[], const double x, double &dy)
Perform polynomial interpolation or extrapolation.
Integrator< Functor > MakeIntegrator(Functor &f)
convenience factory
double GetRombergIntegral(const double a, const double b, const int order=5, const int maxIterations=20) const
Romberg integration Setting order to 2 is equivalent to the Simpson's method.