diff-grok 1.1.0 → 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/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 +10 -4
- package/LICENSE +1 -1
- package/README.MD +41 -23
- package/THIRD_PARTY_LICENSES +135 -0
- package/docs/.nojekyll +1 -0
- package/docs/assets/hierarchy.js +1 -0
- package/docs/assets/highlight.css +99 -0
- package/docs/assets/icons.js +18 -0
- package/docs/assets/icons.svg +1 -0
- package/docs/assets/main.js +60 -0
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -0
- package/docs/assets/style.css +1633 -0
- package/docs/classes/BasicModelPipelineCreator.html +10 -0
- package/docs/classes/Callback.html +7 -0
- package/docs/classes/CyclicModelPipelineCreator.html +10 -0
- package/docs/classes/IterCheckerCallback.html +8 -0
- package/docs/classes/PipelineCreator.html +6 -0
- package/docs/classes/TimeCheckerCallback.html +8 -0
- package/docs/classes/UpdatesModelPipelineCreator.html +10 -0
- package/docs/functions/ab4.html +8 -0
- package/docs/functions/ab5.html +8 -0
- package/docs/functions/applyPipeline.html +9 -0
- package/docs/functions/getCallback.html +3 -0
- package/docs/functions/getIVP.html +6 -0
- package/docs/functions/getInputVector.html +2 -0
- package/docs/functions/getIvp2WebWorker.html +6 -0
- package/docs/functions/getJScode.html +6 -0
- package/docs/functions/getOutputNames.html +4 -0
- package/docs/functions/getPipelineCreator.html +7 -0
- package/docs/functions/lsoda.html +8 -0
- package/docs/functions/mrt.html +11 -0
- package/docs/functions/printE5.html +76 -0
- package/docs/functions/printHires.html +76 -0
- package/docs/functions/printOrego.html +66 -0
- package/docs/functions/printPollution.html +163 -0
- package/docs/functions/printRobertson.html +60 -0
- package/docs/functions/printVdpol.html +66 -0
- 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 +8 -0
- package/docs/functions/ros3prw.html +8 -0
- package/docs/functions/solveIvp.html +5 -0
- package/docs/hierarchy.html +1 -0
- package/docs/index.html +768 -0
- package/docs/media/CONTRIBUTING.md +74 -0
- 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/POLL.png +0 -0
- package/docs/media/ROBER.png +0 -0
- package/docs/media/VDP0L.png +0 -0
- package/docs/media/VDPOL.png +0 -0
- package/docs/media/acid-prod.gif +0 -0
- package/docs/media/basic-use.js +40 -0
- package/docs/media/basic-use.js.map +1 -0
- package/docs/media/basic-use.ts +44 -0
- package/docs/media/check-methods.js +59 -0
- package/docs/media/check-methods.js.map +1 -0
- package/docs/media/check-methods.ts +81 -0
- package/docs/media/corr-probs.js +132 -0
- package/docs/media/corr-probs.js.map +1 -0
- package/docs/media/corr-probs.ts +155 -0
- package/docs/media/cyclic-model.js +102 -0
- package/docs/media/cyclic-model.js.map +1 -0
- package/docs/media/cyclic-model.ts +112 -0
- package/docs/media/e5.js +36 -0
- package/docs/media/e5.js.map +1 -0
- package/docs/media/e5.ts +36 -0
- package/docs/media/hires.js +39 -0
- package/docs/media/hires.js.map +1 -0
- package/docs/media/hires.ts +40 -0
- package/docs/media/model-updates.js +112 -0
- package/docs/media/model-updates.js.map +1 -0
- package/docs/media/model-updates.ts +122 -0
- package/docs/media/orego.js +24 -0
- package/docs/media/orego.js.map +1 -0
- package/docs/media/orego.ts +25 -0
- package/docs/media/pipeline-use.js +87 -0
- package/docs/media/pipeline-use.js.map +1 -0
- package/docs/media/pipeline-use.ts +98 -0
- package/docs/media/pollution.js +132 -0
- package/docs/media/pollution.js.map +1 -0
- package/docs/media/pollution.ts +133 -0
- package/docs/media/print-benchmark.js +581 -0
- package/docs/media/print-benchmark.js.map +1 -0
- package/docs/media/print-benchmark.ts +594 -0
- package/docs/media/robertson.js +19 -0
- package/docs/media/robertson.js.map +1 -0
- package/docs/media/robertson.ts +19 -0
- package/docs/media/scripting.js +30 -0
- package/docs/media/scripting.js.map +1 -0
- package/docs/media/scripting.ts +35 -0
- package/docs/media/vdpol.js +17 -0
- package/docs/media/vdpol.js.map +1 -0
- package/docs/media/vdpol.ts +17 -0
- package/docs/modules.html +1 -0
- package/docs/types/Arg.html +12 -0
- package/docs/types/DifEqs.html +8 -0
- package/docs/types/Func.html +7 -0
- package/docs/types/IVP.html +40 -0
- package/docs/types/IVP2WebWorker.html +12 -0
- package/docs/types/Input.html +8 -0
- package/docs/types/Loop.html +7 -0
- package/docs/types/ODEs.html +31 -0
- package/docs/types/Output.html +6 -0
- package/docs/types/Pipeline.html +6 -0
- package/docs/types/SolverOptions.html +8 -0
- package/docs/types/Update.html +9 -0
- package/docs/types/Wrapper.html +8 -0
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/index.ts +1 -1
- 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/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 +1 -0
- package/src/solver-tools/index.js.map +1 -1
- package/src/solver-tools/index.ts +1 -0
- package/src/solver-tools/lsoda/blas.js +11 -0
- package/src/solver-tools/lsoda/blas.js.map +1 -1
- package/src/solver-tools/lsoda/blas.ts +12 -0
- package/src/solver-tools/lsoda/cfode.js +11 -0
- package/src/solver-tools/lsoda/cfode.js.map +1 -1
- package/src/solver-tools/lsoda/cfode.ts +12 -0
- package/src/solver-tools/lsoda/corfailure.js +11 -0
- package/src/solver-tools/lsoda/corfailure.js.map +1 -1
- package/src/solver-tools/lsoda/corfailure.ts +12 -0
- package/src/solver-tools/lsoda/correction.js +11 -0
- package/src/solver-tools/lsoda/correction.js.map +1 -1
- package/src/solver-tools/lsoda/correction.ts +12 -0
- package/src/solver-tools/lsoda/dense.js +11 -0
- package/src/solver-tools/lsoda/dense.js.map +1 -1
- package/src/solver-tools/lsoda/dense.ts +12 -0
- package/src/solver-tools/lsoda/index.js +11 -0
- package/src/solver-tools/lsoda/index.js.map +1 -1
- package/src/solver-tools/lsoda/index.ts +12 -0
- package/src/solver-tools/lsoda/intdy.js +11 -0
- package/src/solver-tools/lsoda/intdy.js.map +1 -1
- package/src/solver-tools/lsoda/intdy.ts +12 -0
- package/src/solver-tools/lsoda/lsoda.js +11 -0
- package/src/solver-tools/lsoda/lsoda.js.map +1 -1
- package/src/solver-tools/lsoda/lsoda.ts +12 -0
- package/src/solver-tools/lsoda/methodswitch.js +11 -0
- package/src/solver-tools/lsoda/methodswitch.js.map +1 -1
- package/src/solver-tools/lsoda/methodswitch.ts +12 -0
- package/src/solver-tools/lsoda/orderswitch.js +11 -0
- package/src/solver-tools/lsoda/orderswitch.js.map +1 -1
- package/src/solver-tools/lsoda/orderswitch.ts +12 -0
- package/src/solver-tools/lsoda/prja.js +11 -0
- package/src/solver-tools/lsoda/prja.js.map +1 -1
- package/src/solver-tools/lsoda/prja.ts +12 -0
- package/src/solver-tools/lsoda/scaleh.js +11 -0
- package/src/solver-tools/lsoda/scaleh.js.map +1 -1
- package/src/solver-tools/lsoda/scaleh.ts +12 -0
- package/src/solver-tools/lsoda/solsy.js +11 -0
- package/src/solver-tools/lsoda/solsy.js.map +1 -1
- package/src/solver-tools/lsoda/solsy.ts +12 -0
- package/src/solver-tools/lsoda/stoda.js +11 -0
- package/src/solver-tools/lsoda/stoda.js.map +1 -1
- package/src/solver-tools/lsoda/stoda.ts +12 -0
- package/src/solver-tools/lsoda-method.js +23 -9
- package/src/solver-tools/lsoda-method.js.map +1 -1
- package/src/solver-tools/lsoda-method.ts +27 -9
- package/src/solver-tools/solver-defs.js +1 -0
- package/src/solver-tools/solver-defs.js.map +1 -1
- package/src/solver-tools/solver-defs.ts +1 -0
- 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/performance.test.js +4 -2
- package/src/tests/performance.test.js.map +1 -1
- package/src/tests/performance.test.ts +4 -2
- package/src/tests/test-defs.js +7 -1
- package/src/tests/test-defs.js.map +1 -1
- package/src/tests/test-defs.ts +8 -1
- package/src/worker-tools/solving.js +3 -1
- package/src/worker-tools/solving.js.map +1 -1
- package/src/worker-tools/solving.ts +4 -1
- package/src/examples/bioreactor.js +0 -125
- package/src/examples/bioreactor.js.map +0 -1
- package/src/examples/bioreactor.ts +0 -132
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of SUNDIALS CVODE v7.5.0 (https://github.com/LLNL/sundials)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025, Lawrence Livermore National Security, University of
|
|
5
|
+
* Maryland Baltimore County, and the SUNDIALS contributors.
|
|
6
|
+
* Copyright (c) 2013-2025, Lawrence Livermore National Security and
|
|
7
|
+
* Southern Methodist University.
|
|
8
|
+
* Copyright (c) 2002-2013, Lawrence Livermore National Security.
|
|
9
|
+
* Copyright (c) 2026 Datagrok.
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the BSD-3-Clause License. See THIRD_PARTY_LICENSES
|
|
12
|
+
* for the full license text and provenance chain of the original code.
|
|
13
|
+
*/
|
|
14
|
+
// CVODE TypeScript port - High-level Cvode class API
|
|
15
|
+
// Follows the Lsoda class pattern from src/lsoda.ts
|
|
16
|
+
import { cvodeGetDky, CV_ADAMS, CV_BDF, CV_NORMAL, CV_ONE_STEP, CV_ROOT_RETURN, } from './common';
|
|
17
|
+
import { cvodeCreate, cvodeInit, cvode } from './cvode';
|
|
18
|
+
import { cvodeSetLinearSolver, cvodeSetJacFn } from './cvode_ls';
|
|
19
|
+
import { cvodeRootInit } from './cvode_root';
|
|
20
|
+
import { cvodeGetIntegratorStats, cvodeSStolerances, cvodeSVtolerances, cvodeSetMaxNumSteps, cvodeSetMaxOrd, cvodeSetMaxStep, cvodeSetMinStep, cvodeSetInitStep, cvodeSetStopTime, cvodeSetUserData, } from './cvode_io';
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Cvode class
|
|
23
|
+
// ============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* High-level CVODE solver class with a 0-based public interface.
|
|
26
|
+
*
|
|
27
|
+
* Usage:
|
|
28
|
+
* const solver = new Cvode(f, neq, t0, y0, { lmm: 'bdf', rtol: 1e-6, atol: 1e-9 });
|
|
29
|
+
* const result = solver.solve(tout);
|
|
30
|
+
*/
|
|
31
|
+
export class Cvode {
|
|
32
|
+
constructor(f, neq, t0, y0, options) {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
this.neq = neq;
|
|
35
|
+
this.yout = new Float64Array(neq);
|
|
36
|
+
const opts = options !== null && options !== void 0 ? options : {};
|
|
37
|
+
// --- 1. Create CvodeMem ---
|
|
38
|
+
const lmmValue = (opts.lmm === 'adams') ? CV_ADAMS : CV_BDF;
|
|
39
|
+
this.mem = cvodeCreate(lmmValue);
|
|
40
|
+
// --- 2. Wrap user's OdeFunction to CvodeRhsFn (void -> number) ---
|
|
41
|
+
this.wrappedF = (_t, _y, _ydot, _userData) => {
|
|
42
|
+
f(_t, _y, _ydot);
|
|
43
|
+
return 0;
|
|
44
|
+
};
|
|
45
|
+
// --- 3. Initialize ---
|
|
46
|
+
cvodeInit(this.mem, this.wrappedF, t0, y0);
|
|
47
|
+
// --- 4. Set tolerances ---
|
|
48
|
+
const rtol = (_a = opts.rtol) !== null && _a !== void 0 ? _a : 1e-4;
|
|
49
|
+
const atol = (_b = opts.atol) !== null && _b !== void 0 ? _b : 1e-6;
|
|
50
|
+
if (typeof atol === 'number')
|
|
51
|
+
cvodeSStolerances(this.mem, rtol, atol);
|
|
52
|
+
else
|
|
53
|
+
cvodeSVtolerances(this.mem, rtol, atol);
|
|
54
|
+
// --- 5. Set up dense linear solver (required for BDF; optional but useful for Adams) ---
|
|
55
|
+
cvodeSetLinearSolver(this.mem);
|
|
56
|
+
// --- 6. Set user-supplied Jacobian if provided ---
|
|
57
|
+
if (opts.jacFn) {
|
|
58
|
+
const userJac = opts.jacFn;
|
|
59
|
+
const wrappedJacFn = (t, y, fy, J, userData) => {
|
|
60
|
+
userJac(t, y, fy, J);
|
|
61
|
+
return 0;
|
|
62
|
+
};
|
|
63
|
+
cvodeSetJacFn(this.mem, wrappedJacFn);
|
|
64
|
+
}
|
|
65
|
+
// --- 7. Apply optional settings ---
|
|
66
|
+
if (opts.maxSteps !== undefined)
|
|
67
|
+
cvodeSetMaxNumSteps(this.mem, opts.maxSteps);
|
|
68
|
+
if (opts.maxOrder !== undefined)
|
|
69
|
+
cvodeSetMaxOrd(this.mem, opts.maxOrder);
|
|
70
|
+
if (opts.maxStep !== undefined)
|
|
71
|
+
cvodeSetMaxStep(this.mem, opts.maxStep);
|
|
72
|
+
if (opts.minStep !== undefined)
|
|
73
|
+
cvodeSetMinStep(this.mem, opts.minStep);
|
|
74
|
+
if (opts.initStep !== undefined)
|
|
75
|
+
cvodeSetInitStep(this.mem, opts.initStep);
|
|
76
|
+
if (opts.stopTime !== undefined)
|
|
77
|
+
cvodeSetStopTime(this.mem, opts.stopTime);
|
|
78
|
+
if (opts.userData !== undefined)
|
|
79
|
+
cvodeSetUserData(this.mem, opts.userData);
|
|
80
|
+
// --- 8. Set up rootfinding if requested ---
|
|
81
|
+
if (opts.rootFn && opts.nRootFns && opts.nRootFns > 0) {
|
|
82
|
+
const userRoot = opts.rootFn;
|
|
83
|
+
const wrappedRootFn = (t, y, gout, _userData) => {
|
|
84
|
+
userRoot(t, y, gout);
|
|
85
|
+
return 0;
|
|
86
|
+
};
|
|
87
|
+
cvodeRootInit(this.mem, opts.nRootFns, wrappedRootFn);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ==========================================================================
|
|
91
|
+
// Public methods
|
|
92
|
+
// ==========================================================================
|
|
93
|
+
/**
|
|
94
|
+
* Integrate from the current time to tout using CV_NORMAL mode
|
|
95
|
+
* (integrator advances to tout and interpolates).
|
|
96
|
+
*
|
|
97
|
+
* @param tout - target output time
|
|
98
|
+
* @returns CvodeSolveResult with { t, y, flag, rootsFound? }
|
|
99
|
+
*/
|
|
100
|
+
solve(tout) {
|
|
101
|
+
const { flag, t } = cvode(this.mem, tout, this.yout, CV_NORMAL);
|
|
102
|
+
return this._buildResult(t, flag);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Take a single internal step using CV_ONE_STEP mode.
|
|
106
|
+
* The solver advances by one internal step of whatever size it chooses.
|
|
107
|
+
*
|
|
108
|
+
* @returns CvodeSolveResult with { t, y, flag, rootsFound? }
|
|
109
|
+
*/
|
|
110
|
+
step() {
|
|
111
|
+
const { flag, t } = cvode(this.mem, 1e30, this.yout, CV_ONE_STEP);
|
|
112
|
+
return this._buildResult(t, flag);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Dense output: compute the k-th derivative of the interpolating polynomial
|
|
116
|
+
* at time t using the current Nordsieck history array.
|
|
117
|
+
*
|
|
118
|
+
* @param t - interpolation time (must be within the last step interval)
|
|
119
|
+
* @param k - derivative order (0 = solution, 1 = first derivative, ...)
|
|
120
|
+
* @returns copy of the interpolated vector (length neq)
|
|
121
|
+
*/
|
|
122
|
+
getDky(t, k) {
|
|
123
|
+
const dky = new Float64Array(this.neq);
|
|
124
|
+
const flag = cvodeGetDky(this.mem, t, k, dky);
|
|
125
|
+
if (flag !== 0)
|
|
126
|
+
throw new Error(`[Cvode] getDky failed: t=${t} out of range or k=${k} invalid`);
|
|
127
|
+
return dky;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Return current integrator statistics.
|
|
131
|
+
*/
|
|
132
|
+
getStats() {
|
|
133
|
+
return cvodeGetIntegratorStats(this.mem);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Re-initialize the solver for a new initial-value problem with the same
|
|
137
|
+
* ODE function and options. Resets internal state and counters.
|
|
138
|
+
*
|
|
139
|
+
* @param t0 - new initial time
|
|
140
|
+
* @param y0 - new initial conditions (length neq)
|
|
141
|
+
*/
|
|
142
|
+
reInit(t0, y0) {
|
|
143
|
+
cvodeInit(this.mem, this.wrappedF, t0, y0);
|
|
144
|
+
}
|
|
145
|
+
// ==========================================================================
|
|
146
|
+
// Private helpers
|
|
147
|
+
// ==========================================================================
|
|
148
|
+
_buildResult(t, flag) {
|
|
149
|
+
const y = new Float64Array(this.yout); // copy
|
|
150
|
+
const result = { t, y, flag };
|
|
151
|
+
if (flag === CV_ROOT_RETURN) {
|
|
152
|
+
// Return a copy of the root direction info array
|
|
153
|
+
result.rootsFound = new Int32Array(this.mem.cv_iroots);
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=cvode_class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cvode_class.js","sourceRoot":"","sources":["cvode_class.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of SUNDIALS CVODE v7.5.0 (https://github.com/LLNL/sundials)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025, Lawrence Livermore National Security, University of
|
|
5
|
+
* Maryland Baltimore County, and the SUNDIALS contributors.
|
|
6
|
+
* Copyright (c) 2013-2025, Lawrence Livermore National Security and
|
|
7
|
+
* Southern Methodist University.
|
|
8
|
+
* Copyright (c) 2002-2013, Lawrence Livermore National Security.
|
|
9
|
+
* Copyright (c) 2026 Datagrok.
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the BSD-3-Clause License. See THIRD_PARTY_LICENSES
|
|
12
|
+
* for the full license text and provenance chain of the original code.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// CVODE TypeScript port - High-level Cvode class API
|
|
16
|
+
// Follows the Lsoda class pattern from src/lsoda.ts
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
CvodeMem,
|
|
20
|
+
CvodeRhsFn,
|
|
21
|
+
CvodeJacFn,
|
|
22
|
+
CvodeRootFn,
|
|
23
|
+
cvodeGetDky,
|
|
24
|
+
CV_ADAMS, CV_BDF,
|
|
25
|
+
CV_NORMAL, CV_ONE_STEP,
|
|
26
|
+
CV_ROOT_RETURN,
|
|
27
|
+
} from './common';
|
|
28
|
+
|
|
29
|
+
import {cvodeCreate, cvodeInit, cvode} from './cvode';
|
|
30
|
+
import {cvodeSetLinearSolver, cvodeSetJacFn} from './cvode_ls';
|
|
31
|
+
import {cvodeRootInit} from './cvode_root';
|
|
32
|
+
import {
|
|
33
|
+
CvodeStats,
|
|
34
|
+
cvodeGetIntegratorStats,
|
|
35
|
+
cvodeSStolerances,
|
|
36
|
+
cvodeSVtolerances,
|
|
37
|
+
cvodeSetMaxNumSteps,
|
|
38
|
+
cvodeSetMaxOrd,
|
|
39
|
+
cvodeSetMaxStep,
|
|
40
|
+
cvodeSetMinStep,
|
|
41
|
+
cvodeSetInitStep,
|
|
42
|
+
cvodeSetStopTime,
|
|
43
|
+
cvodeSetUserData,
|
|
44
|
+
} from './cvode_io';
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Public types
|
|
48
|
+
// ============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* User ODE function: y' = f(t, y).
|
|
52
|
+
* Arrays are 0-based. Return value is void; wrapping to int is done internally.
|
|
53
|
+
*/
|
|
54
|
+
export type OdeFunction = (t: number, y: Float64Array, ydot: Float64Array) => void;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Options for the Cvode solver.
|
|
58
|
+
*/
|
|
59
|
+
export interface CvodeOptions {
|
|
60
|
+
/** Linear multistep method: 'adams' (non-stiff) or 'bdf' (stiff). Default: 'bdf'. */
|
|
61
|
+
lmm?: 'adams' | 'bdf';
|
|
62
|
+
/** Relative tolerance. Default: 1e-4. */
|
|
63
|
+
rtol?: number;
|
|
64
|
+
/** Absolute tolerance: scalar or per-component array. Default: 1e-6. */
|
|
65
|
+
atol?: number | Float64Array;
|
|
66
|
+
/** Maximum number of internal steps per cvode() call. */
|
|
67
|
+
maxSteps?: number;
|
|
68
|
+
/** Maximum method order. */
|
|
69
|
+
maxOrder?: number;
|
|
70
|
+
/** Maximum step size (0 = no limit). */
|
|
71
|
+
maxStep?: number;
|
|
72
|
+
/** Minimum step size. */
|
|
73
|
+
minStep?: number;
|
|
74
|
+
/** Initial step size (0 = auto-select). */
|
|
75
|
+
initStep?: number;
|
|
76
|
+
/** Stop time: integration will not proceed past this value. */
|
|
77
|
+
stopTime?: number;
|
|
78
|
+
/** Root function: g(t, y, gout). */
|
|
79
|
+
rootFn?: (t: number, y: Float64Array, gout: Float64Array) => void;
|
|
80
|
+
/** Number of root functions (required when rootFn is provided). */
|
|
81
|
+
nRootFns?: number;
|
|
82
|
+
/** User-supplied Jacobian function: J = df/dy. */
|
|
83
|
+
jacFn?: (t: number, y: Float64Array, fy: Float64Array, J: Float64Array[]) => void;
|
|
84
|
+
/** Arbitrary user data (passed as context, not forwarded to callbacks). */
|
|
85
|
+
userData?: any;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Result returned by solve() and step().
|
|
90
|
+
*/
|
|
91
|
+
export interface CvodeSolveResult {
|
|
92
|
+
/** Time reached by the solver. */
|
|
93
|
+
t: number;
|
|
94
|
+
/** Solution vector at time t (0-based, copy). */
|
|
95
|
+
y: Float64Array;
|
|
96
|
+
/** Solver flag (CV_SUCCESS=0, CV_ROOT_RETURN=2, CV_TSTOP_RETURN=1, negative=error). */
|
|
97
|
+
flag: number;
|
|
98
|
+
/** Root indices found when flag === CV_ROOT_RETURN. */
|
|
99
|
+
rootsFound?: Int32Array;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Cvode class
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* High-level CVODE solver class with a 0-based public interface.
|
|
108
|
+
*
|
|
109
|
+
* Usage:
|
|
110
|
+
* const solver = new Cvode(f, neq, t0, y0, { lmm: 'bdf', rtol: 1e-6, atol: 1e-9 });
|
|
111
|
+
* const result = solver.solve(tout);
|
|
112
|
+
*/
|
|
113
|
+
export class Cvode {
|
|
114
|
+
private mem: CvodeMem;
|
|
115
|
+
private neq: number;
|
|
116
|
+
/** Output vector reused across calls (0-based, neq elements). */
|
|
117
|
+
private yout: Float64Array;
|
|
118
|
+
/** Wrapped RHS stored to allow re-initialization. */
|
|
119
|
+
private wrappedF: CvodeRhsFn;
|
|
120
|
+
|
|
121
|
+
constructor(
|
|
122
|
+
f: OdeFunction,
|
|
123
|
+
neq: number,
|
|
124
|
+
t0: number,
|
|
125
|
+
y0: Float64Array,
|
|
126
|
+
options?: CvodeOptions,
|
|
127
|
+
) {
|
|
128
|
+
this.neq = neq;
|
|
129
|
+
this.yout = new Float64Array(neq);
|
|
130
|
+
|
|
131
|
+
const opts = options ?? {};
|
|
132
|
+
|
|
133
|
+
// --- 1. Create CvodeMem ---
|
|
134
|
+
const lmmValue = (opts.lmm === 'adams') ? CV_ADAMS : CV_BDF;
|
|
135
|
+
this.mem = cvodeCreate(lmmValue);
|
|
136
|
+
|
|
137
|
+
// --- 2. Wrap user's OdeFunction to CvodeRhsFn (void -> number) ---
|
|
138
|
+
this.wrappedF = (_t: number, _y: Float64Array, _ydot: Float64Array, _userData: any): number => {
|
|
139
|
+
f(_t, _y, _ydot);
|
|
140
|
+
return 0;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// --- 3. Initialize ---
|
|
144
|
+
cvodeInit(this.mem, this.wrappedF, t0, y0);
|
|
145
|
+
|
|
146
|
+
// --- 4. Set tolerances ---
|
|
147
|
+
const rtol = opts.rtol ?? 1e-4;
|
|
148
|
+
const atol = opts.atol ?? 1e-6;
|
|
149
|
+
|
|
150
|
+
if (typeof atol === 'number')
|
|
151
|
+
cvodeSStolerances(this.mem, rtol, atol);
|
|
152
|
+
else
|
|
153
|
+
cvodeSVtolerances(this.mem, rtol, atol);
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
// --- 5. Set up dense linear solver (required for BDF; optional but useful for Adams) ---
|
|
157
|
+
cvodeSetLinearSolver(this.mem);
|
|
158
|
+
|
|
159
|
+
// --- 6. Set user-supplied Jacobian if provided ---
|
|
160
|
+
if (opts.jacFn) {
|
|
161
|
+
const userJac = opts.jacFn;
|
|
162
|
+
const wrappedJacFn: CvodeJacFn = (
|
|
163
|
+
t: number, y: Float64Array, fy: Float64Array,
|
|
164
|
+
J: Float64Array[], userData: any,
|
|
165
|
+
): number => {
|
|
166
|
+
userJac(t, y, fy, J);
|
|
167
|
+
return 0;
|
|
168
|
+
};
|
|
169
|
+
cvodeSetJacFn(this.mem, wrappedJacFn);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// --- 7. Apply optional settings ---
|
|
173
|
+
if (opts.maxSteps !== undefined) cvodeSetMaxNumSteps(this.mem, opts.maxSteps);
|
|
174
|
+
if (opts.maxOrder !== undefined) cvodeSetMaxOrd(this.mem, opts.maxOrder);
|
|
175
|
+
if (opts.maxStep !== undefined) cvodeSetMaxStep(this.mem, opts.maxStep);
|
|
176
|
+
if (opts.minStep !== undefined) cvodeSetMinStep(this.mem, opts.minStep);
|
|
177
|
+
if (opts.initStep !== undefined) cvodeSetInitStep(this.mem, opts.initStep);
|
|
178
|
+
if (opts.stopTime !== undefined) cvodeSetStopTime(this.mem, opts.stopTime);
|
|
179
|
+
if (opts.userData !== undefined) cvodeSetUserData(this.mem, opts.userData);
|
|
180
|
+
|
|
181
|
+
// --- 8. Set up rootfinding if requested ---
|
|
182
|
+
if (opts.rootFn && opts.nRootFns && opts.nRootFns > 0) {
|
|
183
|
+
const userRoot = opts.rootFn;
|
|
184
|
+
const wrappedRootFn: CvodeRootFn = (
|
|
185
|
+
t: number, y: Float64Array, gout: Float64Array, _userData: any,
|
|
186
|
+
): number => {
|
|
187
|
+
userRoot(t, y, gout);
|
|
188
|
+
return 0;
|
|
189
|
+
};
|
|
190
|
+
cvodeRootInit(this.mem, opts.nRootFns, wrappedRootFn);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ==========================================================================
|
|
195
|
+
// Public methods
|
|
196
|
+
// ==========================================================================
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Integrate from the current time to tout using CV_NORMAL mode
|
|
200
|
+
* (integrator advances to tout and interpolates).
|
|
201
|
+
*
|
|
202
|
+
* @param tout - target output time
|
|
203
|
+
* @returns CvodeSolveResult with { t, y, flag, rootsFound? }
|
|
204
|
+
*/
|
|
205
|
+
solve(tout: number): CvodeSolveResult {
|
|
206
|
+
const {flag, t} = cvode(this.mem, tout, this.yout, CV_NORMAL);
|
|
207
|
+
return this._buildResult(t, flag);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Take a single internal step using CV_ONE_STEP mode.
|
|
212
|
+
* The solver advances by one internal step of whatever size it chooses.
|
|
213
|
+
*
|
|
214
|
+
* @returns CvodeSolveResult with { t, y, flag, rootsFound? }
|
|
215
|
+
*/
|
|
216
|
+
step(): CvodeSolveResult {
|
|
217
|
+
const {flag, t} = cvode(this.mem, 1e30, this.yout, CV_ONE_STEP);
|
|
218
|
+
return this._buildResult(t, flag);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Dense output: compute the k-th derivative of the interpolating polynomial
|
|
223
|
+
* at time t using the current Nordsieck history array.
|
|
224
|
+
*
|
|
225
|
+
* @param t - interpolation time (must be within the last step interval)
|
|
226
|
+
* @param k - derivative order (0 = solution, 1 = first derivative, ...)
|
|
227
|
+
* @returns copy of the interpolated vector (length neq)
|
|
228
|
+
*/
|
|
229
|
+
getDky(t: number, k: number): Float64Array {
|
|
230
|
+
const dky = new Float64Array(this.neq);
|
|
231
|
+
const flag = cvodeGetDky(this.mem, t, k, dky);
|
|
232
|
+
if (flag !== 0)
|
|
233
|
+
throw new Error(`[Cvode] getDky failed: t=${t} out of range or k=${k} invalid`);
|
|
234
|
+
|
|
235
|
+
return dky;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Return current integrator statistics.
|
|
240
|
+
*/
|
|
241
|
+
getStats(): CvodeStats {
|
|
242
|
+
return cvodeGetIntegratorStats(this.mem);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Re-initialize the solver for a new initial-value problem with the same
|
|
247
|
+
* ODE function and options. Resets internal state and counters.
|
|
248
|
+
*
|
|
249
|
+
* @param t0 - new initial time
|
|
250
|
+
* @param y0 - new initial conditions (length neq)
|
|
251
|
+
*/
|
|
252
|
+
reInit(t0: number, y0: Float64Array): void {
|
|
253
|
+
cvodeInit(this.mem, this.wrappedF, t0, y0);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ==========================================================================
|
|
257
|
+
// Private helpers
|
|
258
|
+
// ==========================================================================
|
|
259
|
+
|
|
260
|
+
private _buildResult(t: number, flag: number): CvodeSolveResult {
|
|
261
|
+
const y = new Float64Array(this.yout); // copy
|
|
262
|
+
const result: CvodeSolveResult = {t, y, flag};
|
|
263
|
+
|
|
264
|
+
if (flag === CV_ROOT_RETURN) {
|
|
265
|
+
// Return a copy of the root direction info array
|
|
266
|
+
result.rootsFound = new Int32Array(this.mem.cv_iroots);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return result;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript port of SUNDIALS CVODE v7.5.0 (https://github.com/LLNL/sundials)
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) 2025, Lawrence Livermore National Security, University of
|
|
5
|
+
* Maryland Baltimore County, and the SUNDIALS contributors.
|
|
6
|
+
* Copyright (c) 2013-2025, Lawrence Livermore National Security and
|
|
7
|
+
* Southern Methodist University.
|
|
8
|
+
* Copyright (c) 2002-2013, Lawrence Livermore National Security.
|
|
9
|
+
* Copyright (c) 2026 Datagrok.
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the BSD-3-Clause License. See THIRD_PARTY_LICENSES
|
|
12
|
+
* for the full license text and provenance chain of the original code.
|
|
13
|
+
*/
|
|
14
|
+
// CVODE TypeScript port - Initial step size estimation
|
|
15
|
+
// Ported from SUNDIALS CVODE cvode.c (cvHin, cvUpperBoundH0, cvYddNorm)
|
|
16
|
+
import { wrmsNorm, vLinearSum, vScale, CV_SUCCESS, CV_RHSFUNC_FAIL, RHSFUNC_RECVR, CV_TOO_CLOSE, HLB_FACTOR, HUB_FACTOR, H_BIAS, MAX_ITERS } from './common';
|
|
17
|
+
/**
|
|
18
|
+
* cvHin - Compute initial step size h0.
|
|
19
|
+
*
|
|
20
|
+
* The algorithm:
|
|
21
|
+
* 1. Compute a bound hub on |h| from ydot and tdist
|
|
22
|
+
* 2. Set hlb = HLB_FACTOR * tround (lower bound)
|
|
23
|
+
* 3. Iterate to estimate ||y''|| and compute h candidates
|
|
24
|
+
* 4. h0 = H_BIAS * geometric mean of hlb and hub candidates
|
|
25
|
+
*/
|
|
26
|
+
export function cvHin(mem, tout) {
|
|
27
|
+
const N = mem.cv_N;
|
|
28
|
+
const sign = (tout - mem.cv_tn >= 0.0) ? 1.0 : -1.0;
|
|
29
|
+
const tdist = Math.abs(tout - mem.cv_tn);
|
|
30
|
+
const tround = Math.max(Math.abs(mem.cv_tn), Math.abs(tout)) * 2.2204460492503131e-16;
|
|
31
|
+
if (tdist < 2.0 * tround)
|
|
32
|
+
return CV_TOO_CLOSE;
|
|
33
|
+
// Set lower and upper bounds on h0, initial guess
|
|
34
|
+
const hlb = HLB_FACTOR * tround;
|
|
35
|
+
const hub = cvUpperBoundH0(mem, tdist);
|
|
36
|
+
// Initial guess - geometric mean
|
|
37
|
+
let hg = Math.sqrt(hlb * hub);
|
|
38
|
+
if (hub < 100.0 * hlb)
|
|
39
|
+
hg = 0.5 * hub;
|
|
40
|
+
// Iterate to estimate ydd norm
|
|
41
|
+
let hnew = hg;
|
|
42
|
+
let retval;
|
|
43
|
+
for (let count = 0; count < MAX_ITERS; count++) {
|
|
44
|
+
hg = hnew;
|
|
45
|
+
// Compute y''norm via finite difference
|
|
46
|
+
const result = cvYddNorm(mem, hg * sign);
|
|
47
|
+
retval = result.retval;
|
|
48
|
+
if (retval !== CV_SUCCESS)
|
|
49
|
+
return retval;
|
|
50
|
+
const yddnrm = result.yddnrm;
|
|
51
|
+
// If yddnrm is zero, use current hg
|
|
52
|
+
if (yddnrm * hub * hub > 2.0)
|
|
53
|
+
hnew = Math.sqrt(2.0 / yddnrm);
|
|
54
|
+
else
|
|
55
|
+
hnew = Math.sqrt(hg * hub);
|
|
56
|
+
// Refine: make hnew be a geometric mean biased toward smaller
|
|
57
|
+
hnew = H_BIAS * hnew + (1.0 - H_BIAS) * hg;
|
|
58
|
+
// Check convergence
|
|
59
|
+
if (hnew / hg > 2.0 || hnew / hg < 0.5)
|
|
60
|
+
continue;
|
|
61
|
+
// If converged, break
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
// Bound hnew
|
|
65
|
+
hnew = Math.min(hnew, hub);
|
|
66
|
+
hnew = Math.max(hnew, hlb);
|
|
67
|
+
// Apply bounds on step size
|
|
68
|
+
if (mem.cv_hmax_inv > 0.0)
|
|
69
|
+
hnew = Math.min(hnew, 1.0 / mem.cv_hmax_inv);
|
|
70
|
+
if (mem.cv_hmin > 0.0)
|
|
71
|
+
hnew = Math.max(hnew, mem.cv_hmin);
|
|
72
|
+
// Bound by tdist
|
|
73
|
+
hnew = Math.min(hnew, tdist);
|
|
74
|
+
mem.cv_h = sign * hnew;
|
|
75
|
+
mem.cv_next_h = mem.cv_h;
|
|
76
|
+
mem.cv_hscale = mem.cv_h;
|
|
77
|
+
// Scale zn[1] = h * y'(t0)
|
|
78
|
+
vScale(mem.cv_h, mem.cv_zn[1], mem.cv_zn[1], N);
|
|
79
|
+
return CV_SUCCESS;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* cvUpperBoundH0 - Compute upper bound on initial step size
|
|
83
|
+
* Based on ||y'|| weighted norm
|
|
84
|
+
*/
|
|
85
|
+
function cvUpperBoundH0(mem, tdist) {
|
|
86
|
+
const N = mem.cv_N;
|
|
87
|
+
// Get WRMS norm of y' (zn[1] = f(t0, y0) before scaling)
|
|
88
|
+
const hub_inv = wrmsNorm(N, mem.cv_zn[1], mem.cv_ewt);
|
|
89
|
+
// Bound based on tdist
|
|
90
|
+
let hub = HUB_FACTOR * tdist;
|
|
91
|
+
// Use smaller of two bounds
|
|
92
|
+
if (hub * hub_inv > 1.0)
|
|
93
|
+
hub = 1.0 / hub_inv;
|
|
94
|
+
return hub;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* cvYddNorm - Estimate ||y''|| via finite difference
|
|
98
|
+
* y(t0 + hg) ~ y0 + hg*y'0
|
|
99
|
+
* y'(t0 + hg) = f(t0 + hg, y(t0 + hg))
|
|
100
|
+
* y'' ~ (y'(t0+hg) - y'(t0)) / hg
|
|
101
|
+
*/
|
|
102
|
+
function cvYddNorm(mem, hg) {
|
|
103
|
+
const N = mem.cv_N;
|
|
104
|
+
// y = zn[0] + hg * zn[1] (zn[1] still holds unscaled f at this point)
|
|
105
|
+
vLinearSum(hg, mem.cv_zn[1], 1.0, mem.cv_zn[0], mem.cv_y, N);
|
|
106
|
+
// Evaluate f(t0 + hg, y)
|
|
107
|
+
const retval = mem.cv_f(mem.cv_tn + hg, mem.cv_y, mem.cv_tempv, mem.cv_user_data);
|
|
108
|
+
mem.cv_nfe++;
|
|
109
|
+
if (retval < 0)
|
|
110
|
+
return { retval: CV_RHSFUNC_FAIL, yddnrm: 0 };
|
|
111
|
+
if (retval > 0)
|
|
112
|
+
return { retval: RHSFUNC_RECVR, yddnrm: 0 };
|
|
113
|
+
// tempv = (f(t0+hg, y) - zn[1]) / hg (estimate of y'')
|
|
114
|
+
const hg_inv = 1.0 / hg;
|
|
115
|
+
vLinearSum(hg_inv, mem.cv_tempv, -hg_inv, mem.cv_zn[1], mem.cv_tempv, N);
|
|
116
|
+
const yddnrm = wrmsNorm(N, mem.cv_tempv, mem.cv_ewt);
|
|
117
|
+
return { retval: CV_SUCCESS, yddnrm };
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=cvode_hin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cvode_hin.js","sourceRoot":"","sources":["cvode_hin.ts"],"names":[],"mappings":"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"}
|