1 #ifndef RUNKUTODESOLVER_H
2 #define RUNKUTODESOLVER_H 1
9 #include <streamlog/streamlog.h>
19 #define FCE2(x,y) (_pTemplate->*_fce)(x,y)
68 double RKSolve(
double x0,
double y0,
double x);
105 double RKCSolve(
double x0,
double y0,
double x,
double hTry);
139 double RKFSolve(
double x0,
double y0,
double x,
double hTry);
172 double RK4Method(
double x_i,
double w_i,
double h,
double dydx_i);
215 double RKFMethod(
double x_i,
double w_i,
double h,
double dydx_i,
double * wDiffPointer);
237 int nIter = (int)( 1/_eps );
238 double h = (x - x0)/nIter;
241 for(
int i=0; i<=nIter; i++) {
244 w_i = RK4Method(x_i, w_i, h,
FCE2(x_i, w_i));
247 if( (
double)(x_i+h) == x_i ) {
249 streamlog_out(ERROR) <<
"RunKutSolver::RKSolve: Stepsize is too small!!!"
257 streamlog_out(MESSAGE0) <<
" ODESolver - number of iterations: " << nIter+1 << std::endl;
289 double dydx_i =
FCE2(x_i, w_i);
292 if ( (x_i+h - x)*(x_i+h - x0) > 0.) h = x - x_i;
301 w_i1 = RK4Method(x_i, w_i, h, dydx_i);
304 w2_i1 = RK4Method(x_i, w_i, h2, dydx_i);
305 w2_i1 = RK4Method(x_i + h2, w2_i1, h2,
FCE2(x_i + h2, w2_i1));
309 double fraction = fabs(_eps/(w_i1 - w2_i1));
310 H = h * pow(15./16. * fraction, 0.2 );
315 h = ( ((2*H) > (0.1*h)) ? (2*H) : (0.1*h) );
329 if( (
double)(x_i+h) == x_i ) {
331 streamlog_out(ERROR) <<
"RunKutSolver::RKCSolve: Stepsize is too small!!!"
342 if ( (x_i - x)*(x - x0) >= 0. ) {
345 streamlog_out(MESSAGE0) <<
" ODESolver - number of iterations: " << nIter+1 << std::endl;
357 streamlog_out(ERROR) <<
"RunKutSolver::RKCSolve: Too many steps performed!!!"
387 double dydx_i =
FCE2(x_i, w_i);
390 if ( (x_i+h - x)*(x_i+h - x0) > 0.) h = x - x_i;
400 w_i1 = RKFMethod(x_i, w_i, h, dydx_i, &wDiff);
403 double fraction = fabs((_eps*h/(x - x0))/wDiff);
406 if (fraction <= 1.) {
409 H = 0.9 * h * pow(fraction, 0.25);
412 h = ( (H > (0.1*h)) ? H : (0.1*h) );
420 H = 0.9 * h * pow(fraction, 0.2);
428 if( (
double)(x_i+h) == x_i ) {
430 streamlog_out(ERROR) <<
"RunKutSolver::RKFSolve: Stepsize is too small!!!"
441 if ( (x_i - x)*(x - x0) >= 0. ) {
444 streamlog_out(MESSAGE0) <<
" ODESolver - number of iterations: " << nIter+1 << std::endl;
455 streamlog_out(ERROR) <<
"RunKutSolver::RKFSolve: Too many steps performed!!!"
468 double k1, k2, k3, k4;
475 k2 =
FCE2(x_i + h2, w_i + h2*k1);
478 k3 =
FCE2(x_i + h2, w_i + h2*k2);
481 k4 =
FCE2(x_i + h, w_i + h*k3);
484 Phi = 1./6. * (k1 + 2*k2 + 2*k3 + k4);
487 return (w_i + h*Phi);
496 static float a1 = 0.2, a2 = 0.3, a3 = 0.6, a4 = 1., a5 = 0.875;
497 static float b10= 0.2, b20= 0.075, b30= 0.3, b40=-11./54., b50= 1631./55296.,
498 b21= 0.225, b31=-0.9, b41= 2.5, b51= 175./512.,
499 b32= 1.2, b42=-70./27., b52= 575./13824.,
500 b43= 35./27., b53= 44275./110592.,
503 static float c0I = 37./378., c2I = 250./621., c3I = 125./594., c4I = 0., c5I = 512./1771.,
504 c0II = 2825./27648., c2II = 18575./48384., c3II = 13525./55296., c4II = 277./14336., c5II = 0.25,
505 difc0= c0I - c0II, difc2= c2I - c2II, difc3= c3I - c3II, difc4= c4I - c4II, difc5= c5I - c5II;
507 double f0, f1, f2, f3, f4, f5;
514 f1 =
FCE2(x_i + a1*h, w_i + h*(b10*f0));
517 f2 =
FCE2(x_i + a2*h, w_i + h*(b20*f0 + b21*f1));
520 f3 =
FCE2(x_i + a3*h, w_i + h*(b30*f0 + b31*f1 + b32*f2));
523 f4 =
FCE2(x_i + a4*h, w_i + h*(b40*f0 + b41*f1 + b42*f2 + b43*f3));
526 f5 =
FCE2(x_i + a5*h, w_i + h*(b50*f0 + b51*f1 + b52*f2 + b53*f3 + b54*f4));
529 PhiI = c0I*f0 + c2I*f2 + c3I*f3 + c5I*f5;
532 *wDiffPointer = h*(difc0*f0 + difc2*f2 + difc3*f3 + difc4*f4 + difc5*f5);
535 return (w_i + h*PhiI);
542 #endif // RUNKUTODESOLVER_H
double(T::* _fce)(double, double)
Relative pointer to an integrated function.
double RKCSolve(double x0, double y0, double x, double hTry)
This method returns a solution y(x) to the so-called ODE initial value problem (IVP), using 4th order Runge-Kutta method with adaptive stepsize control.
float _eps
Absolute precision (to hold "global" accumulation of errors constant)
double RKFSolve(double x0, double y0, double x, double hTry)
This method returns a solution y(x) to the so-called ODE initial value problem (IVP), using 5th(4th) order Runge-Kutta-Fehlberg method with adaptive stepsize control.
double RKFMethod(double x_i, double w_i, double h, double dydx_i, double *wDiffPointer)
This method based on 5th(4th) order Runge-Kutta-Fehlberg algorithm returns two approximations: w(x_i+...
~RunKutODESolver()
Destructor.
RunKutODESolver(double(T::*fce)(double, double), T *pTemplate, float eps)
Constructor - sets ODE right-hand side and required absolut accumulated precision.
double RK4Method(double x_i, double w_i, double h, double dydx_i)
This method based on 4th order Runge-Kutta algorithm returns an approximation w(x_i+1,h) to the exact solution y(x_i+1) of the so-called initial value problem (IVP) at position x_i+1 = x_i + h and using given "integration" stepsize h, where the IVP is defined as y' = f(x,y), y(x0) = y0 and for equidistant stepsizes h the coordinate x_i can be expressed as x_i = x0 + ih.
Double precision first-order ODE (IVP, i.e.
double RKSolve(double x0, double y0, double x)
This method returns a solution y(x) to the so-called ODE initial value problem (IVP), using 4th order Runge-Kutta method.
T * _pTemplate
Pointer to the template class.