diff-grok 1.0.10 → 1.2.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/.claude/settings.local.json +11 -0
- package/.claude/skills/license-updater/SKILL.md +149 -0
- package/.claude/skills/license-updater/references/compatibility.md +68 -0
- package/.claude/skills/license-updater/references/templates.md +151 -0
- package/.claude/skills/license-updater/scripts/generate_license_files.py +467 -0
- package/CLAUDE.md +104 -0
- package/LICENSE +1 -1
- package/README.MD +121 -27
- package/THIRD_PARTY_LICENSES +135 -0
- package/docs/assets/hierarchy.js +1 -1
- package/docs/assets/navigation.js +1 -1
- package/docs/assets/search.js +1 -1
- package/docs/classes/BasicModelPipelineCreator.html +4 -4
- package/docs/classes/Callback.html +5 -5
- package/docs/classes/CyclicModelPipelineCreator.html +4 -4
- package/docs/classes/IterCheckerCallback.html +5 -5
- package/docs/classes/PipelineCreator.html +4 -4
- package/docs/classes/TimeCheckerCallback.html +5 -5
- package/docs/classes/UpdatesModelPipelineCreator.html +4 -4
- package/docs/functions/ab4.html +8 -0
- package/docs/functions/ab5.html +8 -0
- package/docs/functions/applyPipeline.html +2 -2
- package/docs/functions/getCallback.html +2 -2
- package/docs/functions/getIVP.html +2 -2
- package/docs/functions/getInputVector.html +2 -2
- package/docs/functions/getIvp2WebWorker.html +2 -2
- package/docs/functions/getJScode.html +2 -2
- package/docs/functions/getOutputNames.html +2 -2
- package/docs/functions/getPipelineCreator.html +2 -2
- package/docs/functions/lsoda.html +8 -0
- package/docs/functions/mrt.html +2 -2
- package/docs/functions/printE5.html +2 -2
- package/docs/functions/printHires.html +2 -2
- package/docs/functions/printOrego.html +2 -2
- package/docs/functions/printPollution.html +2 -2
- package/docs/functions/printRobertson.html +2 -2
- package/docs/functions/printVdpol.html +2 -2
- package/docs/functions/rk3.html +8 -0
- package/docs/functions/rk4.html +8 -0
- package/docs/functions/rkdp.html +8 -0
- package/docs/functions/ros34prw.html +2 -2
- package/docs/functions/ros3prw.html +2 -2
- package/docs/functions/solveIvp.html +2 -2
- package/docs/hierarchy.html +1 -1
- package/docs/index.html +100 -15
- package/docs/media/E5.png +0 -0
- package/docs/media/HIRES.png +0 -0
- package/docs/media/OREGO.png +0 -0
- package/docs/media/POLL-full.png +0 -0
- package/docs/media/ROBER.png +0 -0
- package/docs/media/VDP0L.png +0 -0
- package/docs/media/cyclic-model.js +3 -1
- package/docs/media/cyclic-model.js.map +1 -1
- package/docs/media/cyclic-model.ts +3 -1
- package/docs/modules.html +1 -1
- package/docs/types/Arg.html +7 -7
- package/docs/types/DifEqs.html +4 -4
- package/docs/types/Func.html +2 -2
- package/docs/types/IVP.html +20 -20
- package/docs/types/IVP2WebWorker.html +7 -7
- package/docs/types/Input.html +4 -4
- package/docs/types/Loop.html +4 -4
- package/docs/types/ODEs.html +8 -8
- package/docs/types/Output.html +4 -4
- package/docs/types/Pipeline.html +4 -4
- package/docs/types/SolverOptions.html +5 -5
- package/docs/types/Update.html +5 -5
- package/docs/types/Wrapper.html +5 -5
- package/images/E5.png +0 -0
- package/images/HIRES.png +0 -0
- package/images/OREGO.png +0 -0
- package/images/POLL-full.png +0 -0
- package/images/ROBER.png +0 -0
- package/images/VDP0L.png +0 -0
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/index.ts +2 -1
- package/jest.config.js +1 -0
- package/package.json +4 -2
- package/src/examples/check-methods.js +15 -3
- package/src/examples/check-methods.js.map +1 -1
- package/src/examples/check-methods.ts +18 -3
- package/src/examples/cyclic-model.js +3 -1
- package/src/examples/cyclic-model.js.map +1 -1
- package/src/examples/cyclic-model.ts +3 -1
- package/src/solver-tools/ab4-method.js +332 -0
- package/src/solver-tools/ab4-method.js.map +1 -0
- package/src/solver-tools/ab4-method.ts +395 -0
- package/src/solver-tools/ab5-method.js +334 -0
- package/src/solver-tools/ab5-method.js.map +1 -0
- package/src/solver-tools/ab5-method.ts +397 -0
- package/src/solver-tools/cvode/common.js +487 -0
- package/src/solver-tools/cvode/common.js.map +1 -0
- package/src/solver-tools/cvode/common.ts +549 -0
- package/src/solver-tools/cvode/cvode.js +1062 -0
- package/src/solver-tools/cvode/cvode.js.map +1 -0
- package/src/solver-tools/cvode/cvode.ts +1226 -0
- package/src/solver-tools/cvode/cvode_adams.js +124 -0
- package/src/solver-tools/cvode/cvode_adams.js.map +1 -0
- package/src/solver-tools/cvode/cvode_adams.ts +142 -0
- package/src/solver-tools/cvode/cvode_bdf.js +153 -0
- package/src/solver-tools/cvode/cvode_bdf.js.map +1 -0
- package/src/solver-tools/cvode/cvode_bdf.ts +164 -0
- package/src/solver-tools/cvode/cvode_class.js +158 -0
- package/src/solver-tools/cvode/cvode_class.js.map +1 -0
- package/src/solver-tools/cvode/cvode_class.ts +271 -0
- package/src/solver-tools/cvode/cvode_hin.js +119 -0
- package/src/solver-tools/cvode/cvode_hin.js.map +1 -0
- package/src/solver-tools/cvode/cvode_hin.ts +150 -0
- package/src/solver-tools/cvode/cvode_io.js +203 -0
- package/src/solver-tools/cvode/cvode_io.js.map +1 -0
- package/src/solver-tools/cvode/cvode_io.ts +258 -0
- package/src/solver-tools/cvode/cvode_ls.js +210 -0
- package/src/solver-tools/cvode/cvode_ls.js.map +1 -0
- package/src/solver-tools/cvode/cvode_ls.ts +249 -0
- package/src/solver-tools/cvode/cvode_nls.js +220 -0
- package/src/solver-tools/cvode/cvode_nls.js.map +1 -0
- package/src/solver-tools/cvode/cvode_nls.ts +259 -0
- package/src/solver-tools/cvode/cvode_root.js +415 -0
- package/src/solver-tools/cvode/cvode_root.js.map +1 -0
- package/src/solver-tools/cvode/cvode_root.ts +503 -0
- package/src/solver-tools/cvode/dense_linalg.js +131 -0
- package/src/solver-tools/cvode/dense_linalg.js.map +1 -0
- package/src/solver-tools/cvode/dense_linalg.ts +144 -0
- package/src/solver-tools/cvode/index.js +26 -0
- package/src/solver-tools/cvode/index.js.map +1 -0
- package/src/solver-tools/cvode/index.ts +64 -0
- package/src/solver-tools/cvode-method.js +114 -0
- package/src/solver-tools/cvode-method.js.map +1 -0
- package/src/solver-tools/cvode-method.ts +129 -0
- package/src/solver-tools/index.js +7 -0
- package/src/solver-tools/index.js.map +1 -1
- package/src/solver-tools/index.ts +7 -0
- package/src/solver-tools/lsoda/blas.js +257 -0
- package/src/solver-tools/lsoda/blas.js.map +1 -0
- package/src/solver-tools/lsoda/blas.ts +279 -0
- package/src/solver-tools/lsoda/cfode.js +84 -0
- package/src/solver-tools/lsoda/cfode.js.map +1 -0
- package/src/solver-tools/lsoda/cfode.ts +95 -0
- package/src/solver-tools/lsoda/common.js +94 -0
- package/src/solver-tools/lsoda/common.js.map +1 -0
- package/src/solver-tools/lsoda/common.ts +135 -0
- package/src/solver-tools/lsoda/corfailure.js +36 -0
- package/src/solver-tools/lsoda/corfailure.js.map +1 -0
- package/src/solver-tools/lsoda/corfailure.ts +42 -0
- package/src/solver-tools/lsoda/correction.js +112 -0
- package/src/solver-tools/lsoda/correction.js.map +1 -0
- package/src/solver-tools/lsoda/correction.ts +131 -0
- package/src/solver-tools/lsoda/dense.js +121 -0
- package/src/solver-tools/lsoda/dense.js.map +1 -0
- package/src/solver-tools/lsoda/dense.ts +141 -0
- package/src/solver-tools/lsoda/index.js +15 -0
- package/src/solver-tools/lsoda/index.js.map +1 -0
- package/src/solver-tools/lsoda/index.ts +17 -0
- package/src/solver-tools/lsoda/intdy.js +54 -0
- package/src/solver-tools/lsoda/intdy.js.map +1 -0
- package/src/solver-tools/lsoda/intdy.ts +62 -0
- package/src/solver-tools/lsoda/lsoda.js +578 -0
- package/src/solver-tools/lsoda/lsoda.js.map +1 -0
- package/src/solver-tools/lsoda/lsoda.ts +644 -0
- package/src/solver-tools/lsoda/methodswitch.js +108 -0
- package/src/solver-tools/lsoda/methodswitch.js.map +1 -0
- package/src/solver-tools/lsoda/methodswitch.ts +119 -0
- package/src/solver-tools/lsoda/orderswitch.js +97 -0
- package/src/solver-tools/lsoda/orderswitch.js.map +1 -0
- package/src/solver-tools/lsoda/orderswitch.ts +107 -0
- package/src/solver-tools/lsoda/prja.js +54 -0
- package/src/solver-tools/lsoda/prja.js.map +1 -0
- package/src/solver-tools/lsoda/prja.ts +61 -0
- package/src/solver-tools/lsoda/scaleh.js +41 -0
- package/src/solver-tools/lsoda/scaleh.js.map +1 -0
- package/src/solver-tools/lsoda/scaleh.ts +45 -0
- package/src/solver-tools/lsoda/solsy.js +25 -0
- package/src/solver-tools/lsoda/solsy.js.map +1 -0
- package/src/solver-tools/lsoda/solsy.ts +30 -0
- package/src/solver-tools/lsoda/stoda.js +270 -0
- package/src/solver-tools/lsoda/stoda.js.map +1 -0
- package/src/solver-tools/lsoda/stoda.ts +298 -0
- package/src/solver-tools/lsoda-method.js +134 -0
- package/src/solver-tools/lsoda-method.js.map +1 -0
- package/src/solver-tools/lsoda-method.ts +154 -0
- package/src/solver-tools/mrt-method.js +81 -18
- package/src/solver-tools/mrt-method.js.map +1 -1
- package/src/solver-tools/mrt-method.ts +111 -21
- package/src/solver-tools/rk3-method.js +210 -0
- package/src/solver-tools/rk3-method.js.map +1 -0
- package/src/solver-tools/rk3-method.ts +257 -0
- package/src/solver-tools/rk4-method.js +236 -0
- package/src/solver-tools/rk4-method.js.map +1 -0
- package/src/solver-tools/rk4-method.ts +286 -0
- package/src/solver-tools/rkdp-method.js +247 -0
- package/src/solver-tools/rkdp-method.js.map +1 -0
- package/src/solver-tools/rkdp-method.ts +300 -0
- package/src/solver-tools/ros34prw-method.js +1 -1
- package/src/solver-tools/ros34prw-method.js.map +1 -1
- package/src/solver-tools/ros34prw-method.ts +1 -1
- package/src/solver-tools/ros3prw-method.js +1 -1
- package/src/solver-tools/ros3prw-method.js.map +1 -1
- package/src/solver-tools/ros3prw-method.ts +1 -1
- package/src/solver-tools/solver-defs.js +7 -0
- package/src/solver-tools/solver-defs.js.map +1 -1
- package/src/solver-tools/solver-defs.ts +7 -0
- package/src/tests/correctness.test.js +6 -4
- package/src/tests/correctness.test.js.map +1 -1
- package/src/tests/correctness.test.ts +6 -4
- package/src/tests/cvode-lib-correctness.test.js +404 -0
- package/src/tests/cvode-lib-correctness.test.js.map +1 -0
- package/src/tests/cvode-lib-correctness.test.ts +505 -0
- package/src/tests/cvode-lib-performance.test.js +103 -0
- package/src/tests/cvode-lib-performance.test.js.map +1 -0
- package/src/tests/cvode-lib-performance.test.ts +128 -0
- package/src/tests/lsoda-lib-correctness.test.js +223 -0
- package/src/tests/lsoda-lib-correctness.test.js.map +1 -0
- package/src/tests/lsoda-lib-correctness.test.ts +283 -0
- package/src/tests/lsoda-lib-performance.test.js +95 -0
- package/src/tests/lsoda-lib-performance.test.js.map +1 -0
- package/src/tests/lsoda-lib-performance.test.ts +126 -0
- package/src/tests/performance.test.js +12 -8
- package/src/tests/performance.test.js.map +1 -1
- package/src/tests/performance.test.ts +12 -8
- package/src/tests/test-defs.js +20 -1
- package/src/tests/test-defs.js.map +1 -1
- package/src/tests/test-defs.ts +22 -1
- package/src/worker-tools/solving.js +15 -1
- package/src/worker-tools/solving.js.map +1 -1
- package/src/worker-tools/solving.ts +23 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of liblsoda (https://github.com/sdwfrost/liblsoda)
|
|
3
|
+
* Original LSODA algorithm by Linda Petzold & Alan Hindmarsh (1983)
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2011 Yu Feng, McWilliam Cosmology Center, Carnegie Mellon University
|
|
6
|
+
* Copyright (c) 2016 Simon Frost
|
|
7
|
+
* Copyright (c) 2026 Datagrok
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the MIT License. See THIRD_PARTY_LICENSES for the full
|
|
10
|
+
* license text and provenance chain of the original code.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Dense output interpolator. Given a sequence of Nordsieck snapshots
|
|
14
|
+
* captured during integration, evaluates the solution at arbitrary points
|
|
15
|
+
* via Taylor/Horner interpolation.
|
|
16
|
+
*/
|
|
17
|
+
export class DenseOutput {
|
|
18
|
+
constructor(snapshots, neq) {
|
|
19
|
+
if (snapshots.length === 0)
|
|
20
|
+
throw new Error('[DenseOutput] no snapshots collected');
|
|
21
|
+
this.snaps = snapshots;
|
|
22
|
+
this.neq = neq;
|
|
23
|
+
}
|
|
24
|
+
/** Leftmost reachable time. */
|
|
25
|
+
get tMin() {
|
|
26
|
+
const s = this.snaps[0];
|
|
27
|
+
return s.tn - s.hu;
|
|
28
|
+
}
|
|
29
|
+
/** Rightmost reachable time. */
|
|
30
|
+
get tMax() {
|
|
31
|
+
return this.snaps[this.snaps.length - 1].tn;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Evaluate the solution at a single time point.
|
|
35
|
+
* Uses Horner's method on the Nordsieck array of the enclosing step.
|
|
36
|
+
*/
|
|
37
|
+
evaluateAt(t) {
|
|
38
|
+
const snap = this.findSnap(t);
|
|
39
|
+
return this.horner(snap, t, new Float64Array(this.neq));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Evaluate the solution at each point in a sorted ascending array.
|
|
43
|
+
* Uses a linear scan over snapshots for efficiency.
|
|
44
|
+
*/
|
|
45
|
+
solveAtTimes(tArray) {
|
|
46
|
+
if (tArray.length === 0)
|
|
47
|
+
return [];
|
|
48
|
+
const snaps = this.snaps;
|
|
49
|
+
// Validate range
|
|
50
|
+
const tFirst = tArray[0];
|
|
51
|
+
const tLast = tArray[tArray.length - 1];
|
|
52
|
+
if (tFirst < this.tMin - 1e-14 * Math.abs(this.tMin))
|
|
53
|
+
throw new Error(`[DenseOutput] t=${tFirst} is before tMin=${this.tMin}`);
|
|
54
|
+
if (tLast > this.tMax + 1e-14 * Math.abs(this.tMax))
|
|
55
|
+
throw new Error(`[DenseOutput] t=${tLast} is after tMax=${this.tMax}`);
|
|
56
|
+
const dky = new Float64Array(this.neq);
|
|
57
|
+
const result = [];
|
|
58
|
+
for (let i = 0; i < this.neq; ++i)
|
|
59
|
+
result.push(new Float64Array(tArray.length));
|
|
60
|
+
let si = 0; // snapshot pointer
|
|
61
|
+
for (let qi = 0; qi < tArray.length; qi++) {
|
|
62
|
+
const t = tArray[qi];
|
|
63
|
+
// Advance snapshot pointer until we find an interval containing t
|
|
64
|
+
while (si < snaps.length - 1 && t > snaps[si].tn + 1e-14 * Math.abs(snaps[si].tn))
|
|
65
|
+
si++;
|
|
66
|
+
this.horner(snaps[si], t, dky);
|
|
67
|
+
for (let i = 0; i < this.neq; ++i)
|
|
68
|
+
result[i][qi] = dky[i];
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Evaluate the solution on a uniform grid from tStart to tEnd with given step.
|
|
74
|
+
*/
|
|
75
|
+
solveOnGrid(tStart, tEnd, step) {
|
|
76
|
+
if (step <= 0)
|
|
77
|
+
throw new Error('[DenseOutput] step must be positive');
|
|
78
|
+
const n = Math.floor((tEnd - tStart) / step) + 1;
|
|
79
|
+
const tArr = new Float64Array(n);
|
|
80
|
+
for (let i = 0; i < n - 1; i++)
|
|
81
|
+
tArr[i] = tStart + i * step;
|
|
82
|
+
tArr[n - 1] = tEnd;
|
|
83
|
+
const t = tArr;
|
|
84
|
+
const y = this.solveAtTimes(t);
|
|
85
|
+
return { t, y };
|
|
86
|
+
}
|
|
87
|
+
/** Find the snapshot whose interval contains t via binary search. */
|
|
88
|
+
findSnap(t) {
|
|
89
|
+
const snaps = this.snaps;
|
|
90
|
+
// Quick boundary checks
|
|
91
|
+
if (t <= snaps[0].tn)
|
|
92
|
+
return snaps[0];
|
|
93
|
+
if (t >= snaps[snaps.length - 1].tn)
|
|
94
|
+
return snaps[snaps.length - 1];
|
|
95
|
+
// Binary search: find first snap with tn >= t
|
|
96
|
+
let lo = 0;
|
|
97
|
+
let hi = snaps.length - 1;
|
|
98
|
+
while (lo < hi) {
|
|
99
|
+
const mid = (lo + hi) >>> 1;
|
|
100
|
+
if (snaps[mid].tn < t)
|
|
101
|
+
lo = mid + 1;
|
|
102
|
+
else
|
|
103
|
+
hi = mid;
|
|
104
|
+
}
|
|
105
|
+
return snaps[lo];
|
|
106
|
+
}
|
|
107
|
+
/** Horner evaluation of the Nordsieck polynomial at time t. */
|
|
108
|
+
horner(snap, t, dky) {
|
|
109
|
+
const { nq, h, yh } = snap;
|
|
110
|
+
const neq = this.neq;
|
|
111
|
+
const s = (t - snap.tn) / h;
|
|
112
|
+
for (let i = 0; i < neq; i++) {
|
|
113
|
+
let val = yh[nq][i];
|
|
114
|
+
for (let j = nq - 1; j >= 0; j--)
|
|
115
|
+
val = yh[j][i] + s * val;
|
|
116
|
+
dky[i] = val;
|
|
117
|
+
}
|
|
118
|
+
return dky;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=dense.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dense.js","sourceRoot":"","sources":["dense.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of liblsoda (https://github.com/sdwfrost/liblsoda)
|
|
3
|
+
* Original LSODA algorithm by Linda Petzold & Alan Hindmarsh (1983)
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2011 Yu Feng, McWilliam Cosmology Center, Carnegie Mellon University
|
|
6
|
+
* Copyright (c) 2016 Simon Frost
|
|
7
|
+
* Copyright (c) 2026 Datagrok
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the MIT License. See THIRD_PARTY_LICENSES for the full
|
|
10
|
+
* license text and provenance chain of the original code.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {NordsieckSnapshot} from './common';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Dense output interpolator. Given a sequence of Nordsieck snapshots
|
|
17
|
+
* captured during integration, evaluates the solution at arbitrary points
|
|
18
|
+
* via Taylor/Horner interpolation.
|
|
19
|
+
*/
|
|
20
|
+
export class DenseOutput {
|
|
21
|
+
private snaps: NordsieckSnapshot[];
|
|
22
|
+
private neq: number;
|
|
23
|
+
|
|
24
|
+
constructor(snapshots: NordsieckSnapshot[], neq: number) {
|
|
25
|
+
if (snapshots.length === 0)
|
|
26
|
+
throw new Error('[DenseOutput] no snapshots collected');
|
|
27
|
+
this.snaps = snapshots;
|
|
28
|
+
this.neq = neq;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Leftmost reachable time. */
|
|
32
|
+
get tMin(): number {
|
|
33
|
+
const s = this.snaps[0];
|
|
34
|
+
return s.tn - s.hu;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Rightmost reachable time. */
|
|
38
|
+
get tMax(): number {
|
|
39
|
+
return this.snaps[this.snaps.length - 1].tn;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Evaluate the solution at a single time point.
|
|
44
|
+
* Uses Horner's method on the Nordsieck array of the enclosing step.
|
|
45
|
+
*/
|
|
46
|
+
evaluateAt(t: number): Float64Array {
|
|
47
|
+
const snap = this.findSnap(t);
|
|
48
|
+
return this.horner(snap, t, new Float64Array(this.neq));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Evaluate the solution at each point in a sorted ascending array.
|
|
53
|
+
* Uses a linear scan over snapshots for efficiency.
|
|
54
|
+
*/
|
|
55
|
+
solveAtTimes(tArray: Float64Array): Float64Array[] {
|
|
56
|
+
if (tArray.length === 0) return [];
|
|
57
|
+
const snaps = this.snaps;
|
|
58
|
+
|
|
59
|
+
// Validate range
|
|
60
|
+
const tFirst = tArray[0];
|
|
61
|
+
const tLast = tArray[tArray.length - 1];
|
|
62
|
+
if (tFirst < this.tMin - 1e-14 * Math.abs(this.tMin))
|
|
63
|
+
throw new Error(`[DenseOutput] t=${tFirst} is before tMin=${this.tMin}`);
|
|
64
|
+
if (tLast > this.tMax + 1e-14 * Math.abs(this.tMax))
|
|
65
|
+
throw new Error(`[DenseOutput] t=${tLast} is after tMax=${this.tMax}`);
|
|
66
|
+
|
|
67
|
+
const dky = new Float64Array(this.neq);
|
|
68
|
+
const result: Float64Array[] = [];
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < this.neq; ++i)
|
|
71
|
+
result.push(new Float64Array(tArray.length));
|
|
72
|
+
|
|
73
|
+
let si = 0; // snapshot pointer
|
|
74
|
+
|
|
75
|
+
for (let qi = 0; qi < tArray.length; qi++) {
|
|
76
|
+
const t = tArray[qi];
|
|
77
|
+
// Advance snapshot pointer until we find an interval containing t
|
|
78
|
+
while (si < snaps.length - 1 && t > snaps[si].tn + 1e-14 * Math.abs(snaps[si].tn))
|
|
79
|
+
si++;
|
|
80
|
+
|
|
81
|
+
this.horner(snaps[si], t, dky);
|
|
82
|
+
|
|
83
|
+
for (let i = 0; i < this.neq; ++i)
|
|
84
|
+
result[i][qi] = dky[i];
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Evaluate the solution on a uniform grid from tStart to tEnd with given step.
|
|
91
|
+
*/
|
|
92
|
+
solveOnGrid(tStart: number, tEnd: number, step: number): { t: Float64Array, y: Float64Array[] } {
|
|
93
|
+
if (step <= 0)
|
|
94
|
+
throw new Error('[DenseOutput] step must be positive');
|
|
95
|
+
|
|
96
|
+
const n = Math.floor((tEnd - tStart) / step) + 1;
|
|
97
|
+
const tArr = new Float64Array(n);
|
|
98
|
+
for (let i = 0; i < n - 1; i++)
|
|
99
|
+
tArr[i] = tStart + i * step;
|
|
100
|
+
tArr[n - 1] = tEnd;
|
|
101
|
+
|
|
102
|
+
const t = tArr;
|
|
103
|
+
const y = this.solveAtTimes(t);
|
|
104
|
+
return {t, y};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Find the snapshot whose interval contains t via binary search. */
|
|
108
|
+
private findSnap(t: number): NordsieckSnapshot {
|
|
109
|
+
const snaps = this.snaps;
|
|
110
|
+
|
|
111
|
+
// Quick boundary checks
|
|
112
|
+
if (t <= snaps[0].tn) return snaps[0];
|
|
113
|
+
if (t >= snaps[snaps.length - 1].tn) return snaps[snaps.length - 1];
|
|
114
|
+
|
|
115
|
+
// Binary search: find first snap with tn >= t
|
|
116
|
+
let lo = 0; let hi = snaps.length - 1;
|
|
117
|
+
while (lo < hi) {
|
|
118
|
+
const mid = (lo + hi) >>> 1;
|
|
119
|
+
if (snaps[mid].tn < t)
|
|
120
|
+
lo = mid + 1;
|
|
121
|
+
else
|
|
122
|
+
hi = mid;
|
|
123
|
+
}
|
|
124
|
+
return snaps[lo];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Horner evaluation of the Nordsieck polynomial at time t. */
|
|
128
|
+
private horner(snap: NordsieckSnapshot, t: number, dky: Float64Array): Float64Array {
|
|
129
|
+
const {nq, h, yh} = snap;
|
|
130
|
+
const neq = this.neq;
|
|
131
|
+
const s = (t - snap.tn) / h;
|
|
132
|
+
|
|
133
|
+
for (let i = 0; i < neq; i++) {
|
|
134
|
+
let val = yh[nq][i];
|
|
135
|
+
for (let j = nq - 1; j >= 0; j--)
|
|
136
|
+
val = yh[j][i] + s * val;
|
|
137
|
+
dky[i] = val;
|
|
138
|
+
}
|
|
139
|
+
return dky;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of liblsoda (https://github.com/sdwfrost/liblsoda)
|
|
3
|
+
* Original LSODA algorithm by Linda Petzold & Alan Hindmarsh (1983)
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2011 Yu Feng, McWilliam Cosmology Center, Carnegie Mellon University
|
|
6
|
+
* Copyright (c) 2016 Simon Frost
|
|
7
|
+
* Copyright (c) 2026 Datagrok
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the MIT License. See THIRD_PARTY_LICENSES for the full
|
|
10
|
+
* license text and provenance chain of the original code.
|
|
11
|
+
*/
|
|
12
|
+
export { Lsoda, lsoda, lsodaPrepare, lsodaReset, lsodaFree } from './lsoda';
|
|
13
|
+
export { LsodaContext } from './common';
|
|
14
|
+
export { DenseOutput } from './dense';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAC,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAC,MAAM,SAAS,CAAC;AAG1E,OAAO,EAAC,YAAY,EAAC,MAAM,UAAU,CAAC;AACtC,OAAO,EAAC,WAAW,EAAC,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of liblsoda (https://github.com/sdwfrost/liblsoda)
|
|
3
|
+
* Original LSODA algorithm by Linda Petzold & Alan Hindmarsh (1983)
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2011 Yu Feng, McWilliam Cosmology Center, Carnegie Mellon University
|
|
6
|
+
* Copyright (c) 2016 Simon Frost
|
|
7
|
+
* Copyright (c) 2026 Datagrok
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the MIT License. See THIRD_PARTY_LICENSES for the full
|
|
10
|
+
* license text and provenance chain of the original code.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export {Lsoda, lsoda, lsodaPrepare, lsodaReset, lsodaFree} from './lsoda';
|
|
14
|
+
export type {OdeFunction, LsodaSolveResult} from './lsoda';
|
|
15
|
+
export type {LsodaOpt, LsodaFunc, NordsieckSnapshot} from './common';
|
|
16
|
+
export {LsodaContext} from './common';
|
|
17
|
+
export {DenseOutput} from './dense';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of liblsoda (https://github.com/sdwfrost/liblsoda)
|
|
3
|
+
* Original LSODA algorithm by Linda Petzold & Alan Hindmarsh (1983)
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2011 Yu Feng, McWilliam Cosmology Center, Carnegie Mellon University
|
|
6
|
+
* Copyright (c) 2016 Simon Frost
|
|
7
|
+
* Copyright (c) 2026 Datagrok
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the MIT License. See THIRD_PARTY_LICENSES for the full
|
|
10
|
+
* license text and provenance chain of the original code.
|
|
11
|
+
*/
|
|
12
|
+
import { ETA } from './common';
|
|
13
|
+
/**
|
|
14
|
+
* Interpolate solution at time t using Nordsieck history array.
|
|
15
|
+
* k: derivative order (0 for solution)
|
|
16
|
+
* dky: output array (1-indexed)
|
|
17
|
+
* Returns 0 on success, negative on error.
|
|
18
|
+
*/
|
|
19
|
+
export function intdy(ctx, t, k, dky) {
|
|
20
|
+
const c = ctx.common;
|
|
21
|
+
const neq = ctx.neq;
|
|
22
|
+
if (k < 0 || k > c.nq) {
|
|
23
|
+
console.error(`[intdy] k = ${k} illegal`);
|
|
24
|
+
return -1;
|
|
25
|
+
}
|
|
26
|
+
const tp = c.tn - c.hu - 100. * ETA * (c.tn + c.hu);
|
|
27
|
+
if ((t - tp) * (t - c.tn) > 0.) {
|
|
28
|
+
console.error(`intdy -- t = ${t} illegal. t not in interval tcur - hu to tcur`);
|
|
29
|
+
return -2;
|
|
30
|
+
}
|
|
31
|
+
const s = (t - c.tn) / c.h;
|
|
32
|
+
let ic = 1;
|
|
33
|
+
for (let jj = (c.nq + 1) - k; jj <= c.nq; jj++)
|
|
34
|
+
ic *= jj;
|
|
35
|
+
let cc = ic;
|
|
36
|
+
for (let i = 1; i <= neq; i++)
|
|
37
|
+
dky[i] = cc * c.yh[c.nq + 1][i];
|
|
38
|
+
for (let j = c.nq - 1; j >= k; j--) {
|
|
39
|
+
const jp1 = j + 1;
|
|
40
|
+
ic = 1;
|
|
41
|
+
for (let jj = jp1 - k; jj <= j; jj++)
|
|
42
|
+
ic *= jj;
|
|
43
|
+
cc = ic;
|
|
44
|
+
for (let i = 1; i <= neq; i++)
|
|
45
|
+
dky[i] = cc * c.yh[jp1][i] + s * dky[i];
|
|
46
|
+
}
|
|
47
|
+
if (k === 0)
|
|
48
|
+
return 0;
|
|
49
|
+
const r = Math.pow(c.h, -k);
|
|
50
|
+
for (let i = 1; i <= neq; i++)
|
|
51
|
+
dky[i] *= r;
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=intdy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intdy.js","sourceRoot":"","sources":["intdy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAe,GAAG,EAAC,MAAM,UAAU,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,UAAU,KAAK,CAAC,GAAiB,EAAE,CAAS,EAAE,CAAS,EAAE,GAAiB;IAC9E,MAAM,CAAC,GAAG,GAAG,CAAC,MAAO,CAAC;IACtB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC;IAEpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QAC1C,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IACpD,IAAI,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,+CAA+C,CAAC,CAAC;QAChF,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3B,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,KAAK,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE;QAC5C,EAAE,IAAI,EAAE,CAAC;IACX,IAAI,EAAE,GAAG,EAAE,CAAC;IAEZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE;QAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElC,KAAK,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAClB,EAAE,GAAG,CAAC,CAAC;QACP,KAAK,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE;YAClC,EAAE,IAAI,EAAE,CAAC;QACX,EAAE,GAAG,EAAE,CAAC;QACR,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE;YAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAEtB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE;QAC3B,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of liblsoda (https://github.com/sdwfrost/liblsoda)
|
|
3
|
+
* Original LSODA algorithm by Linda Petzold & Alan Hindmarsh (1983)
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2011 Yu Feng, McWilliam Cosmology Center, Carnegie Mellon University
|
|
6
|
+
* Copyright (c) 2016 Simon Frost
|
|
7
|
+
* Copyright (c) 2026 Datagrok
|
|
8
|
+
*
|
|
9
|
+
* Licensed under the MIT License. See THIRD_PARTY_LICENSES for the full
|
|
10
|
+
* license text and provenance chain of the original code.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {LsodaContext, ETA} from './common';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Interpolate solution at time t using Nordsieck history array.
|
|
17
|
+
* k: derivative order (0 for solution)
|
|
18
|
+
* dky: output array (1-indexed)
|
|
19
|
+
* Returns 0 on success, negative on error.
|
|
20
|
+
*/
|
|
21
|
+
export function intdy(ctx: LsodaContext, t: number, k: number, dky: Float64Array): number {
|
|
22
|
+
const c = ctx.common!;
|
|
23
|
+
const neq = ctx.neq;
|
|
24
|
+
|
|
25
|
+
if (k < 0 || k > c.nq) {
|
|
26
|
+
console.error(`[intdy] k = ${k} illegal`);
|
|
27
|
+
return -1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const tp = c.tn - c.hu - 100. * ETA * (c.tn + c.hu);
|
|
31
|
+
if ((t - tp) * (t - c.tn) > 0.) {
|
|
32
|
+
console.error(`intdy -- t = ${t} illegal. t not in interval tcur - hu to tcur`);
|
|
33
|
+
return -2;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const s = (t - c.tn) / c.h;
|
|
37
|
+
let ic = 1;
|
|
38
|
+
for (let jj = (c.nq + 1) - k; jj <= c.nq; jj++)
|
|
39
|
+
ic *= jj;
|
|
40
|
+
let cc = ic;
|
|
41
|
+
|
|
42
|
+
for (let i = 1; i <= neq; i++)
|
|
43
|
+
dky[i] = cc * c.yh[c.nq + 1][i];
|
|
44
|
+
|
|
45
|
+
for (let j = c.nq - 1; j >= k; j--) {
|
|
46
|
+
const jp1 = j + 1;
|
|
47
|
+
ic = 1;
|
|
48
|
+
for (let jj = jp1 - k; jj <= j; jj++)
|
|
49
|
+
ic *= jj;
|
|
50
|
+
cc = ic;
|
|
51
|
+
for (let i = 1; i <= neq; i++)
|
|
52
|
+
dky[i] = cc * c.yh[jp1][i] + s * dky[i];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (k === 0) return 0;
|
|
56
|
+
|
|
57
|
+
const r = Math.pow(c.h, -k);
|
|
58
|
+
for (let i = 1; i <= neq; i++)
|
|
59
|
+
dky[i] *= r;
|
|
60
|
+
|
|
61
|
+
return 0;
|
|
62
|
+
}
|