cacatoo
Version:
Building, exploring, and sharing spatially structured models
743 lines (740 loc) • 33.9 kB
JavaScript
"use strict";
/**
* An implementation of ODEX, by E. Hairer and G. Wanner, ported from the Fortran ODEX.F.
* The original work carries the BSD 2-clause license, and so does this.
*
* Copyright (c) 2016 Colin Smith.
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Object.defineProperty(exports, "__esModule", { value: true });
// var Outcome;
// (function (Outcome) {
// Outcome[Outcome["Converged"] = 0] = "Converged";
// Outcome[Outcome["MaxStepsExceeded"] = 1] = "MaxStepsExceeded";
// Outcome[Outcome["EarlyReturn"] = 2] = "EarlyReturn";
// })
//(Outcome = exports.Outcome || (exports.Outcome = {}));
function Outcome(){
Outcome[Outcome["Converged"] = 0] = "Converged";
Outcome[Outcome["MaxStepsExceeded"] = 1] = "MaxStepsExceeded";
Outcome[Outcome["EarlyReturn"] = 2] = "EarlyReturn";
}
var Solver = (function () {
function Solver(n) {
this.n = n;
this.uRound = 2.3e-16;
this.maxSteps = 100; // 10000
this.initialStepSize = 1e-4;
this.maxStepSize = 0;
this.maxExtrapolationColumns = 9;
this.stepSizeSequence = 0;
this.stabilityCheckCount = 1;
this.stabilityCheckTableLines = 2;
this.denseOutput = false;
this.denseOutputErrorEstimator = true;
this.denseComponents = undefined;
this.interpolationFormulaDegree = 4;
this.stepSizeReductionFactor = 0.5;
this.stepSizeFac1 = 0.02;
this.stepSizeFac2 = 4.0;
this.stepSizeFac3 = 0.8;
this.stepSizeFac4 = 0.9;
this.stepSafetyFactor1 = 0.65;
this.stepSafetyFactor2 = 0.94;
this.relativeTolerance = 1e-3; // 1e-5
this.absoluteTolerance = 1e-3; // 1e-5
this.debug = false;
}
Solver.prototype.grid = function (dt, out) {
if (!this.denseOutput)
throw new Error('Must set .denseOutput to true when using grid');
var components = this.denseComponents;
if (!components) {
components = [];
for (var i = 0; i < this.n; ++i)
components.push(i);
}
var t;
return function (n, xOld, x, y, interpolate) {
if (n === 1) {
var v = out(x, y);
t = x + dt;
return v;
}
while (t <= x) {
var yf = [];
for (var _i = 0, components_1 = components; _i < components_1.length; _i++) {
var i = components_1[_i];
yf.push(interpolate(i, t));
}
var v = out(t, yf);
if (v === false)
return false;
t += dt;
}
};
};
// Make a 1-based 2D array, with r rows and c columns. The initial values are undefined.
Solver.dim2 = function (r, c) {
var a = new Array(r + 1);
for (var i = 1; i <= r; ++i)
a[i] = Solver.dim(c);
return a;
};
// Generate step size sequence and return as a 1-based array of length n.
Solver.stepSizeSequence = function (nSeq, n) {
var a = new Array(n + 1);
a[0] = 0;
switch (nSeq) {
case 1:
for (var i = 1; i <= n; ++i)
a[i] = 2 * i;
break;
case 2:
a[1] = 2;
for (var i = 2; i <= n; ++i)
a[i] = 4 * i - 4;
break;
case 3:
a[1] = 2;
a[2] = 4;
a[3] = 6;
for (var i = 4; i <= n; ++i)
a[i] = 2 * a[i - 2];
break;
case 4:
for (var i = 1; i <= n; ++i)
a[i] = 4 * i - 2;
break;
case 5:
for (var i = 1; i <= n; ++i)
a[i] = 4 * i;
break;
default:
throw new Error('invalid stepSizeSequence selected');
}
return a;
};
// Integrate the differential system represented by f, from x to xEnd, with initial data y.
// solOut, if provided, is called at each integration step.
Solver.prototype.solve = function (f, x, y0, xEnd, solOut) {
var _this = this;
// Make a copy of y0, 1-based. We leave the user's parameters alone so that they may be reused if desired.
var y = [0].concat(y0);
var dz = Solver.dim(this.n);
var yh1 = Solver.dim(this.n);
var yh2 = Solver.dim(this.n);
if (this.maxSteps <= 0)
throw new Error('maxSteps must be positive');
var km = this.maxExtrapolationColumns;
if (km <= 2)
throw new Error('maxExtrapolationColumns must be > 2');
var nSeq = this.stepSizeSequence || (this.denseOutput ? 4 : 1);
if (nSeq <= 3 && this.denseOutput)
throw new Error('stepSizeSequence incompatible with denseOutput');
if (this.denseOutput && !solOut)
throw new Error('denseOutput requires a solution observer function');
if (this.interpolationFormulaDegree <= 0 || this.interpolationFormulaDegree >= 7)
throw new Error('bad interpolationFormulaDegree');
var icom = [0]; // icom will be 1-based, so start with a pad entry.
var nrdens = 0;
if (this.denseOutput) {
if (this.denseComponents) {
for (var _i = 0, _a = this.denseComponents; _i < _a.length; _i++) {
var c = _a[_i];
// convert dense components requested into one-based indexing.
if (c < 0 || c > this.n)
throw new Error('bad dense component: ' + c);
icom.push(c + 1);
++nrdens;
}
}
else {
// if user asked for dense output but did not specify any denseComponents,
// request all of them.
for (var i = 1; i <= this.n; ++i) {
icom.push(i);
}
nrdens = this.n;
}
}
if (this.uRound <= 1e-35 || this.uRound > 1)
throw new Error('suspicious value of uRound');
var hMax = Math.abs(this.maxStepSize || xEnd - x);
var lfSafe = 2 * km * km + km;
function expandToArray(x, n) {
// If x is an array, return a 1-based copy of it. If x is a number, return a new 1-based array
// consisting of n copies of the number.
var tolArray = [0];
if (Array.isArray(x)) {
return tolArray.concat(x);
}
else {
for (var i = 0; i < n; ++i)
tolArray.push(x);
return tolArray;
}
}
var aTol = expandToArray(this.absoluteTolerance, this.n);
var rTol = expandToArray(this.relativeTolerance, this.n);
var _b = [0, 0, 0, 0], nEval = _b[0], nStep = _b[1], nAccept = _b[2], nReject = _b[3];
// call to core integrator
var nrd = Math.max(1, nrdens);
var ncom = Math.max(1, (2 * km + 5) * nrdens);
var dens = Solver.dim(ncom);
var fSafe = Solver.dim2(lfSafe, nrd);
// Wrap f in a function F which hides the one-based indexing from the customers.
var F = function (x, y, yp) {
var ret = f(x, y.slice(1));
for (var i = 0; i < ret.length; ++i)
yp[i + 1] = ret[i];
};
var odxcor = function () {
// The following three variables are COMMON/CONTEX/
var xOldd;
var hhh;
var kmit;
var acceptStep = function (n) {
// Returns true if we should continue the integration. The only time false
// is returned is when the user's solution observation function has returned false,
// indicating that she does not wish to continue the computation.
xOld = x;
x += h;
if (_this.denseOutput) {
// kmit = mu of the paper
kmit = 2 * kc - _this.interpolationFormulaDegree + 1;
for (var i = 1; i <= nrd; ++i)
dens[i] = y[icom[i]];
xOldd = xOld;
hhh = h; // note: xOldd and hhh are part of /CONODX/
for (var i = 1; i <= nrd; ++i)
dens[nrd + i] = h * dz[icom[i]];
var kln = 2 * nrd;
for (var i = 1; i <= nrd; ++i)
dens[kln + i] = t[1][icom[i]];
// compute solution at mid-point
for (var j = 2; j <= kc; ++j) {
var dblenj = nj[j];
for (var l = j; l >= 2; --l) {
var factor = Math.pow((dblenj / nj[l - 1]), 2) - 1;
for (var i = 1; i <= nrd; ++i) {
ySafe[l - 1][i] = ySafe[l][i] + (ySafe[l][i] - ySafe[l - 1][i]) / factor;
}
}
}
var krn = 4 * nrd;
for (var i = 1; i <= nrd; ++i)
dens[krn + i] = ySafe[1][i];
// compute first derivative at right end
for (var i = 1; i <= n; ++i)
yh1[i] = t[1][i];
F(x, yh1, yh2);
krn = 3 * nrd;
for (var i = 1; i <= nrd; ++i)
dens[krn + i] = yh2[icom[i]] * h;
// THE LOOP
for (var kmi = 1; kmi <= kmit; ++kmi) {
// compute kmi-th derivative at mid-point
var kbeg = (kmi + 1) / 2 | 0;
for (var kk = kbeg; kk <= kc; ++kk) {
var facnj = Math.pow((nj[kk] / 2), (kmi - 1));
iPt = iPoint[kk + 1] - 2 * kk + kmi;
for (var i = 1; i <= nrd; ++i) {
ySafe[kk][i] = fSafe[iPt][i] * facnj;
}
}
for (var j = kbeg + 1; j <= kc; ++j) {
var dblenj = nj[j];
for (var l = j; l >= kbeg + 1; --l) {
var factor = Math.pow((dblenj / nj[l - 1]), 2) - 1;
for (var i = 1; i <= nrd; ++i) {
ySafe[l - 1][i] = ySafe[l][i] + (ySafe[l][i] - ySafe[l - 1][i]) / factor;
}
}
}
krn = (kmi + 4) * nrd;
for (var i = 1; i <= nrd; ++i)
dens[krn + i] = ySafe[kbeg][i] * h;
if (kmi === kmit)
continue;
// compute differences
for (var kk = (kmi + 2) / 2 | 0; kk <= kc; ++kk) {
var lbeg = iPoint[kk + 1];
var lend = iPoint[kk] + kmi + 1;
if (kmi === 1 && nSeq === 4)
lend += 2;
var l = void 0;
for (l = lbeg; l >= lend; l -= 2) {
for (var i = 1; i <= nrd; ++i) {
fSafe[l][i] -= fSafe[l - 2][i];
}
}
if (kmi === 1 && nSeq === 4) {
l = lend - 2;
for (var i = 1; i <= nrd; ++i)
fSafe[l][i] -= dz[icom[i]];
}
}
// compute differences
for (var kk = (kmi + 2) / 2 | 0; kk <= kc; ++kk) {
var lbeg = iPoint[kk + 1] - 1;
var lend = iPoint[kk] + kmi + 2;
for (var l = lbeg; l >= lend; l -= 2) {
for (var i = 1; i <= nrd; ++i) {
fSafe[l][i] -= fSafe[l - 2][i];
}
}
}
}
interp(nrd, dens, kmit);
// estimation of interpolation error
if (_this.denseOutputErrorEstimator && kmit >= 1) {
var errint = 0;
for (var i = 1; i <= nrd; ++i)
errint += Math.pow((dens[(kmit + 4) * nrd + i] / scal[icom[i]]), 2);
errint = Math.sqrt(errint / nrd) * errfac[kmit];
hoptde = h / Math.max(Math.pow(errint, (1 / (kmit + 4))), 0.01);
if (errint > 10) {
h = hoptde;
x = xOld;
++nReject;
reject = true;
return true;
}
}
for (var i = 1; i <= n; ++i)
dz[i] = yh2[i];
}
for (var i = 1; i <= n; ++i)
y[i] = t[1][i];
++nAccept;
if (solOut) {
// If denseOutput, we also want to supply the dense closure.
if (solOut(nAccept + 1, xOld, x, y.slice(1), _this.denseOutput && contex(xOldd, hhh, kmit, dens, icom)) === false)
return false;
}
// compute optimal order
var kopt;
if (kc === 2) {
kopt = Math.min(3, km - 1);
if (reject)
kopt = 2;
}
else {
if (kc <= k) {
kopt = kc;
if (w[kc - 1] < w[kc] * _this.stepSizeFac3)
kopt = kc - 1;
if (w[kc] < w[kc - 1] * _this.stepSizeFac4)
kopt = Math.min(kc + 1, km - 1);
}
else {
kopt = kc - 1;
if (kc > 3 && w[kc - 2] < w[kc - 1] * _this.stepSizeFac3)
kopt = kc - 2;
if (w[kc] < w[kopt] * _this.stepSizeFac4)
kopt = Math.min(kc, km - 1);
}
}
// after a rejected step
if (reject) {
k = Math.min(kopt, kc);
h = posneg * Math.min(Math.abs(h), Math.abs(hh[k]));
reject = false;
return true; // goto 10
}
if (kopt <= kc) {
h = hh[kopt];
}
else {
if (kc < k && w[kc] < w[kc - 1] * _this.stepSizeFac4) {
h = hh[kc] * a[kopt + 1] / a[kc];
}
else {
h = hh[kc] * a[kopt] / a[kc];
}
}
// compute stepsize for next step
k = kopt;
h = posneg * Math.abs(h);
return true;
};
var midex = function (j) {
var dy = Solver.dim(_this.n);
// Computes the jth line of the extrapolation table and
// provides an estimation of the optional stepsize
var hj = h / nj[j];
// Euler starting step
for (var i = 1; i <= _this.n; ++i) {
yh1[i] = y[i];
yh2[i] = y[i] + hj * dz[i];
}
// Explicit midpoint rule
var m = nj[j] - 1;
var njMid = (nj[j] / 2) | 0;
for (var mm = 1; mm <= m; ++mm) {
if (_this.denseOutput && mm === njMid) {
for (var i = 1; i <= nrd; ++i) {
ySafe[j][i] = yh2[icom[i]];
}
}
F(x + hj * mm, yh2, dy);
if (_this.denseOutput && Math.abs(mm - njMid) <= 2 * j - 1) {
++iPt;
for (var i = 1; i <= nrd; ++i) {
fSafe[iPt][i] = dy[icom[i]];
}
}
for (var i = 1; i <= _this.n; ++i) {
var ys = yh1[i];
yh1[i] = yh2[i];
yh2[i] = ys + 2 * hj * dy[i];
}
if (mm <= _this.stabilityCheckCount && j <= _this.stabilityCheckTableLines) {
// stability check
var del1 = 0;
for (var i = 1; i <= _this.n; ++i) {
del1 += Math.pow((dz[i] / scal[i]), 2);
}
var del2 = 0;
for (var i = 1; i <= _this.n; ++i) {
del2 += Math.pow(((dy[i] - dz[i]) / scal[i]), 2);
}
var quot = del2 / Math.max(_this.uRound, del1);
if (quot > 4) {
++nEval;
atov = true;
h *= _this.stepSizeReductionFactor;
reject = true;
return;
}
}
}
// final smoothing step
F(x + h, yh2, dy);
if (_this.denseOutput && njMid <= 2 * j - 1) {
++iPt;
for (var i = 1; i <= nrd; ++i) {
fSafe[iPt][i] = dy[icom[i]];
}
}
for (var i = 1; i <= _this.n; ++i) {
t[j][i] = (yh1[i] + yh2[i] + hj * dy[i]) / 2;
}
nEval += nj[j];
// polynomial extrapolation
if (j === 1)
return; // was j.eq.1
var dblenj = nj[j];
var fac;
for (var l = j; l > 1; --l) {
fac = Math.pow((dblenj / nj[l - 1]), 2) - 1;
for (var i = 1; i <= _this.n; ++i) {
t[l - 1][i] = t[l][i] + (t[l][i] - t[l - 1][i]) / fac;
}
}
err = 0;
// scaling
for (var i = 1; i <= _this.n; ++i) {
var t1i = Math.max(Math.abs(y[i]), Math.abs(t[1][i]));
scal[i] = aTol[i] + rTol[i] * t1i;
err += Math.pow(((t[1][i] - t[2][i]) / scal[i]), 2);
}
err = Math.sqrt(err / _this.n);
if (err * _this.uRound >= 1 || (j > 2 && err >= errOld)) {
atov = true;
h *= _this.stepSizeReductionFactor;
reject = true;
return;
}
errOld = Math.max(4 * err, 1);
// compute optimal stepsizes
var exp0 = 1 / (2 * j - 1);
var facMin = Math.pow(_this.stepSizeFac1, exp0);
fac = Math.min(_this.stepSizeFac2 / facMin, Math.max(facMin, Math.pow((err / _this.stepSafetyFactor1), exp0) / _this.stepSafetyFactor2));
fac = 1 / fac;
hh[j] = Math.min(Math.abs(h) * fac, hMax);
w[j] = a[j] / hh[j];
};
var interp = function (n, y, imit) {
// computes the coefficients of the interpolation formula
var a = new Array(31); // zero-based: 0:30
// begin with Hermite interpolation
for (var i = 1; i <= n; ++i) {
var y0_1 = y[i];
var y1 = y[2 * n + i];
var yp0 = y[n + i];
var yp1 = y[3 * n + i];
var yDiff = y1 - y0_1;
var aspl = -yp1 + yDiff;
var bspl = yp0 - yDiff;
y[n + i] = yDiff;
y[2 * n + i] = aspl;
y[3 * n + i] = bspl;
if (imit < 0)
continue;
// compute the derivatives of Hermite at midpoint
var ph0 = (y0_1 + y1) * 0.5 + 0.125 * (aspl + bspl);
var ph1 = yDiff + (aspl - bspl) * 0.25;
var ph2 = -(yp0 - yp1);
var ph3 = 6 * (bspl - aspl);
// compute the further coefficients
if (imit >= 1) {
a[1] = 16 * (y[5 * n + i] - ph1);
if (imit >= 3) {
a[3] = 16 * (y[7 * n + i] - ph3 + 3 * a[1]);
if (imit >= 5) {
for (var im = 5; im <= imit; im += 2) {
var fac1 = im * (im - 1) / 2;
var fac2 = fac1 * (im - 2) * (im - 3) * 2;
a[im] = 16 * (y[(im + 4) * n + i] + fac1 * a[im - 2] - fac2 * a[im - 4]);
}
}
}
}
a[0] = (y[4 * n + i] - ph0) * 16;
if (imit >= 2) {
a[2] = (y[n * 6 + i] - ph2 + a[0]) * 16;
if (imit >= 4) {
for (var im = 4; im <= imit; im += 2) {
var fac1 = im * (im - 1) / 2;
var fac2 = im * (im - 1) * (im - 2) * (im - 3);
a[im] = (y[n * (im + 4) + i] + a[im - 2] * fac1 - a[im - 4] * fac2) * 16;
}
}
}
for (var im = 0; im <= imit; ++im)
y[n * (im + 4) + i] = a[im];
}
};
var contex = function (xOld, h, imit, y, icom) {
return function (c, x) {
var i = 0;
for (var j = 1; j <= nrd; ++j) {
// careful: customers describe components 0-based. We record indices 1-based.
if (icom[j] === c + 1)
i = j;
}
if (i === 0)
throw new Error('no dense output available for component ' + c);
var theta = (x - xOld) / h;
var theta1 = 1 - theta;
var phthet = y[i] + theta * (y[nrd + i] + theta1 * (y[2 * nrd + i] * theta + y[3 * nrd + i] * theta1));
if (imit < 0)
return phthet;
var thetah = theta - 0.5;
var ret = y[nrd * (imit + 4) + i];
for (var im = imit; im >= 1; --im) {
ret = y[nrd * (im + 3) + i] + ret * thetah / im;
}
return phthet + Math.pow((theta * theta1), 2) * ret;
};
};
// preparation
var ySafe = Solver.dim2(km, nrd);
var hh = Solver.dim(km);
var t = Solver.dim2(km, _this.n);
// Define the step size sequence
var nj = Solver.stepSizeSequence(nSeq, km);
// Define the a[i] for order selection
var a = Solver.dim(km);
a[1] = 1 + nj[1];
for (var i = 2; i <= km; ++i) {
a[i] = a[i - 1] + nj[i];
}
// Initial Scaling
var scal = Solver.dim(_this.n);
for (var i = 1; i <= _this.n; ++i) {
scal[i] = aTol[i] + rTol[i] + Math.abs(y[i]);
}
// Initial preparations
var posneg = xEnd - x >= 0 ? 1 : -1;
var k = Math.max(2, Math.min(km - 1, Math.floor(-Solver.log10(rTol[1] + 1e-40) * 0.6 + 1.5)));
var h = Math.max(Math.abs(_this.initialStepSize), 1e-4);
h = posneg * Math.min(h, hMax, Math.abs(xEnd - x) / 2);
var iPoint = Solver.dim(km + 1);
var errfac = Solver.dim(2 * km);
var xOld = x;
var iPt = 0;
if (solOut) {
if (_this.denseOutput) {
iPoint[1] = 0;
for (var i = 1; i <= km; ++i) {
var njAdd = 4 * i - 2;
if (nj[i] > njAdd)
++njAdd;
iPoint[i + 1] = iPoint[i] + njAdd;
}
for (var mu = 1; mu <= 2 * km; ++mu) {
var errx = Math.sqrt(mu / (mu + 4)) * 0.5;
var prod = Math.pow((1 / (mu + 4)), 2);
for (var j = 1; j <= mu; ++j)
prod *= errx / j;
errfac[mu] = prod;
}
iPt = 0;
}
// check return value and abandon integration if called for
if (false === solOut(nAccept + 1, xOld, x, y.slice(1))) {
return Outcome.EarlyReturn;
}
}
var err = 0;
var errOld = 1e10;
var hoptde = posneg * hMax;
var w = Solver.dim(km);
w[1] = 0;
var reject = false;
var last = false;
var atov;
var kc = 0;
var STATE;
(function (STATE) {
STATE[STATE["Start"] = 0] = "Start";
STATE[STATE["BasicIntegrationStep"] = 1] = "BasicIntegrationStep";
STATE[STATE["ConvergenceStep"] = 2] = "ConvergenceStep";
STATE[STATE["HopeForConvergence"] = 3] = "HopeForConvergence";
STATE[STATE["Accept"] = 4] = "Accept";
STATE[STATE["Reject"] = 5] = "Reject";
})(STATE || (STATE = {}));
var state = STATE.Start;
loop: while (true) {
_this.debug && console.log('STATE', STATE[state], nStep, xOld, x, h, k, kc, hoptde);
switch (state) {
case STATE.Start:
atov = false;
// Is xEnd reached in the next step?
if (0.1 * Math.abs(xEnd - x) <= Math.abs(x) * _this.uRound)
break loop;
h = posneg * Math.min(Math.abs(h), Math.abs(xEnd - x), hMax, Math.abs(hoptde));
if ((x + 1.01 * h - xEnd) * posneg > 0) {
h = xEnd - x;
last = true;
}
if (nStep === 0 || !_this.denseOutput) {
F(x, y, dz);
++nEval;
}
// The first and last step
if (nStep === 0 || last) {
iPt = 0;
++nStep;
for (var j = 1; j <= k; ++j) {
kc = j;
midex(j);
if (atov)
continue loop;
if (j > 1 && err <= 1) {
state = STATE.Accept;
continue loop;
}
}
state = STATE.HopeForConvergence;
continue;
}
state = STATE.BasicIntegrationStep;
continue;
case STATE.BasicIntegrationStep:
// basic integration step
iPt = 0;
++nStep;
if (nStep >= _this.maxSteps) {
return Outcome.MaxStepsExceeded;
}
kc = k - 1;
for (var j = 1; j <= kc; ++j) {
midex(j);
if (atov) {
state = STATE.Start;
continue loop;
}
}
// convergence monitor
if (k === 2 || reject) {
state = STATE.ConvergenceStep;
}
else {
if (err <= 1) {
state = STATE.Accept;
}
else if (err > Math.pow(((nj[k + 1] * nj[k]) / 4), 2)) {
state = STATE.Reject;
}
else
state = STATE.ConvergenceStep;
}
continue;
case STATE.ConvergenceStep:
midex(k);
if (atov) {
state = STATE.Start;
continue;
}
kc = k;
if (err <= 1) {
state = STATE.Accept;
continue;
}
state = STATE.HopeForConvergence;
continue;
case STATE.HopeForConvergence:
// hope for convergence in line k + 1
if (err > Math.pow((nj[k + 1] / 2), 2)) {
state = STATE.Reject;
continue;
}
kc = k + 1;
midex(kc);
if (atov)
state = STATE.Start;
else if (err > 1)
state = STATE.Reject;
else
state = STATE.Accept;
continue;
case STATE.Accept:
if (!acceptStep(_this.n))
return Outcome.EarlyReturn;
state = STATE.Start;
continue;
case STATE.Reject:
k = Math.min(k, kc, km - 1);
if (k > 2 && w[k - 1] < w[k] * _this.stepSizeFac3)
k -= 1;
++nReject;
h = posneg * hh[k];
reject = true;
state = STATE.BasicIntegrationStep;
}
}
return Outcome.Converged;
};
var outcome = odxcor();
return {
y: y.slice(1),
outcome: outcome,
nStep: nStep,
xEnd: xEnd,
nAccept: nAccept,
nReject: nReject,
nEval: nEval
};
};
return Solver;
}());
// return a 1-based array of length n. Initial values undefined.
Solver.dim = function (n) { return Array(n + 1); };
Solver.log10 = function (x) { return Math.log(x) / Math.LN10; };
//exports.Solver = Solver;
////# sourceMappingURL=odex.js.map