32static constexpr double a2 = 0.2, a3 = 0.3, a4 = 0.6, a5 = 1.0, a6 = 0.875;
34static constexpr double b21 = 0.2;
35static constexpr double b31 = 3.0 / 40.0, b32 = 9.0 / 40.0;
36static constexpr double b41 = 0.3, b42 = -0.9, b43 = 1.2;
37static constexpr double b51 = -11.0 / 54.0, b52 = 2.5, b53 = -70.0 / 27.0, b54 = 35.0 / 27.0;
38static constexpr double b61 = 1631.0 / 55296.0, b62 = 175.0 / 512.0, b63 = 575.0 / 13824.0,
39 b64 = 44275.0 / 110592.0, b65 = 253.0 / 4096.0;
41static constexpr double c1 = 37.0 / 378.0, c3 = 250.0 / 621.0, c4 = 125.0 / 594.0,
43static constexpr double dc1 = c1 - 2825.0 / 27648.0;
44static constexpr double dc3 = c3 - 18575.0 / 48384.0;
45static constexpr double dc4 = c4 - 13525.0 / 55296.0;
46static constexpr double dc5 = -277.0 / 14336.0;
47static constexpr double dc6 = c6 - 0.25;
82template <
typename F>
void rkck(
OdeWorkspace& ws_,
double x,
int n,
double h, F&& derivs) {
84 double* ak3 = ws_.ak + n;
85 double* ak4 = ws_.ak + n * 2;
86 double* ak5 = ws_.ak + n * 3;
87 double* ak6 = ws_.ak + n * 4;
89 for (
int i = 0; i < n; i++)
90 ws_.ytemp[i] = ws_.y[i] + b21 * h * ws_.dydx[i];
91 derivs(x + a2 * h, ws_.ytemp, ak2);
93 for (
int i = 0; i < n; i++)
94 ws_.ytemp[i] = ws_.y[i] + h * (b31 * ws_.dydx[i] + b32 * ak2[i]);
95 derivs(x + a3 * h, ws_.ytemp, ak3);
97 for (
int i = 0; i < n; i++)
98 ws_.ytemp[i] = ws_.y[i] + h * (b41 * ws_.dydx[i] + b42 * ak2[i] + b43 * ak3[i]);
99 derivs(x + a4 * h, ws_.ytemp, ak4);
101 for (
int i = 0; i < n; i++)
103 ws_.y[i] + h * (b51 * ws_.dydx[i] + b52 * ak2[i] + b53 * ak3[i] + b54 * ak4[i]);
104 derivs(x + a5 * h, ws_.ytemp, ak5);
106 for (
int i = 0; i < n; i++)
107 ws_.ytemp[i] = ws_.y[i] + h * (b61 * ws_.dydx[i] + b62 * ak2[i] + b63 * ak3[i] +
108 b64 * ak4[i] + b65 * ak5[i]);
109 derivs(x + a6 * h, ws_.ytemp, ak6);
111 for (
int i = 0; i < n; i++)
112 ws_.ytemp[i] = ws_.y[i] + h * (c1 * ws_.dydx[i] + c3 * ak3[i] + c4 * ak4[i] + c6 * ak6[i]);
114 for (
int i = 0; i < n; i++)
116 h * (dc1 * ws_.dydx[i] + dc3 * ak3[i] + dc4 * ak4[i] + dc5 * ak5[i] + dc6 * ak6[i]);
138int rkqs(
OdeWorkspace& ws_,
double* x,
int n,
double htry,
double eps,
double* hdid,
double* hnext,
140 double err, errmax, h, htemp, xnew, xold = *x;
144 rkck(ws_, xold, n, h, derivs);
147 for (
int i = 0; i < n; i++) {
148 err = std::fabs(ws_.yerr[i] / ws_.yscal[i]);
177 for (
int i = 0; i < n; i++)
178 ws_.y[i] = ws_.ytemp[i];
185int integrate(
double* ystart,
int n,
double x1,
double x2,
double eps,
double h1,
195 for (
int i = 0; i < n; i++)
196 ws_.y[i] = ystart[i];
198 for (
int nstp = 1; nstp <=
MAXSTP; nstp++) {
199 derivs(x, ws_.y, ws_.dydx);
200 for (
int i = 0; i < n; i++)
201 ws_.yscal[i] = std::fabs(ws_.y[i]) + std::fabs(ws_.dydx[i] * h) +
TINY;
202 if ((x + h - x2) * (x + h - x1) > 0.0)
205 int errcode =
rkqs(ws_, &x, n, h, eps, &hdid, &hnext, derivs);
209 if ((x - x2) * (x2 - x1) >= 0.0) {
210 for (
int i = 0; i < n; i++)
211 ystart[i] = ws_.y[i];
214 if (std::fabs(hnext) <= 0.0)
Runge-Kutta-Cash-Karp (RK45) ODE integrator with adaptive step control.
Definition OdeSolver.cpp:37
OdeWorkspace & workspace(int n)
Grow this thread's reusable solver arrays for n equations.
Definition OdeSolver.cpp:84
int rkqs(OdeWorkspace &ws_, double *x, int n, double htry, double eps, double *hdid, double *hnext, F &&derivs)
Reject and shrink trial RK45 steps until local error is acceptable.
Definition OdeSolverDetail.hpp:138
void rkck(OdeWorkspace &ws_, double x, int n, double h, F &&derivs)
Evaluate one Cash-Karp trial step in the thread-local workspace.
Definition OdeSolverDetail.hpp:82
int integrate(double *ystart, int n, double x1, double x2, double eps, double h1, F &&derivs)
Definition OdeSolverDetail.hpp:185
Definition OdeSolver.cpp:35
constexpr int MAXSTP
Maximum integration steps.
Definition OdeSolver.hpp:55
constexpr double PSHRNK
Exponent for step decrease.
Definition OdeSolver.hpp:59
int integrateCallable(double *y, int n, double x1, double x2, double eps, double h1, F &&derivs)
Integrate with a concrete synchronous derivative callable.
Definition OdeSolverDetail.hpp:223
constexpr double SAFETY
Step adjustment safety factor.
Definition OdeSolver.hpp:57
constexpr double PGROW
Exponent for step increase.
Definition OdeSolver.hpp:58
constexpr int ODE_UNDERFLOW
Step size underflowed.
Definition OdeSolver.hpp:68
constexpr int ODE_OK
Success.
Definition OdeSolver.hpp:66
constexpr int ODE_MAX_STEPS
Exceeded MAXSTP.
Definition OdeSolver.hpp:69
constexpr double TINY
Underflow protection.
Definition OdeSolver.hpp:56
constexpr double ERRCON
= (5/SAFETY)^(1/PGROW)
Definition OdeSolver.hpp:60
constexpr int ODE_TOO_MANY
n > allocated max
Definition OdeSolver.hpp:67
double * y
Definition odesolve.c:37
Definition OdeSolverDetail.hpp:49
double * yerr
Definition OdeSolverDetail.hpp:54
double * ytemp
Definition OdeSolverDetail.hpp:55
double * y
Definition OdeSolverDetail.hpp:51
~OdeWorkspace()
Release this thread's six solver buffers and reset their pointers.
Definition OdeSolver.cpp:53
double * yscal
Definition OdeSolverDetail.hpp:52
int nmax
Definition OdeSolverDetail.hpp:50
double * dydx
Definition OdeSolverDetail.hpp:53
double * ak
Definition OdeSolverDetail.hpp:56