#include <cmath>
|
|
#include <iostream>
|
|
#include "lsode.h"
|
|
//#include "simulation.h"
|
|
#include "c++rocket.h"
|
|
|
|
//typedef int (* ModelFunc)(const int &, const double &, double *,
|
|
// double *, int &);
|
|
|
|
char *error_msg(State s);
|
|
|
|
static int ModelNeq[MODEL_LAST] = { 7, 5 };
|
|
|
|
lsode::lsode(Model_t model) {
|
|
|
|
memory = 0;
|
|
|
|
neq = ModelNeq[model];
|
|
//dy = new double*[7];
|
|
time = 0.0;
|
|
|
|
itol = 1;
|
|
rtol = 1.49012e-08;
|
|
atol = 1.49012e-08;
|
|
itask = 1;
|
|
istate = 1;
|
|
iopt = 0;
|
|
|
|
rwork = new double[20+16*neq];
|
|
lrw = 20+16*neq;
|
|
iwork = new int[20];
|
|
liw = 20;
|
|
mf = 10;
|
|
state = new double[neq];
|
|
|
|
if (!rwork) {
|
|
cout << "Allocation error\n";
|
|
exit(-1);
|
|
}
|
|
|
|
switch (model)
|
|
{
|
|
case AERO_MODEL:
|
|
md = model_1;
|
|
break;
|
|
case SIMPLE_MODEL:
|
|
md = model_2;
|
|
break;
|
|
default:
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
lsode::~lsode() {
|
|
|
|
if (memory) {
|
|
for (int j = 0; j < neq; j++)
|
|
delete [] dy[j];
|
|
delete dy;
|
|
}
|
|
|
|
delete [] state;
|
|
delete [] iwork;
|
|
delete [] rwork;
|
|
cout << "Freeing memory...\n" ;
|
|
}
|
|
|
|
int lsode::solve(double *st, double duration, double step)
|
|
{
|
|
reset();
|
|
|
|
if (memory) {
|
|
for (int j = 0; j < neq; j++)
|
|
delete [] dy[j];
|
|
delete dy;
|
|
|
|
memory = 0;
|
|
}
|
|
|
|
length = (int)rint(duration/step);
|
|
|
|
// on alloue la memoire
|
|
dy = new double*[neq];
|
|
for (int j = 0; j < neq; j++)
|
|
dy[j] = new double[length];
|
|
|
|
memory = 1; // pour indiquer que l'on a alloue la memoire
|
|
|
|
// on simule et on remplie l'array
|
|
for (int i = 0; i < length; i++) {
|
|
tout = i*step;
|
|
|
|
|
|
lsode_((ModelFunc_t)md, neq, st, time, tout, itol, rtol, atol,
|
|
itask, istate, iopt, rwork, lrw, iwork, liw, NULL, mf);
|
|
|
|
for (int j = 0; j < neq ; j++)
|
|
dy[j][i] = st[j];
|
|
|
|
if (istate < 0) // if any error, stop the simulation
|
|
{
|
|
cout << "ERROR: " << error_msg ((State)istate) << endl;
|
|
cout << i << " points out of " << length << " were found."
|
|
<< endl;
|
|
return i;
|
|
}
|
|
|
|
}
|
|
|
|
cout << "Simulation completed successfully." << endl;
|
|
cout << length << " " << "points computed" << endl;
|
|
|
|
return length;
|
|
}
|
|
|
|
void lsode::reset()
|
|
{
|
|
tout = 0.0; // restart the simulation at 0
|
|
time = 0.0; // restart the time at 0
|
|
istate = 1; // should reset the istate
|
|
}
|
|
|
|
void lsode::print() {
|
|
for (int i = 0; i < length; i++) {
|
|
for (int j = 0; j < neq; j++) {
|
|
cout << dy[j][i] << "\t";
|
|
}
|
|
cout << "\n";
|
|
}
|
|
}
|
|
|
|
|
|
void lsode::get_data(double** a)
|
|
{
|
|
for (int i = 0; i < length; i++)
|
|
for (int j = 0; j < neq; j++)
|
|
a[j][i] = dy[j][i];
|
|
}
|
|
|
|
|
|
|
|
|
|
char *error_msg(State s)
|
|
{
|
|
switch (s)
|
|
{
|
|
case TOO_MUCH_WORK:
|
|
return "Excess work done on this call (perhaps wrong mf).";
|
|
break;
|
|
|
|
case TOO_MUCH_ACC:
|
|
return "Excess Accuracy Requested (Tolerances too small).";
|
|
break;
|
|
|
|
case ILLEGAL_INPUT:
|
|
return "Illegal input detected.";
|
|
break;
|
|
|
|
case ERR_FAILURE:
|
|
return "Repeated error test failures.";
|
|
break;
|
|
|
|
case CONV_FAILURE:
|
|
return "Repeated convergence failures.";
|
|
break;
|
|
|
|
case ERROR_WEIGHT:
|
|
return "Error weight became zero during problem.";
|
|
break;
|
|
|
|
case EXIT_IN_FUNCTION:
|
|
return "Exit requested in ode function.";
|
|
break;
|
|
|
|
default:
|
|
return "Unrecognize error state.";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|