38 sm1 = {{0., 0.5, 0.575, 0.55, 0.45, 0.35, 0.25, 0.2, 0.15, 0.1, 0.075, 0.05, 0.025}};
50 return (std::abs(a) < std::abs(b));
54 size_t LSODA::idamax1(
const vector<double> &dx,
const size_t n,
const size_t offset = 0)
57 size_t v = 0, vmax = 0;
59 for(
size_t i = 1; i <= n; i++) {
60 v = abs(dx[i + offset]);
77 const double da, vector<double> &dx,
const size_t n,
const size_t offset = 0)
82 std::transform(dx.begin() + 1 + offset, dx.end(), dx.begin() + 1 + offset,
83 [&da](
double x) ->
double {
return da * x; });
87 double LSODA::ddot1(
const vector<double> &a,
const vector<double> &b,
const size_t n,
88 const size_t offsetA = 0,
const size_t offsetB = 0)
91 for(
size_t i = 1; i <= n; i++)
92 sum += a[i + offsetA] * b[i + offsetB];
96 void LSODA::daxpy1(
const double da,
const vector<double> &dx, vector<double> &dy,
97 const size_t n,
const size_t offsetX = 0,
const size_t offsetY = 0)
100 for(
size_t i = 1; i <= n; i++)
101 dy[i + offsetY] = da * dx[i + offsetX] + dy[i + offsetY];
105 void LSODA::dgesl(
const vector<vector<double>> &a,
const size_t n, vector<int> &ipvt,
106 vector<double> &b,
const size_t job)
118 for(k = 1; k <= n; k++) {
119 t = ddot1(a[k], b, k - 1);
120 b[k] = (b[k] - t) / a[k][k];
125 for(k = n - 1; k >= 1; k--) {
126 b[k] = b[k] + ddot1(a[k], b, n - k, k, k);
141 for(k = 1; k <= n - 1; k++) {
148 daxpy1(t, a[k], b, n - k, k, k);
153 for(k = n; k >= 1; k--) {
154 b[k] = b[k] / a[k][k];
156 daxpy1(t, a[k], b, k - 1);
162 vector<vector<double>> &a,
const size_t n, vector<int> &ipvt,
size_t *
const info)
164 size_t j = 0, k = 0, i = 0;
170 for(k = 1; k <= n - 1; k++) {
175 j = idamax1(a[k], n - k + 1, k - 1) + k - 1;
196 dscal1(t, a[k], n - k, k);
201 for(i = k + 1; i <= n; i++) {
207 daxpy1(t, a[k], a[i], n - k, k, k);
220 cerr <<
"[lsoda] repeated occurrence of illegal input. run aborted.. " 221 "apparent infinite loop." 232 for(
size_t i = 1; i <= n; i++)
245 for(
size_t i = 1; i <= n; i++)
246 ewt[i] = rtol_[1] * fabs(ycur[i]) + atol_[1];
249 for(
size_t i = 1; i <= n; i++)
250 ewt[i] = rtol_[1] * fabs(ycur[i]) + atol_[i];
253 for(
size_t i = 1; i <= n; i++)
254 ewt[i] = rtol_[i] * fabs(ycur[i]) + atol_[1];
257 for(
size_t i = 1; i <= n; i++)
258 ewt[i] = rtol_[i] * fabs(ycur[i]) + atol_[i];
292 if(k < 0 || k > (
int)nq) {
293 fprintf(stderr,
"[intdy] k = %d illegal\n", k);
297 tp = tn_ - hu - 100. * ETA * (tn_ + hu);
298 if((t - tp) * (t - tn_) > 0.) {
300 stderr,
"intdy -- t = %g illegal. t not in interval tcur - hu to tcur\n", t);
306 for(
size_t jj = l - k; jj <= nq; jj++)
309 for(
size_t i = 1; i <= n; i++)
310 dky[i] = c * yh_[l][i];
312 for(
int j = nq - 1; j >= k; j--) {
315 for(
int jj = jp1 - k; jj <= j; jj++)
319 for(
size_t i = 1; i <= n; i++)
320 dky[i] = c * yh_[jp1][i] + s * dky[i];
324 r = pow(h_, (
double)(-k));
326 for(
size_t i = 1; i <= n; i++)
333 int i, nq, nqm1, nqp1;
334 double agamq, fnq, fnqm1, pc[13], pint, ragq, rqfac, rq1fac, tsign, xpin;
376 for(nq = 2; nq <= 12; nq++) {
385 rqfac = rqfac / (double)nq;
387 fnqm1 = (double)nqm1;
393 for(i = nq; i >= 2; i--)
394 pc[i] = pc[i - 1] + fnqm1 * pc[i];
395 pc[1] = fnqm1 * pc[1];
402 for(i = 2; i <= nq; i++) {
404 pint += tsign * pc[i] / (double)i;
405 xpin += tsign * pc[i] / (double)(i + 1);
410 elco[nq][1] = pint * rq1fac;
412 for(i = 2; i <= nq; i++)
413 elco[nq][i + 1] = rq1fac * pc[i] / (
double)i;
414 agamq = rqfac * xpin;
418 tesco[nqp1][1] = ragq * rqfac / (double)nqp1;
419 tesco[nqm1][3] = ragq;
433 for(nq = 1; nq <= 5; nq++) {
440 for(i = nq + 1; i >= 2; i--)
441 pc[i] = pc[i - 1] + fnq * pc[i];
446 for(i = 1; i <= nqp1; i++)
447 elco[nq][i] = pc[i] / pc[2];
449 tesco[nq][1] = rq1fac;
450 tesco[nq][2] = ((double)nqp1) / elco[nq][1];
451 tesco[nq][3] = ((double)(nq + 2)) / elco[nq][1];
467 *rh = min(*rh, rmax);
468 *rh = *rh / max(1., fabs(h_) * hmxi * *rh);
476 *pdh = max(fabs(h_) * pdlast, 0.000001);
477 if((*rh * *pdh * 1.00001) >= sm1[nq]) {
478 *rh = sm1[nq] / *pdh;
483 for(
size_t j = 2; j <= l; j++) {
485 for(
size_t i = 1; i <= n; i++)
501 double LSODA::vmnorm(
const size_t n,
const vector<double> &v,
const vector<double> &w)
504 for(
size_t i = 1; i <= n; i++)
505 vm = max(vm, fabs(v[i]) * w[i]);
509 double LSODA::fnorm(
int n,
const vector<vector<double>> &a,
const vector<double> &w)
520 double an = 0, sum = 0;
522 for(
size_t i = 1; i <= (size_t)n; i++) {
524 for(
size_t j = 1; j <= (size_t)n; j++)
525 sum += fabs(a[i][j]) / w[j];
526 an = max(an, sum * w[i]);
537 for(
size_t j = nq; j >= 1; j--)
538 for(
size_t i1 = j; i1 <= nq; i1++)
539 for(
size_t i = 1; i <= n; i++)
540 yh_[i1][i] -= yh_[i1 + 1][i];
542 if(fabs(h_) <= hmin * 1.00001 || *ncf == mxncf) {
564 printf(
"solsy -- miter != 2\n");
568 dgesl(wm_, n, ipvt, y, 0);
574 int lm1, lm1p1, lm2, lm2p1, nqm1, nqm2;
575 double rh1, rh2, rh1it, exm2, dm2, exm1, dm1, alpha, exsm;
598 if(dsm <= (100. * pnorm * ETA) || pdest == 0.) {
602 nqm2 = min(nq, mxords);
605 exsm = 1. / (double)l;
606 rh1 = 1. / (1.2 * pow(dsm, exsm) + 0.0000012);
608 *pdh = pdlast * fabs(h_);
609 if((*pdh * rh1) > 0.00001)
610 rh1it = sm1[nq] / *pdh;
611 rh1 = min(rh1, rh1it);
615 exm2 = 1. / (double)lm2;
617 dm2 = vmnorm(n, yh_[lm2p1], ewt) / cm2[mxords];
618 rh2 = 1. / (1.2 * pow(dm2, exm2) + 0.0000012);
621 dm2 = dsm * (cm1[nq] / cm2[nq]);
622 rh2 = 1. / (1.2 * pow(dm2, exsm) + 0.0000012);
625 if(rh2 < ratio * rh1)
651 exsm = 1. / (double)l;
655 exm1 = 1. / (double)lm1;
657 dm1 = vmnorm(n, yh_[lm1p1], ewt) / cm1[mxordn];
658 rh1 = 1. / (1.2 * pow(dm1, exm1) + 0.0000012);
661 dm1 = dsm * (cm2[nq] / cm1[nq]);
662 rh1 = 1. / (1.2 * pow(dm1, exsm) + 0.0000012);
667 *pdh = pdnorm * fabs(h_);
668 if((*pdh * rh1) > 0.00001)
669 rh1it = sm1[nqm1] / *pdh;
670 rh1 = min(rh1, rh1it);
671 rh2 = 1. / (1.2 * pow(dsm, exsm) + 0.0000012);
672 if((rh1 * ratio) < (5. * rh2))
674 alpha = max(0.001, rh1);
675 dm1 *= pow(alpha, exm1);
676 if(dm1 <= 1000. * ETA * pnorm)
696 double r = 1. / tesco[nqu][2];
697 for(
size_t i = 1; i <= n; i++)
717 double *rhup,
double dsm,
double *pdh,
double *rh,
size_t *orderflag)
720 double exsm, rhdn, rhsm, ddn, exdn, r;
724 exsm = 1. / (double)l;
725 rhsm = 1. / (1.2 * pow(dsm, exsm) + 0.0000012);
729 ddn = vmnorm(n, yh_[l], ewt) / tesco[nq][1];
730 exdn = 1. / (double)nq;
731 rhdn = 1. / (1.3 * pow(ddn, exdn) + 0.0000013);
737 *pdh = max(fabs(h_) * pdlast, 0.000001);
739 *rhup = min(*rhup, sm1[l] / *pdh);
740 rhsm = min(rhsm, sm1[nq] / *pdh);
742 rhdn = min(rhdn, sm1[nq - 1] / *pdh);
753 if(kflag < 0 && *rh > 1.)
761 if(kflag < 0 && *rh > 1.)
767 r = el[l] / (double)l;
770 for(
size_t i = 1; i <= n; i++)
771 yh_[l][i] = acor[i] * r;
786 if((*rh * *pdh * 1.00001) < sm1[newq])
787 if(kflag == 0 && *rh < 1.1) {
793 if(kflag == 0 && *rh < 1.1) {
821 array<double, 14> ep1;
824 for(
size_t i = 1; i <= l; i++)
826 rc = rc * el[1] / el0;
828 conit = 0.5 / (double)(nq + 2);
839 yh_.clear(); yh_.resize(lenyh + 1, std::vector<double>(nyh + 1, 0.0));
840 wm_.clear(); wm_.resize(nyh + 1, std::vector<double>(nyh + 1, 0.0));
841 ewt.resize(1 + nyh, 0);
842 savf.resize(1 + nyh, 0);
843 acor.resize(nyh + 1, 0.0);
844 ipvt.resize(nyh + 1, 0.0);
void orderswitch(double *rhup, double dsm, double *pdh, double *rh, size_t *orderflag)
void terminate(int *istate)
static bool abs_compare(double a, double b)
void ewset(const std::vector< double > &ycur)
void scaleh(double *rh, double *pdh)
void solsy(std::vector< double > &y)
double vmnorm(const size_t n, const std::vector< double > &v, const std::vector< double > &w)
double fnorm(int n, const std::vector< std::vector< double >> &a, const std::vector< double > &w)
void dscal1(const double da, std::vector< double > &dx, const size_t n, const size_t offset)
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)
size_t idamax1(const std::vector< double > &dx, const size_t n, const size_t offset)
void resize_system(int nyh, int lenyh)
void methodswitch(double dsm, double pnorm, double *pdh, double *rh)
void dgesl(const std::vector< std::vector< double >> &a, const size_t n, std::vector< int > &ipvt, std::vector< double > &b, const size_t job)
void dgefa(std::vector< std::vector< double >> &a, const size_t n, std::vector< int > &ipvt, size_t *const info)
double ddot1(const std::vector< double > &a, const std::vector< double > &b, const size_t n, const size_t offsetA, const size_t offsetB)
void daxpy1(const double da, const std::vector< double > &dx, std::vector< double > &dy, const size_t n, const size_t offsetX, const size_t offsetY)