CMlib
Cell mapping algorithms in C++
rk45.h
Go to the documentation of this file.
1 #ifndef CELL_MAPPING_CPP_RK45_H
2 #define CELL_MAPPING_CPP_RK45_H
3 
4 #include <cstdio>
5 
6 namespace cm {
7 
12  template <class T, class S>
13  class RK45 {
14  private:
15  const S* sys;
16  T k1, k2, k3, k4, k5, k6, k7, c6;
17  T y15, y14;
18  double relTol;
19  double stepSizeIncrement = 1.1;
20  double stepSizeDecrement = 0.1;
21  T internalStep(const T& y, double& t, double& h) {
22  k1 = sys->f(y, t);
23  k2 = sys->f(y + 1.0/5.0*h*k1, t + 1.0/5.0*h);
24  k3 = sys->f(y + 3.0/40.0*h*k1 + 9.0/40.0*h*k2, t + 3.0/10.0*h);
25  k4 = sys->f(y + 44.0/45.0*h*k1 - 56.0/15.0*h*k2 + 32.0/9.0*h*k3, t + 4.0/5.0*h);
26  k5 = sys->f(y + 19372.0/6561.0*h*k1 - 25360.0/2187.0*h*k2 + 64448.0/6561.0*h*k3 - 212.0/729.0*h*k4, t + 8.0/9.0*h);
27  k6 = sys->f(y + 9017.0/3168.0*h*k1 - 355.0/33.0*h*k2 + 46732.0/5247.0*h*k3 + 49.0/176.0*h*k4 - 5103.0/18656.0*h*k5, t + h);
28  c6 = 35.0/384.0*h*k1 + 500.0/1113.0*h*k3 + 125.0/192.0*h*k4 - 2187.0/6784.0*h*k5 + 11.0/84.0*h*k6;
29  k7 = sys->f(y + c6, t + h);
30  y15 = y + c6;
31  y14 = y + 5179.0/57600.0*h*k1 + 7571.0/16695.0*h*k3 + 393.0/640.0*h*k4 - 92097.0/339200.0*h*k5 + 187.0/2100.0*h*k6 + 1.0/40.0*h*k7;
32  double relErr = abs(norm(y15-y14)/norm(y15));
33  if (relErr < relTol) {
34  // If true, increase internal step size and continue
35  t+=h;
36  h*=stepSizeIncrement;
37  return y15;
38  } else {
39  // Decrease internal step size
40  h*=stepSizeDecrement;
41  return y;
42  }
43  }
44  public:
45  RK45(const S* systemPointer, double relativeTolerance) : sys(systemPointer), relTol(relativeTolerance) { }
46  T step(const T& y0, const double t0, const double dt, const double h0) {
47  // Uses internalStep to integrate the system from t_start = t0 to t_end = t0+dt
48  double t = t0;
49  double h = h0;
50  T y = y0;
51  while (t < t0+dt) {
52  // To reach t0+dt exactly, reduce the final step size if necessary
53  if (t+h > t0+dt) { h = (t0+dt-t); }
54  y = internalStep(y,t,h);
55  }
56  return y;
57  }
58  T step(const T& y0, const double t0, const double dt, const double h0, const size_t maxsteps) {
59  // Uses internalStep to integrate the system from t_start = t0 to t_end = t0+dt
60  double t = t0;
61  double h = h0;
62  T y = y0;
63  size_t steps = 0;
64  while (t < t0+dt) {
65  steps++;
66  if (steps > maxsteps) {
67  // Stop integration if maximum steps exceeded
68  break;
69  }
70  // To reach t0+dt exactly, reduce the final step size if necessary
71  if (t+h > t0+dt) { h = (t0+dt-t); }
72  y = internalStep(y,t,h);
73  }
74  return y;
75  }
76 
77  };
78 
79 }
80 
81 #endif //CELL_MAPPING_CPP_RK45_H
RK45(const S *systemPointer, double relativeTolerance)
Definition: rk45.h:45
T step(const T &y0, const double t0, const double dt, const double h0)
Definition: rk45.h:46
RK45 Scheme with adaptive step-size control Can be used on any system having member function f(y,...
Definition: rk45.h:13
double norm(const vec2 &v)
Vector L2 norm.
Definition: vec2.cpp:66
T step(const T &y0, const double t0, const double dt, const double h0, const size_t maxsteps)
Definition: rk45.h:58
Definition: cell.h:6