@danielsimonjr/mathts-functions 0.25.1 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +161 -9
- package/dist/numeric/solveODE.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -36301,6 +36301,127 @@ var createSolveODE = /* @__PURE__ */ factory(
|
|
|
36301
36301
|
}
|
|
36302
36302
|
return true;
|
|
36303
36303
|
}
|
|
36304
|
+
function _rmsNorm(v) {
|
|
36305
|
+
let s = 0;
|
|
36306
|
+
for (let i = 0; i < v.length; i++) s += v[i] * v[i];
|
|
36307
|
+
return Math.sqrt(s / v.length);
|
|
36308
|
+
}
|
|
36309
|
+
function _luSolve(A, b) {
|
|
36310
|
+
const n = b.length;
|
|
36311
|
+
const M = A.map((r) => r.slice());
|
|
36312
|
+
const x = b.slice();
|
|
36313
|
+
for (let k = 0; k < n; k++) {
|
|
36314
|
+
let piv = k;
|
|
36315
|
+
for (let i = k + 1; i < n; i++) if (Math.abs(M[i][k]) > Math.abs(M[piv][k])) piv = i;
|
|
36316
|
+
[M[k], M[piv]] = [M[piv], M[k]];
|
|
36317
|
+
[x[k], x[piv]] = [x[piv], x[k]];
|
|
36318
|
+
const akk = M[k][k];
|
|
36319
|
+
for (let i = k + 1; i < n; i++) {
|
|
36320
|
+
const factor2 = M[i][k] / akk;
|
|
36321
|
+
for (let j = k; j < n; j++) M[i][j] -= factor2 * M[k][j];
|
|
36322
|
+
x[i] -= factor2 * x[k];
|
|
36323
|
+
}
|
|
36324
|
+
}
|
|
36325
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
36326
|
+
let s = x[i];
|
|
36327
|
+
for (let j = i + 1; j < n; j++) s -= M[i][j] * x[j];
|
|
36328
|
+
x[i] = s / M[i][i];
|
|
36329
|
+
}
|
|
36330
|
+
return x;
|
|
36331
|
+
}
|
|
36332
|
+
function _fArr(f, t, y) {
|
|
36333
|
+
const r = f(t, y);
|
|
36334
|
+
return Array.isArray(r) ? r : [r];
|
|
36335
|
+
}
|
|
36336
|
+
function _fdJacobian(f, t, y, f0) {
|
|
36337
|
+
const n = y.length;
|
|
36338
|
+
const J = Array.from({ length: n }, () => new Array(n));
|
|
36339
|
+
for (let j = 0; j < n; j++) {
|
|
36340
|
+
const eps = Math.max(1e-8, 1e-7 * Math.abs(y[j]));
|
|
36341
|
+
const yj = y.slice();
|
|
36342
|
+
yj[j] += eps;
|
|
36343
|
+
const fj = _fArr(f, t, yj);
|
|
36344
|
+
for (let i = 0; i < n; i++) J[i][j] = (fj[i] - f0[i]) / eps;
|
|
36345
|
+
}
|
|
36346
|
+
return J;
|
|
36347
|
+
}
|
|
36348
|
+
function _rosenbrock(f, tspan, y0raw, options) {
|
|
36349
|
+
const t0 = tspan[0];
|
|
36350
|
+
const tf = tspan[1];
|
|
36351
|
+
if (!(typeof t0 === "number" && typeof tf === "number")) {
|
|
36352
|
+
throw new Error('The "Rosenbrock" stiff method requires numeric tspan');
|
|
36353
|
+
}
|
|
36354
|
+
if (!y0raw.every((v) => typeof v === "number")) {
|
|
36355
|
+
throw new Error('The "Rosenbrock" stiff method requires plain-number state (y0)');
|
|
36356
|
+
}
|
|
36357
|
+
const y0 = y0raw;
|
|
36358
|
+
const n = y0.length;
|
|
36359
|
+
const dir = tf >= t0 ? 1 : -1;
|
|
36360
|
+
const gamma2 = 1 / (2 + Math.SQRT2);
|
|
36361
|
+
const c32 = 6 + Math.SQRT2;
|
|
36362
|
+
const rtol = options.tol ? options.tol : 1e-4;
|
|
36363
|
+
const atol = rtol * 1e-3;
|
|
36364
|
+
const maxIter = options.maxIter ? options.maxIter : 1e5;
|
|
36365
|
+
const span = Math.abs(tf - t0);
|
|
36366
|
+
let t = t0;
|
|
36367
|
+
let y = y0.slice();
|
|
36368
|
+
let h;
|
|
36369
|
+
if (options.firstStep) {
|
|
36370
|
+
h = dir * Math.abs(options.firstStep);
|
|
36371
|
+
} else {
|
|
36372
|
+
const f0 = f(t, y);
|
|
36373
|
+
const d0 = _rmsNorm(y);
|
|
36374
|
+
const d1 = _rmsNorm(Array.isArray(f0) ? f0 : [f0]);
|
|
36375
|
+
h = dir * Math.min(d0 < 1e-5 || d1 < 1e-5 ? 1e-6 : 0.01 * (d0 / d1), span);
|
|
36376
|
+
}
|
|
36377
|
+
const tOut = [t];
|
|
36378
|
+
const yOut = [y.slice()];
|
|
36379
|
+
let iter = 0;
|
|
36380
|
+
const identityMinus = (J, hg) => J.map((row2, i) => row2.map((v, j) => (i === j ? 1 : 0) - hg * v));
|
|
36381
|
+
while ((dir > 0 ? t < tf : t > tf) && iter < maxIter) {
|
|
36382
|
+
if (Math.abs(h) > Math.abs(tf - t)) h = tf - t;
|
|
36383
|
+
const F0 = _fArr(f, t, y);
|
|
36384
|
+
const J = _fdJacobian(f, t, y, F0);
|
|
36385
|
+
const W = identityMinus(J, h * gamma2);
|
|
36386
|
+
const k1 = _luSolve(W, F0);
|
|
36387
|
+
const y1 = y.map((yi, i) => yi + 0.5 * h * k1[i]);
|
|
36388
|
+
const F1 = _fArr(f, t + 0.5 * h, y1);
|
|
36389
|
+
const dk = _luSolve(
|
|
36390
|
+
W,
|
|
36391
|
+
F1.map((v, i) => v - k1[i])
|
|
36392
|
+
);
|
|
36393
|
+
const k2 = k1.map((v, i) => v + dk[i]);
|
|
36394
|
+
const yNew = y.map((yi, i) => yi + h * k2[i]);
|
|
36395
|
+
const F2 = _fArr(f, t + h, yNew);
|
|
36396
|
+
const k3 = _luSolve(
|
|
36397
|
+
W,
|
|
36398
|
+
F2.map((v, i) => v - c32 * (k2[i] - F1[i]) - 2 * (k1[i] - F0[i]))
|
|
36399
|
+
);
|
|
36400
|
+
let errNorm = 0;
|
|
36401
|
+
for (let i = 0; i < n; i++) {
|
|
36402
|
+
const err = h / 6 * (k1[i] - 2 * k2[i] + k3[i]);
|
|
36403
|
+
const sc = atol + rtol * Math.max(Math.abs(y[i]), Math.abs(yNew[i]));
|
|
36404
|
+
errNorm += (err / sc) ** 2;
|
|
36405
|
+
}
|
|
36406
|
+
errNorm = Math.sqrt(errNorm / n);
|
|
36407
|
+
if (errNorm <= 1 || Math.abs(h) <= 1e-14 * Math.abs(t)) {
|
|
36408
|
+
t += h;
|
|
36409
|
+
y = yNew;
|
|
36410
|
+
tOut.push(t);
|
|
36411
|
+
yOut.push(y.slice());
|
|
36412
|
+
}
|
|
36413
|
+
h *= Math.min(4, Math.max(0.25, 0.9 * Math.pow(errNorm || 1e-10, -1 / 3)));
|
|
36414
|
+
const maxStepR = options.maxStep;
|
|
36415
|
+
const minStepR = options.minStep;
|
|
36416
|
+
if (maxStepR && Math.abs(h) > maxStepR) h = dir * maxStepR;
|
|
36417
|
+
else if (minStepR && Math.abs(h) < minStepR) h = dir * minStepR;
|
|
36418
|
+
iter++;
|
|
36419
|
+
}
|
|
36420
|
+
if (iter >= maxIter) {
|
|
36421
|
+
throw new Error("Maximum number of iterations reached, try changing options");
|
|
36422
|
+
}
|
|
36423
|
+
return { t: tOut, y: yOut };
|
|
36424
|
+
}
|
|
36304
36425
|
function _rkWasmLoop(f, tspan, y0, options, butcherTableau) {
|
|
36305
36426
|
const wasm = wasmLoader.getModule();
|
|
36306
36427
|
if (!wasm) return null;
|
|
@@ -36313,12 +36434,21 @@ var createSolveODE = /* @__PURE__ */ factory(
|
|
|
36313
36434
|
const t0 = tspan[0];
|
|
36314
36435
|
const tf = tspan[1];
|
|
36315
36436
|
const isForwards = tf > t0;
|
|
36316
|
-
const steps = 1;
|
|
36317
36437
|
const tol = options.tol ? options.tol : 1e-4;
|
|
36318
36438
|
const minDelta = options.minDelta ? options.minDelta : 0.2;
|
|
36319
36439
|
const maxDelta = options.maxDelta ? options.maxDelta : 5;
|
|
36320
36440
|
const maxIter = options.maxIter ? options.maxIter : 1e4;
|
|
36321
|
-
let h
|
|
36441
|
+
let h;
|
|
36442
|
+
if (options.firstStep) {
|
|
36443
|
+
h = isForwards ? options.firstStep : -options.firstStep;
|
|
36444
|
+
} else {
|
|
36445
|
+
const f0 = f(t0, y0);
|
|
36446
|
+
const d0 = _rmsNorm(y0);
|
|
36447
|
+
const d1 = _rmsNorm(Array.isArray(f0) ? f0 : [f0]);
|
|
36448
|
+
const h0 = d0 < 1e-5 || d1 < 1e-5 ? 1e-6 : 0.01 * (d0 / d1);
|
|
36449
|
+
const hMag = Math.min(h0, Math.abs(tf - t0));
|
|
36450
|
+
h = isForwards ? hMag : -hMag;
|
|
36451
|
+
}
|
|
36322
36452
|
const maxStepVal = options.maxStep;
|
|
36323
36453
|
const minStepVal = options.minStep;
|
|
36324
36454
|
const deltaB = new Float64Array(numStages);
|
|
@@ -36468,10 +36598,31 @@ var createSolveODE = /* @__PURE__ */ factory(
|
|
|
36468
36598
|
bignumber2(butcherTableau.b),
|
|
36469
36599
|
bignumber2(butcherTableau.bp)
|
|
36470
36600
|
] : [butcherTableau.a, butcherTableau.c, butcherTableau.b, butcherTableau.bp];
|
|
36471
|
-
let h
|
|
36601
|
+
let h;
|
|
36602
|
+
if (firstStep) {
|
|
36603
|
+
h = isForwards ? firstStep : unaryMinus2(firstStep);
|
|
36604
|
+
} else if (!hasBigNumbers && !tspan.some(isUnit) && y0.every((v) => typeof v === "number")) {
|
|
36605
|
+
const f0 = f(t0, y0);
|
|
36606
|
+
const f0arr = Array.isArray(f0) ? f0 : [f0];
|
|
36607
|
+
const d0 = _rmsNorm(y0);
|
|
36608
|
+
const d1 = _rmsNorm(f0arr);
|
|
36609
|
+
const h0 = d0 < 1e-5 || d1 < 1e-5 ? 1e-6 : 0.01 * (d0 / d1);
|
|
36610
|
+
const hMag = Math.min(h0, Math.abs(tf - t0));
|
|
36611
|
+
h = isForwards ? hMag : -hMag;
|
|
36612
|
+
} else {
|
|
36613
|
+
h = divide2(subtract2(tf, t0), steps);
|
|
36614
|
+
}
|
|
36472
36615
|
const t = [t0];
|
|
36473
36616
|
const y = [y0];
|
|
36474
36617
|
const deltaB = subtract2(b, bp);
|
|
36618
|
+
function stageCombo(coeffs, stages) {
|
|
36619
|
+
const m = Math.min(coeffs.length, stages.length);
|
|
36620
|
+
let acc = multiply2(coeffs[0], stages[0]);
|
|
36621
|
+
for (let j = 1; j < m; j++) {
|
|
36622
|
+
acc = add2(acc, multiply2(coeffs[j], stages[j]));
|
|
36623
|
+
}
|
|
36624
|
+
return acc;
|
|
36625
|
+
}
|
|
36475
36626
|
let n = 0;
|
|
36476
36627
|
let iter = 0;
|
|
36477
36628
|
const ongoing = _createOngoing(isForwards);
|
|
@@ -36481,14 +36632,14 @@ var createSolveODE = /* @__PURE__ */ factory(
|
|
|
36481
36632
|
h = trimStep(t[n], tf, h);
|
|
36482
36633
|
k.push(f(t[n], y[n]));
|
|
36483
36634
|
for (let i = 1; i < c.length; ++i) {
|
|
36484
|
-
k.push(f(add2(t[n], multiply2(c[i], h)), add2(y[n], multiply2(h, a[i], k))));
|
|
36635
|
+
k.push(f(add2(t[n], multiply2(c[i], h)), add2(y[n], multiply2(h, stageCombo(a[i], k)))));
|
|
36485
36636
|
}
|
|
36486
|
-
const
|
|
36487
|
-
|
|
36488
|
-
);
|
|
36637
|
+
const errComb = stageCombo(deltaB, k);
|
|
36638
|
+
const errArr = Array.isArray(errComb) ? errComb : [errComb];
|
|
36639
|
+
const TE = max2(abs2(map2(errArr, (X) => isUnit(X) ? X.value : X)));
|
|
36489
36640
|
if (TE < tol && tol / TE > 1 / 4) {
|
|
36490
36641
|
t.push(add2(t[n], h));
|
|
36491
|
-
y.push(add2(y[n], multiply2(h, b, k)));
|
|
36642
|
+
y.push(add2(y[n], multiply2(h, stageCombo(b, k))));
|
|
36492
36643
|
n++;
|
|
36493
36644
|
}
|
|
36494
36645
|
let delta = 0.84 * (tol / TE) ** (1 / 5);
|
|
@@ -36548,7 +36699,8 @@ var createSolveODE = /* @__PURE__ */ factory(
|
|
|
36548
36699
|
const method = opt.method ? opt.method : "RK45";
|
|
36549
36700
|
const methods = {
|
|
36550
36701
|
RK23: _rk23,
|
|
36551
|
-
RK45: _rk45
|
|
36702
|
+
RK45: _rk45,
|
|
36703
|
+
ROSENBROCK: _rosenbrock
|
|
36552
36704
|
};
|
|
36553
36705
|
if (method.toUpperCase() in methods) {
|
|
36554
36706
|
const methodOptions = { ...opt };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solveODE.d.ts","sourceRoot":"","sources":["../../src/numeric/solveODE.ts"],"names":[],"mappings":"AAmEA,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"solveODE.d.ts","sourceRoot":"","sources":["../../src/numeric/solveODE.ts"],"names":[],"mappings":"AAmEA,eAAO,MAAM,cAAc,yDAkyB1B,CAAC"}
|
package/package.json
CHANGED