5 template <
class Functor>
7 const size_t neq, std::vector<double> &y, Functor &derivs,
void *_data)
11 size_t i = 0, ier = 0, j = 0;
12 double fac = 0.0, hl0 = 0.0, r = 0.0, r0 = 0.0, yj = 0.0;
32 fprintf(stderr,
"[prja] miter != 2\n");
37 r0 = 1000. * fabs(
h_) *
ETA * ((double)
n) * fac;
40 for(j = 1; j <=
n; j++) {
45 derivs(
tn_, ++y.begin(), ++
acor.begin(), _data);
46 for(i = 1; i <=
n; i++)
58 for(i = 1; i <=
n; i++)
77 template <
class Functor>
79 size_t *corflag,
double pnorm,
double *del,
double *delp,
double *told,
size_t *ncf,
80 double *rh,
size_t *m,
void *_data)
82 double rm = 0.0, rate = 0.0, dcon = 0.0;
95 for(
size_t i = 1; i <=
n; i++)
98 derivs(
tn_, ++y.begin(), ++
savf.begin(), _data);
109 prja(neq, y, derivs, _data);
119 for(
size_t i = 1; i <=
n; i++)
127 for(
size_t i = 1; i <=
n; i++) {
132 for(
size_t i = 1; i <=
n; i++) {
144 for(
size_t i = 1; i <=
n; i++)
150 for(
size_t i = 1; i <=
n; i++) {
167 if(*del <= 100. * pnorm *
ETA)
169 if(*m != 0 ||
meth_ != 1) {
172 if(*del <= (1024. * *delp))
174 rate = std::max(rate, rm);
193 if(*m ==
maxcor || (*m >= 2 && *del > 2. * *delp)) {
205 for(
size_t i = 1; i <=
n; i++)
208 derivs(
tn_, ++y.begin(), ++
savf.begin(), _data);
217 derivs(
tn_, ++y.begin(), ++
savf.begin(), _data);
224 template <
class Functor>
226 const size_t neq, std::vector<double> &y, Functor &derivs,
void *_data)
228 assert(neq + 1 == y.size());
230 size_t corflag = 0, orderflag = 0;
231 size_t i = 0, i1 = 0, j = 0, m = 0, ncf = 0;
232 double del = 0.0, delp = 0.0, dsm = 0.0, dup = 0.0, exup = 0.0, r = 0.0, rh = 0.0,
233 rhup = 0.0, told = 0.0;
234 double pdh = 0.0, pnorm = 0.0;
305 for(i = 1; i <= 5; i++)
308 for(i = 1; i <= 12; i++)
363 for(
size_t j =
nq; j >= 1; j--)
364 for(
size_t i1 = j; i1 <=
nq; i1++)
365 for(i = 1; i <=
n; i++)
366 yh_[i1][i] +=
yh_[i1 + 1][i];
370 neq, y, derivs, &corflag, pnorm, &del, &delp, &told, &ncf, &rh, &m, _data);
374 rh = std::max(rh,
hmin / fabs(
h_));
416 for(
size_t j = 1; j <=
l; j++) {
418 for(i = 1; i <=
n; i++)
425 rh = std::max(rh,
hmin / fabs(
h_));
439 for(i = 1; i <=
n; i++)
442 exup = 1. / (double)(
l + 1);
443 rhup = 1. / (1.4 * pow(dup, exup) + 0.0000014);
459 rh = std::max(rh,
hmin / fabs(
h_));
470 rh = std::max(rh,
hmin / fabs(
h_));
482 for(
size_t i = 1; i <=
n; i++)
499 for(j =
nq; j >= 1; j--) {
500 for(i1 = j; i1 <=
nq; i1++)
501 for(i = 1; i <=
n; i++)
502 yh_[i1][i] -=
yh_[i1 + 1][i];
505 if(fabs(
h_) <=
hmin * 1.00001) {
514 if(orderflag == 1 || orderflag == 0) {
516 rh = std::min(rh, 0.2);
517 rh = std::max(rh,
hmin / fabs(
h_));
522 rh = std::max(rh,
hmin / fabs(
h_));
546 rh = std::max(
hmin / fabs(
h_), rh);
548 for(i = 1; i <=
n; i++)
550 derivs(
tn_, ++y.begin(), ++
savf.begin(), _data);
552 for(i = 1; i <=
n; i++)
577 template<
class AfterStep>
579 std::vector<double> &y,
double *t,
int itask,
int ihit,
double tcrit,
int *istate)
581 for(
size_t i = 1; i <=
n; i++)
584 if(itask == 4 || itask == 5)
590 after_step(*t, ++y.begin());
605 template <
class Functor,
class AfterStep>
606 void LSODA::lsoda(Functor &derivs, AfterStep &after_step,
const size_t neq, std::vector<double> &y,
double *t,
607 double tout,
int itask,
int *istate,
int iopt,
int jt, std::array<int, 7> &iworks,
608 std::array<double, 4> &rworks,
void *_data)
612 int mxstp0 = 500, mxhnl0 = 10;
614 int iflag = 0, lenyh = 0, ihit = 0;
616 double atoli = 0, ayi = 0, big = 0, h0 = 0, hmax = 0, hmx = 0, rh = 0, rtoli = 0,
617 tcrit = 0, tdist = 0, tnext = 0, tol = 0, tolsf = 0, tp = 0, size = 0, sum = 0,
629 if(*istate < 1 || *istate > 3) {
631 std::cerr <<
"[lsoda] illegal istate = " << *istate << std::endl;
635 if(itask < 1 || itask > 5) {
636 fprintf(stderr,
"[lsoda] illegal itask = %d\n", itask);
640 if(
init == 0 && (*istate == 2 || *istate == 3)) {
641 fprintf(stderr,
"[lsoda] istate > 1 but lsoda not initialized\n");
656 if(*istate == 1 || *istate == 3) {
659 std::cerr <<
"[lsoda] neq = " << neq <<
" is less than 1." << std::endl;
663 if(*istate == 3 && neq >
n) {
664 std::cerr <<
"[lsoda] istate = 3 and neq increased" << std::endl;
669 if(itol_ < 1 || itol_ > 4) {
670 std::cerr <<
"[lsoda] itol = " <<
itol_ <<
" illegal" << std::endl;
674 if(iopt < 0 || iopt > 1) {
675 std::cerr <<
"[lsoda] iopt = " << iopt <<
" illegal" << std::endl;
679 if(jt == 3 || jt < 1 || jt > 5) {
680 std::cerr <<
"[lsoda] jt = " << jt <<
" illegal" << std::endl;
689 std::cerr <<
"[lsoda] ml = " <<
ml <<
" not between 1 and neq" << std::endl;
694 std::cerr <<
"[lsoda] mu = " <<
mu <<
" not between 1 and neq" << std::endl;
720 std::cerr <<
"[lsoda] ixpr = " <<
ixpr <<
" is illegal" << std::endl;
746 if((tout - *t) * h0 < 0.) {
747 std::cerr <<
"[lsoda] tout = " << tout <<
" behind t = " << *t
748 <<
". integration direction is given by " << h0 << std::endl;
755 std::cerr <<
"[lsoda] hmax < 0." << std::endl;
765 std::cerr <<
"[lsoda] hmin < 0." << std::endl;
799 if(*istate == 1 || *istate == 3) {
802 for(
size_t i = 1; i <=
n; i++) {
808 fprintf(stderr,
"[lsoda] rtol = %g is less than 0.\n", rtoli);
813 fprintf(stderr,
"[lsoda] atol = %g is less than 0.\n", atoli);
835 if(itask == 4 || itask == 5) {
837 if((tcrit - tout) * (tout - *t) < 0.) {
838 fprintf(stderr,
"[lsoda] itask = 4 or 5 and tcrit behind tout\n");
842 if(h0 != 0. && (*t + h0 - tcrit) * h0 > 0.)
861 assert((
int)
yh_.size() == lenyh + 1);
862 assert(
yh_[0].size() ==
nyh + 1);
864 derivs(*t, ++y.begin(), ++
yh_[2].begin(), _data);
868 for(
size_t i = 1; i <=
n; i++)
875 for(
size_t i = 1; i <=
n; i++) {
877 std::cerr <<
"[lsoda] ewt[" << i <<
"] = " <<
ewt[i] <<
" <= 0.\n" << std::endl;
905 tdist = fabs(tout - *t);
906 w0 = std::max(fabs(*t), fabs(tout));
907 if(tdist < 2. *
ETA * w0) {
908 fprintf(stderr,
"[lsoda] tout too close to t to start integration\n ");
914 for(
size_t i = 2; i <=
n; i++)
915 tol = std::max(tol,
rtol_[i]);
919 for(
size_t i = 1; i <=
n; i++) {
924 tol = std::max(tol, atoli / ayi);
927 tol = std::max(tol, 100. *
ETA);
928 tol = std::min(tol, 0.001);
930 sum = 1. / (tol * w0 * w0) + tol * sum * sum;
932 h0 = std::min(h0, tdist);
933 h0 = h0 * ((tout - *t >= 0.) ? 1. : -1.);
938 rh = fabs(h0) *
hmxi;
946 for(
size_t i = 1; i <=
n; i++)
954 if(*istate == 2 || *istate == 3) {
958 if((
tn_ - tout) *
h_ >= 0.) {
959 intdy(tout, 0, y, &iflag);
962 "[lsoda] trouble from intdy, itask = %d, tout = %g\n", itask,
977 if((tp - tout) *
h_ > 0.) {
979 stderr,
"[lsoda] itask = %d and tout behind tcur - hu\n", itask);
983 if((
tn_ - tout) *
h_ < 0.)
989 if((
tn_ - tcrit) *
h_ > 0.) {
990 fprintf(stderr,
"[lsoda] itask = 4 or 5 and tcrit behind tcur\n");
994 if((tcrit - tout) *
h_ < 0.) {
995 fprintf(stderr,
"[lsoda] itask = 4 or 5 and tcrit behind tout\n");
999 if((
tn_ - tout) *
h_ >= 0.) {
1000 intdy(tout, 0, y, &iflag);
1003 "[lsoda] trouble from intdy, itask = %d, tout = %g\n", itask,
1011 after_step(*t, ++y.begin());
1018 if((
tn_ - tcrit) *
h_ > 0.) {
1019 fprintf(stderr,
"[lsoda] itask = 4 or 5 and tcrit behind tcur\n");
1024 hmx = fabs(
tn_) + fabs(
h_);
1025 ihit = fabs(
tn_ - tcrit) <= (100. *
ETA * hmx);
1028 successreturn(after_step, y, t, itask, ihit, tcrit, istate);
1031 tnext =
tn_ +
h_ * (1. + 4. *
ETA);
1032 if((tnext - tcrit) *
h_ <= 0.)
1034 h_ = (tcrit -
tn_) * (1. - 4. *
ETA);
1052 if(*istate != 1 ||
nst != 0) {
1054 std::cerr <<
"[lsoda] " <<
mxstep <<
" steps taken before reaching tout" 1062 for(
size_t i = 1; i <=
n; i++) {
1064 std::cerr <<
"[lsoda] ewt[" << i <<
"] = " <<
ewt[i] <<
" <= 0." << std::endl;
1074 tolsf = tolsf * 200.;
1076 fprintf(stderr,
"lsoda -- at start of problem, too much accuracy\n");
1077 fprintf(stderr,
" requested for precision of machine,\n");
1078 fprintf(stderr,
" suggested scaling factor = %g\n", tolsf);
1082 fprintf(stderr,
"lsoda -- at t = %g, too much accuracy requested\n", *t);
1083 fprintf(stderr,
" for precision of machine, suggested\n");
1084 fprintf(stderr,
" scaling factor = %g\n", tolsf);
1093 fprintf(stderr,
"lsoda -- warning..internal t = %g and h_ = %g are\n",
1096 " such that in the machine, t + h_ = t on the next step\n");
1097 fprintf(stderr,
" solver will continue anyway.\n");
1099 std::cerr <<
"lsoda -- above warning has been issued " <<
nhnil 1100 <<
" times, " << std::endl
1101 <<
" it will not be issued again for this problem" << std::endl;
1107 stoda(neq, y, derivs, _data);
1118 if (
tn_ < tout) after_step(
tn_, ++y.begin());
1129 std::cerr <<
"[lsoda] a switch to the stiff method has occurred " 1132 std::cerr <<
"[lsoda] a switch to the nonstiff method has occurred" 1141 if((
tn_ - tout) *
h_ < 0.)
1144 intdy(tout, 0, y, &iflag);
1148 after_step(*t, ++y.begin());
1155 successreturn(after_step, y, t, itask, ihit, tcrit, istate);
1163 if((
tn_ - tout) *
h_ >= 0.) {
1164 successreturn(after_step, y, t, itask, ihit, tcrit, istate);
1174 if((
tn_ - tout) *
h_ >= 0.) {
1175 intdy(tout, 0, y, &iflag);
1179 after_step(*t, ++y.begin());
1183 hmx = fabs(
tn_) + fabs(
h_);
1184 ihit = fabs(
tn_ - tcrit) <= (100. *
ETA * hmx);
1186 successreturn(after_step, y, t, itask, ihit, tcrit, istate);
1189 tnext =
tn_ +
h_ * (1. + 4. *
ETA);
1190 if((tnext - tcrit) *
h_ <= 0.)
1192 h_ = (tcrit -
tn_) * (1. - 4. *
ETA);
1202 hmx = fabs(
tn_) + fabs(
h_);
1203 ihit = fabs(
tn_ - tcrit) <= (100. *
ETA * hmx);
1204 successreturn(after_step, y, t, itask, ihit, tcrit, istate);
1214 fprintf(stderr,
"lsoda -- at t = %g and step size h_ = %g, the\n",
tn_,
h_);
1216 fprintf(stderr,
" error test failed repeatedly or\n");
1217 fprintf(stderr,
" with fabs(h_) = hmin\n");
1221 fprintf(stderr,
" corrector convergence failed repeatedly or\n");
1222 fprintf(stderr,
" with fabs(h_) = hmin\n");
1227 for(
size_t i = 1; i <=
n; i++) {
1228 size = fabs(
acor[i]) *
ewt[i];
1256 template <
class Functor,
class AfterStep>
1258 double *t,
const double tout,
void *_data,
1259 double rtol,
double atol)
1261 std::array<int, 7> iworks = {{0}};
1262 std::array<double, 4> rworks = {{0.0}};
1264 int itask, iopt, jt;
1272 yout.resize(neq + 1);
1275 rtol_.resize(neq + 1, rtol);
1276 atol_.resize(neq + 1, atol);
1281 for(
size_t i = 1; i <= neq; i++)
1284 lsoda(derivs, after_step, neq,
yout, t, tout, itask, &
iState, iopt, jt, iworks, rworks, _data);
1286 for (
int i=0; i<y.size(); ++i) y[i] =
yout[i+1];
void orderswitch(double *rhup, double dsm, double *pdh, double *rh, size_t *orderflag)
std::vector< double > savf
std::array< std::array< double, 14 >, 13 > elco
void prja(const size_t neq, std::vector< double > &y, Functor &derivs, void *_data)
void terminate(int *istate)
std::vector< std::vector< double > > yh_
std::vector< std::vector< double > > wm_
void ewset(const std::vector< double > &ycur)
void scaleh(double *rh, double *pdh)
void correction(const size_t neq, std::vector< double > &y, Functor &derivs, size_t *corflag, double pnorm, double *del, double *delp, double *told, size_t *ncf, double *rh, size_t *m, void *_data)
void solsy(std::vector< double > &y)
std::vector< double > ewt
double vmnorm(const size_t n, const std::vector< double > &v, const std::vector< double > &w)
void lsoda_update(Functor &derivs, AfterStep &after_step, const size_t neq, std::vector< double > &y, double *t, const double tout, void *const _data, double rtol=1e-6, double atol=1e-6)
double fnorm(int n, const std::vector< std::vector< double >> &a, const std::vector< double > &w)
void successreturn(AfterStep &after_step, std::vector< double > &y, double *t, int itask, int ihit, double tcrit, int *istate)
std::array< std::array< double, 4 >, 13 > tesco
std::array< size_t, 3 > mord
std::array< double, 13 > cm1
void terminate2(std::vector< double > &y, double *t)
void intdy(double t, int k, std::vector< double > &dky, int *iflag)
void corfailure(double *told, double *rh, size_t *ncf, size_t *corflag)
std::vector< double > acor
void resize_system(int nyh, int lenyh)
void methodswitch(double dsm, double pnorm, double *pdh, double *rh)
void lsoda(Functor &derivs, AfterStep &after_step, const size_t neq, std::vector< double > &y, double *t, double tout, int itask, int *istate, int iopt, int jt, std::array< int, 7 > &iworks, std::array< double, 4 > &rworks, void *_data)
std::vector< double > atol_
void dgefa(std::vector< std::vector< double >> &a, const size_t n, std::vector< int > &ipvt, size_t *const info)
void stoda(const size_t neq, std::vector< double > &y, Functor &derivs, void *_data)
std::vector< double > yout
std::array< double, 6 > cm2
std::vector< double > rtol_
std::array< double, 14 > el