Taken from sources in CVS at: https://sourceforge.net/projects/rocketworkbench/ Sources extracted in two steps: 1. Pull entire project tree into a subdir "rwb" via "rsync": rsync -a a.cvs.sourceforge.net::cvsroot/rocketworkbench/ rwb/. 2. Export sources: export CVSROOT=$(pwd)/rwb SUBDIRS="analyser cpropep cpropep-web CVSROOT data libcompat libcpropep libnum libsimulation libthermo prop rocketworkbench rockflight" mkdir rwbx; cd rwbx cvs export -D now ${SUBDIRS} After this (and some backups for safety), the directory content was added to a Git repo: git init . git add *
180 lines
3.7 KiB
C
180 lines
3.7 KiB
C
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
|
|
#include "num.h"
|
|
|
|
/* neq: number of equations
|
|
* step: initial time step
|
|
* duration: total duration of the simulation
|
|
* ic: initial conditions vector
|
|
* y: solution vector
|
|
* epsil: precision on the data
|
|
* data: pointer to data structure
|
|
*/
|
|
|
|
/* Runge-Kutta-Fehlberg 4-5 order */
|
|
|
|
int NUM_rkf(int (*f)(int neq, double time, double *y, double *dy, void *data),
|
|
int neq, double step, double duration, double *ic,
|
|
double **y, double epsil, void *data)
|
|
{
|
|
int i;
|
|
int n;
|
|
|
|
int col;
|
|
|
|
double h;
|
|
double t = 0.0;
|
|
|
|
double *a;
|
|
|
|
double *tmp;
|
|
double *dy;
|
|
double *K1, *K2, *K3, *K4, *K5, *K6;
|
|
|
|
double *E; /* Error vector of the error */
|
|
|
|
double err; /* maximum error */
|
|
double beta;
|
|
|
|
tmp = (double *) malloc(sizeof(double) * neq);
|
|
dy = (double *) malloc(sizeof(double) * neq);
|
|
|
|
E = (double *) malloc(sizeof(double) * neq);
|
|
|
|
K1 = (double *) malloc(sizeof(double) * neq);
|
|
K2 = (double *) malloc(sizeof(double) * neq);
|
|
K3 = (double *) malloc(sizeof(double) * neq);
|
|
K4 = (double *) malloc(sizeof(double) * neq);
|
|
K5 = (double *) malloc(sizeof(double) * neq);
|
|
K6 = (double *) malloc(sizeof(double) * neq);
|
|
|
|
|
|
h = step;
|
|
n = 0;
|
|
|
|
col = neq + 1;
|
|
|
|
a = *y = (double *) malloc(sizeof(double) * col * (n + 1));
|
|
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
tmp[i] = a[i + col*0] = ic[i]; /* initial conditions */
|
|
}
|
|
|
|
while (t < duration)
|
|
{
|
|
a = *y = (double *) realloc(*y, sizeof(double) * col * (n + 2));
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
f(neq, t, tmp, dy, data);
|
|
K1[i] = h * dy[i];
|
|
|
|
tmp[i] = a[i + col*n] + K1[i]/4.0; /* for the next step */
|
|
}
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
f(neq, t + h/4.0, tmp, dy, data);
|
|
K2[i] = h * dy[i];
|
|
|
|
tmp[i] = a[i + col*n] + 3.0*K1[i]/32.0 + 9.0*K2[i]/32.0;
|
|
|
|
}
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
f(neq, t + 3.0*h/8.0, tmp, dy, data);
|
|
K3[i] = h * dy[i];
|
|
|
|
tmp[i] = a[i + col*n] + 1932.0*K1[i]/2197.0 - 7200.0*K2[i]/2197.0 +
|
|
7296.0*K3[i]/2197.0;
|
|
}
|
|
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
f(neq, t + 12.0*h/13.0, tmp, dy, data);
|
|
K4[i] = h * dy[i];
|
|
|
|
tmp[i] = a[i + col*n] + 439.0*K1[i]/216.0 - 8.0*K2[i] +
|
|
3680.0*K3[i]/513.0 - 845.0*K4[i]/4104.0;
|
|
}
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
f(neq, t + h, tmp, dy, data);
|
|
K5[i] = h * dy[i];
|
|
|
|
tmp[i] = a[i + col*n] - 8.0*K1[i]/27.0 + 2.0*K2[i] -
|
|
3544.0*K3[i]/2565.0 + 1859.0*K4[i]/4104.0 - 11.0*K5[i]/40.0;
|
|
}
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
f(neq, t + h/2.0, tmp, dy, data);
|
|
K6[i] = h * dy[i];
|
|
}
|
|
|
|
err = 0.0;
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
E[i] = fabs(K1[i]/360.0 - 128.0*K3[i]/4275.0 - 2197.0*K4[i]/75240.0 +
|
|
K5[i]/50.0 + 2.0*K6[i]/55.0); /* /h ?? */
|
|
//printf("E[%d] = %f\n", i, E[i]);
|
|
err = ((E[i] > err) ? E[i] : err);
|
|
}
|
|
|
|
//printf("err = %e\n", err);
|
|
|
|
if ((err < epsil) || (h <= step/1000) )
|
|
{
|
|
t += h;
|
|
|
|
for (i = 0; i < neq; i++)
|
|
{
|
|
a[i + col*(n+1)] = a[i + col*n] + 25.0*K1[i]/216.0 +
|
|
1408.0*K3[i]/2565.0 + 2197.0*K4[i]/4104.0 - 0.2*K5[i];
|
|
}
|
|
/* store the time */
|
|
a[neq + col*(n+1)] = t;
|
|
n++;
|
|
}
|
|
|
|
beta = pow(epsil/(2*err), 0.25);
|
|
|
|
if (beta < 0.1)
|
|
{
|
|
h = 0.1* h;
|
|
}
|
|
else if (beta > 4)
|
|
{
|
|
h = 4.0*h;
|
|
}
|
|
else
|
|
{
|
|
h = beta * h;
|
|
}
|
|
|
|
/* we have to prevent too little h*/
|
|
if (h < step/1000)
|
|
h = step/1000;
|
|
|
|
/* prevent too big */
|
|
if (h > duration/16)
|
|
h = duration/16;
|
|
|
|
if (t + h > duration)
|
|
{
|
|
h = duration - t;
|
|
}
|
|
|
|
}
|
|
|
|
return n+1;
|
|
}
|
|
|