atomicrex  0.1
An advanced atomistic model building tool
NumericalIntegration.h
1 //
3 // Copyright (C) 2017, Alexander Stukowski and Paul Erhart
4 //
5 // This file is part of atomicrex.
6 //
7 // Atomicrex is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Atomicrex is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //
21 
22 #pragma once
23 
24 #include "../Atomicrex.h"
25 
26 namespace atomicrex {
27 
32 {
33 public:
34 
37  template<typename DifferentialForm>
38  double integrate(double a, double b, DifferentialForm diffForm) {
39  if(a > b)
40  throw std::runtime_error(boost::str(boost::format("Left boundary larger than right boundary in NumericalIntegration::integrate(): %1% > %2%.") % a % b));
41  return simpson(a, b, diffForm);
42  };
43 
46  virtual double integrate(double a, double b) {
47  return integrate(a, b, differentialFormDefault);
48  }
49 
52  virtual double integrateSpherical(double a, double b) {
53  return integrate(a, b, differentialFormSpherical);
54  }
55 
56 protected:
57 
60  virtual double evaluateInternal(double x) = 0;
61 
62 private:
63 
65  static double differentialFormDefault(double r, double f) {
66  return f;
67  }
68 
70  static double differentialFormSpherical(double r, double f) {
71  return square(r) * f;
72  }
73 
74 private:
75 
76  /**********************************************************************
77  * Returns the integral of the function func from a to b. The parameters
78  * epsilon can be set to the desired fractional accuracy and JMAX so that 2
79  * to the power JMAX-1 is the maximum allowed number of steps.
80  * Integration is performed by Simpson's rule.
81  **********************************************************************/
82  template<typename DifferentialForm>
83  double simpson(double a, double b, DifferentialForm diffForm, double eps = FLOATTYPE_EPSILON, int jmax = 20)
84  {
85  double s, s2, st, ost = 0.0, os = 0.0;
86  for(int j = 1; j <= jmax; j++) {
87  st = trapezoid(a, b, j, s2, diffForm);
88  s = (4.0 * st - ost) / 3.0;
89  if(j > 5) // Avoid spurious early convergence.
90  if(fabs(s - os) < eps*fabs(os) || (s == 0.0 && os == 0.0)) return s;
91  os = s;
92  ost = st;
93  }
94  throw std::runtime_error("Exceeded maximum number of iterations in routine NumericalIntegration::simpson().");
95  return 0.0; // Never get here.
96  };
97 
98  /**********************************************************************
99  * This routine computes the nth stage of refinement of an extended
100  * trapezoidal rule. func is input as a pointer to the function to
101  * be integrated between limits a and b, also input. When called with
102  * n=1, the routine returns the crudest estimate of a int_a^b f(x)dx.
103  * Subsequent calls with n=2,3,... (in that sequential order) will
104  * improve the accuracy by adding 2^(n-2) additional interior points.
105  **********************************************************************/
106  template<typename DifferentialForm>
107  double trapezoid(double a, double b, int n, double& s, DifferentialForm diffForm)
108  {
109  if(n == 1) {
110  return (s = 0.5*(b-a)*(diffForm(a, evaluateInternal(a)) + diffForm(b, evaluateInternal(b))));
111  }
112  else {
113  int it = 1;
114  for(int j = 1; j < n-1; j++) it <<= 1;
115  double tnm = it;
116  double del = (b-a)/tnm; // This is the spacing of the points to be added.
117  double x = a + 0.5 * del;
118  double sum = 0;
119  for(int j = 1; j <= it; j++, x+=del) sum += diffForm(x, evaluateInternal(x));
120  s = 0.5 * (s + (b-a) * sum / tnm); // This replaces s by its refined value.
121  return s;
122  }
123  }
124 };
125 
126 } // End of namespace
double integrate(double a, double b, DifferentialForm diffForm)
Definition: NumericalIntegration.h:38
T square(const T &f)
Computes the square of a number.
Definition: FloatType.h:43
virtual double evaluateInternal(double x)=0
virtual double integrate(double a, double b)
Definition: NumericalIntegration.h:46
This file collects the definition of classes that define various simple crystal structures.
Definition: Atomicrex.h:67
virtual double integrateSpherical(double a, double b)
Definition: NumericalIntegration.h:52
Definition: NumericalIntegration.h:31