#include #include #include "RK.h" /* Runge-Kutta-Fehlberg method solve an ordinary differential equation dx/dt = f(x,t) where x is an n-dimensional vector consisting of n variables. you can find how to use this function in rkf-solve-t0.c */ /* solve an ordinary differential equation dx/dt = f(x,t) from the k-th time step to the (k+1)-th time step input: n dimension of vector x x[] value of vector x at the k-th time step diff() procedure to compute f(x,t) *pt time at the k-th time step dt time step (interval) procedure diff() should be in the following form: diff(int n, double x[], double t, double v[]) n dimension of vector x x[] vector (n-dimensional array) t time v[] array where value of f(x,t) is stored (n-dimensional array) output: x[] value of vector x at the (k+1)-th time step *pt time at the (k+1)-th time step */ extern void RungeKuttaFehlbergOneStep(int n, double x[], void diff(int, double *, double, double *), double *pt, double dt) { int i; double t2, t3, t4, t5, t6; double x2[MaxVars], x3[MaxVars], x4[MaxVars], x5[MaxVars], x6[MaxVars]; double d1[MaxVars], d2[MaxVars], d3[MaxVars], d4[MaxVars], d5[MaxVars], d6[MaxVars]; diff(n, x, *pt, d1); /* comp. d1 */ t2 = (*pt) + (1./4.)*dt; for(i=0;i MaxVars) { fprintf(stderr, "%d exceeds MaxVars (%d)\n", n, MaxVars); fprintf(stderr, "increase MaxVars in opt.h and recompile all\n"); exit(1); } for(k=1; k<=kcnt; k++) { #if DEBUG printf("<<<<< count = %d >>>>>\n", k); #endif RungeKuttaFehlbergOneStep(n, x, diff, pt, dt); RungeKuttaFehlbergfprint(fd, n, x, *pt); } } /* Adaptive Runge-Kutta-Fehlberg formula solve an ordinary differential equation dx/dt = f(x,t). time interval is updated adaptively you can find how to use this function in rkf-solve-adp-t0.c */ #define SafetyRatio 0.80 #define Allowance 1e-6 #define PowerTwo(a) ((a)*(a)) #define PowerFive(a) ((a)*(a)*(a)*(a)*(a)) extern void RungeKuttaFehlbergAdaptiveOneStep(int n, double x[], void diff(int, double *, double, double *), double *pt, double *pdt) { int i; double t1, t2, t3, t4, t5, t6; double x1[MaxVars], x2[MaxVars], x3[MaxVars], x4[MaxVars], x5[MaxVars], x6[MaxVars]; double d1[MaxVars], d2[MaxVars], d3[MaxVars], d4[MaxVars], d5[MaxVars], d6[MaxVars]; double xest[MaxVars]; double dt, error, limit; dt = (*pdt); /* current time step */ t1 = (*pt); for(i=0;i Allowance * PowerFive(SafetyRatio)) { limit = SafetyRatio * dt * pow(Allowance/error,0.20); while (*pdt > limit) { *pdt = (*pdt)/2; } } else { limit = SafetyRatio * dt * pow(Allowance/error,0.20); while ( 2*(*pdt) < limit) { *pdt = (*pdt)*2; } } } extern void RungeKuttaFehlbergAdaptivefprint(FILE *fd, int n, double x[], double t, double dt) { int i; fprintf(fd, format, t); for(i=0;i MaxVars) { fprintf(stderr, "%d exceeds MaxVars (%d)\n", n, MaxVars); fprintf(stderr, "increase MaxVars in opt.h and recompile all\n"); exit(1); } for(k=1; k<=kcnt; k++) { #if DEBUG printf("<<<<< count = %d dt = %lf >>>>>\n", k, *pdt); #endif RungeKuttaFehlbergAdaptiveOneStep(n, x, diff, pt, pdt); RungeKuttaFehlbergAdaptivefprint(fd, n, x, *pt, *pdt); if ((*pt) > tend) break; } }