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,236 @@
|
|
|
1
|
+
/* The Runge-Kutta-Fehlberg 4(5) method (RK4).
|
|
2
|
+
|
|
3
|
+
An explicit adaptive Runge-Kutta method of order 4 with an embedded
|
|
4
|
+
5th-order error estimate for step size control.
|
|
5
|
+
|
|
6
|
+
Reference:
|
|
7
|
+
[1] E. Fehlberg, "Low-order classical Runge-Kutta formulas with stepsize control
|
|
8
|
+
and their application to some heat transfer problems", NASA Technical Report 315, 1969.
|
|
9
|
+
*/
|
|
10
|
+
import { max, abs, SAFETY, PSHRNK, PSGROW, REDUCE_COEF, GROW_COEF, ERR_CONTR, TINY, ERROR_MSG } from './solver-defs';
|
|
11
|
+
// Fehlberg 4(5) Butcher tableau coefficients
|
|
12
|
+
// Nodes (c_i)
|
|
13
|
+
const C2 = 1.0 / 4.0;
|
|
14
|
+
const C3 = 3.0 / 8.0;
|
|
15
|
+
const C4 = 12.0 / 13.0;
|
|
16
|
+
// C5 = 1
|
|
17
|
+
const C6 = 1.0 / 2.0;
|
|
18
|
+
// Matrix coefficients (a_ij)
|
|
19
|
+
const A21 = 1.0 / 4.0;
|
|
20
|
+
const A31 = 3.0 / 32.0;
|
|
21
|
+
const A32 = 9.0 / 32.0;
|
|
22
|
+
const A41 = 1932.0 / 2197.0;
|
|
23
|
+
const A42 = -7200.0 / 2197.0;
|
|
24
|
+
const A43 = 7296.0 / 2197.0;
|
|
25
|
+
const A51 = 439.0 / 216.0;
|
|
26
|
+
const A52 = -8.0;
|
|
27
|
+
const A53 = 3680.0 / 513.0;
|
|
28
|
+
const A54 = -845.0 / 4104.0;
|
|
29
|
+
const A61 = -8.0 / 27.0;
|
|
30
|
+
const A62 = 2.0;
|
|
31
|
+
const A63 = -3544.0 / 2565.0;
|
|
32
|
+
const A64 = 1859.0 / 4104.0;
|
|
33
|
+
const A65 = -11.0 / 40.0;
|
|
34
|
+
// 4th-order weights (b_i)
|
|
35
|
+
const B1 = 25.0 / 216.0;
|
|
36
|
+
// B2 = 0
|
|
37
|
+
const B3 = 1408.0 / 2565.0;
|
|
38
|
+
const B4 = 2197.0 / 4104.0;
|
|
39
|
+
const B5 = -1.0 / 5.0;
|
|
40
|
+
// B6 = 0
|
|
41
|
+
// Error coefficients: (b_i - bHat_i), where bHat are the 5th-order weights
|
|
42
|
+
const E1 = 1.0 / 360.0;
|
|
43
|
+
// E2 = 0
|
|
44
|
+
const E3 = -128.0 / 4275.0;
|
|
45
|
+
const E4 = -2197.0 / 75240.0;
|
|
46
|
+
const E5 = 1.0 / 50.0;
|
|
47
|
+
const E6 = 2.0 / 55.0;
|
|
48
|
+
/** Solve initial value problem using the Runge-Kutta-Fehlberg 4(5) method
|
|
49
|
+
* @param odes initial value problem for ordinary differential equations
|
|
50
|
+
* @param callback computations control callback
|
|
51
|
+
* @returns solution of the problem
|
|
52
|
+
* @example
|
|
53
|
+
* // Example. Solve the following initial value problem using the RK4 method:
|
|
54
|
+
* // dx/dt = x + y - t
|
|
55
|
+
* // dy/dt = x * y + t
|
|
56
|
+
* // x(0) = 1
|
|
57
|
+
* // y(0) = -1
|
|
58
|
+
* // on [0, 2] with the step 0.01.
|
|
59
|
+
* import { ODEs, rk4 } from 'diff-grok';
|
|
60
|
+
*
|
|
61
|
+
* const task: ODEs = {
|
|
62
|
+
* name: 'Example', // name of your model
|
|
63
|
+
* arg: {
|
|
64
|
+
* name: 't', // name of the argument
|
|
65
|
+
* start: 0, // initial value of the argument
|
|
66
|
+
* finish: 2, // final value of the argument
|
|
67
|
+
* step: 0.01, // solution grid step
|
|
68
|
+
* },
|
|
69
|
+
* initial: [1, -1], // initial values
|
|
70
|
+
* func: (t: number, y: Float64Array, output: Float64Array) => { // right-hand side of the system
|
|
71
|
+
* output[0] = y[0] + y[1] - t; // 1-st equation
|
|
72
|
+
* output[1] = y[0] * y[1] + t; // 2-nd equation
|
|
73
|
+
* },
|
|
74
|
+
* tolerance: 1e-7, // tolerance
|
|
75
|
+
* solutionColNames: ['x', 'y'], // names of solution functions
|
|
76
|
+
* };
|
|
77
|
+
*
|
|
78
|
+
* try {
|
|
79
|
+
* // Solve the problem using the RK4 method
|
|
80
|
+
* const solution = rk4(task);
|
|
81
|
+
*
|
|
82
|
+
* // Print a table with the results
|
|
83
|
+
* console.log(task.arg.name, task.solutionColNames[0], task.solutionColNames[1]);
|
|
84
|
+
* const length = solution[0].length;
|
|
85
|
+
* for (let i = 0; i < length; ++i)
|
|
86
|
+
* console.log(solution[0][i], solution[1][i], solution[2][i]);
|
|
87
|
+
* } catch (err) {
|
|
88
|
+
* console.log('Solver failed: ', err instanceof Error ? err.message : 'Unknown problem!');
|
|
89
|
+
* }
|
|
90
|
+
*/
|
|
91
|
+
export function rk4(odes, callback) {
|
|
92
|
+
const f = odes.func;
|
|
93
|
+
// operating variables
|
|
94
|
+
const t0 = odes.arg.start;
|
|
95
|
+
const t1 = odes.arg.finish;
|
|
96
|
+
let h = odes.arg.step;
|
|
97
|
+
const hDataframe = h;
|
|
98
|
+
const hMax = hDataframe * 10;
|
|
99
|
+
const tolerance = odes.tolerance;
|
|
100
|
+
const rowCount = Math.trunc((t1 - t0) / h) + 1;
|
|
101
|
+
const dim = odes.initial.length;
|
|
102
|
+
// result arrays
|
|
103
|
+
const tArr = new Float64Array(rowCount);
|
|
104
|
+
const yArrs = Array(dim);
|
|
105
|
+
for (let i = 0; i < dim; ++i)
|
|
106
|
+
yArrs[i] = new Float64Array(rowCount);
|
|
107
|
+
// method routine
|
|
108
|
+
let timeDataframe = t0 + hDataframe;
|
|
109
|
+
let t = t0;
|
|
110
|
+
let tPrev = t0;
|
|
111
|
+
let hNext = 0.0;
|
|
112
|
+
let flag = true;
|
|
113
|
+
let index = 1;
|
|
114
|
+
let errmax = 0;
|
|
115
|
+
let hTemp = 0;
|
|
116
|
+
let tNew = 0;
|
|
117
|
+
// buffers
|
|
118
|
+
const y = new Float64Array(odes.initial);
|
|
119
|
+
const yPrev = new Float64Array(odes.initial);
|
|
120
|
+
const dydt = new Float64Array(dim);
|
|
121
|
+
const yScale = new Float64Array(dim);
|
|
122
|
+
const yTemp = new Float64Array(dim);
|
|
123
|
+
const yErr = new Float64Array(dim);
|
|
124
|
+
const k1 = new Float64Array(dim);
|
|
125
|
+
const k2 = new Float64Array(dim);
|
|
126
|
+
const k3 = new Float64Array(dim);
|
|
127
|
+
const k4 = new Float64Array(dim);
|
|
128
|
+
const k5 = new Float64Array(dim);
|
|
129
|
+
const k6 = new Float64Array(dim);
|
|
130
|
+
// 1. SOLUTION AT THE POINT t0
|
|
131
|
+
tArr[0] = t0;
|
|
132
|
+
for (let i = 0; i < dim; ++i)
|
|
133
|
+
yArrs[i][0] = y[i];
|
|
134
|
+
// 2. COMPUTE NUMERICAL SOLUTION FOR THE POINTS FROM THE INTERVAL (t0, t1)
|
|
135
|
+
while (flag) {
|
|
136
|
+
// compute derivative
|
|
137
|
+
f(t, y, dydt);
|
|
138
|
+
// check whether to go on computations
|
|
139
|
+
if (callback)
|
|
140
|
+
callback.onIterationStart();
|
|
141
|
+
// compute scale vector
|
|
142
|
+
for (let i = 0; i < dim; ++i)
|
|
143
|
+
yScale[i] = abs(y[i]) + h * abs(dydt[i]) + TINY;
|
|
144
|
+
// check end point
|
|
145
|
+
if (t + h > t1) {
|
|
146
|
+
h = t1 - t;
|
|
147
|
+
flag = false;
|
|
148
|
+
}
|
|
149
|
+
// adaptive step loop
|
|
150
|
+
while (true) {
|
|
151
|
+
// Stage 1: k1 = f(t, y)
|
|
152
|
+
f(t, y, k1);
|
|
153
|
+
// Stage 2: k2 = f(t + C2*h, y + h*A21*k1)
|
|
154
|
+
for (let i = 0; i < dim; ++i)
|
|
155
|
+
yTemp[i] = y[i] + h * A21 * k1[i];
|
|
156
|
+
f(t + C2 * h, yTemp, k2);
|
|
157
|
+
// Stage 3: k3 = f(t + C3*h, y + h*(A31*k1 + A32*k2))
|
|
158
|
+
for (let i = 0; i < dim; ++i)
|
|
159
|
+
yTemp[i] = y[i] + h * (A31 * k1[i] + A32 * k2[i]);
|
|
160
|
+
f(t + C3 * h, yTemp, k3);
|
|
161
|
+
// Stage 4: k4 = f(t + C4*h, y + h*(A41*k1 + A42*k2 + A43*k3))
|
|
162
|
+
for (let i = 0; i < dim; ++i)
|
|
163
|
+
yTemp[i] = y[i] + h * (A41 * k1[i] + A42 * k2[i] + A43 * k3[i]);
|
|
164
|
+
f(t + C4 * h, yTemp, k4);
|
|
165
|
+
// Stage 5: k5 = f(t + h, y + h*(A51*k1 + A52*k2 + A53*k3 + A54*k4))
|
|
166
|
+
for (let i = 0; i < dim; ++i)
|
|
167
|
+
yTemp[i] = y[i] + h * (A51 * k1[i] + A52 * k2[i] + A53 * k3[i] + A54 * k4[i]);
|
|
168
|
+
f(t + h, yTemp, k5);
|
|
169
|
+
// Stage 6: k6 = f(t + C6*h, y + h*(A61*k1 + A62*k2 + A63*k3 + A64*k4 + A65*k5))
|
|
170
|
+
for (let i = 0; i < dim; ++i)
|
|
171
|
+
yTemp[i] = y[i] + h * (A61 * k1[i] + A62 * k2[i] + A63 * k3[i] + A64 * k4[i] + A65 * k5[i]);
|
|
172
|
+
f(t + C6 * h, yTemp, k6);
|
|
173
|
+
// 4th-order solution
|
|
174
|
+
for (let i = 0; i < dim; ++i)
|
|
175
|
+
yTemp[i] = y[i] + h * (B1 * k1[i] + B3 * k3[i] + B4 * k4[i] + B5 * k5[i]);
|
|
176
|
+
// Error estimate: difference between 4th and 5th order solutions
|
|
177
|
+
for (let i = 0; i < dim; ++i)
|
|
178
|
+
yErr[i] = h * (E1 * k1[i] + E3 * k3[i] + E4 * k4[i] + E5 * k5[i] + E6 * k6[i]);
|
|
179
|
+
// estimating error
|
|
180
|
+
errmax = 0;
|
|
181
|
+
for (let i = 0; i < dim; ++i)
|
|
182
|
+
errmax = max(errmax, abs(yErr[i] / yScale[i]));
|
|
183
|
+
errmax /= tolerance;
|
|
184
|
+
// processing the error obtained
|
|
185
|
+
if (errmax > 1) {
|
|
186
|
+
hTemp = SAFETY * h * Math.pow(errmax, PSHRNK);
|
|
187
|
+
h = max(hTemp, REDUCE_COEF * h);
|
|
188
|
+
tNew = t + h;
|
|
189
|
+
if (tNew == t)
|
|
190
|
+
throw new Error(ERROR_MSG.RK4_FAILS);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
if (errmax > ERR_CONTR)
|
|
194
|
+
hNext = SAFETY * h * Math.pow(errmax, PSGROW);
|
|
195
|
+
else
|
|
196
|
+
hNext = GROW_COEF * h;
|
|
197
|
+
if (hNext > hMax)
|
|
198
|
+
hNext = hMax;
|
|
199
|
+
t = t + h;
|
|
200
|
+
for (let i = 0; i < dim; ++i)
|
|
201
|
+
y[i] = yTemp[i];
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
} // while (true)
|
|
205
|
+
// compute linearly interpolated results and store them in dataframe
|
|
206
|
+
while (timeDataframe < t) {
|
|
207
|
+
const cLeft = (t - timeDataframe) / (t - tPrev);
|
|
208
|
+
const cRight = 1.0 - cLeft;
|
|
209
|
+
tArr[index] = timeDataframe;
|
|
210
|
+
for (let j = 0; j < dim; ++j)
|
|
211
|
+
yArrs[j][index] = cRight * y[j] + cLeft * yPrev[j];
|
|
212
|
+
timeDataframe += hDataframe;
|
|
213
|
+
++index;
|
|
214
|
+
}
|
|
215
|
+
h = hNext;
|
|
216
|
+
tPrev = t;
|
|
217
|
+
for (let i = 0; i < dim; ++i)
|
|
218
|
+
yPrev[i] = y[i];
|
|
219
|
+
} // while (flag)
|
|
220
|
+
// perform final callback actions
|
|
221
|
+
if (callback)
|
|
222
|
+
callback.onComputationsCompleted();
|
|
223
|
+
// 3. solution at the point t1
|
|
224
|
+
tArr[rowCount - 1] = t1;
|
|
225
|
+
for (let i = 0; i < dim; ++i)
|
|
226
|
+
yArrs[i][rowCount - 1] = y[i];
|
|
227
|
+
// 4. prepare output
|
|
228
|
+
const solution = Array(dim + 1);
|
|
229
|
+
// independent variable
|
|
230
|
+
solution[0] = tArr;
|
|
231
|
+
// functions
|
|
232
|
+
for (let i = 0; i < dim; ++i)
|
|
233
|
+
solution[i + 1] = yArrs[i];
|
|
234
|
+
return solution;
|
|
235
|
+
} // rk4
|
|
236
|
+
//# sourceMappingURL=rk4-method.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rk4-method.js","sourceRoot":"","sources":["rk4-method.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/* The Runge-Kutta-Fehlberg 4(5) method (RK4).
|
|
2
|
+
|
|
3
|
+
An explicit adaptive Runge-Kutta method of order 4 with an embedded
|
|
4
|
+
5th-order error estimate for step size control.
|
|
5
|
+
|
|
6
|
+
Reference:
|
|
7
|
+
[1] E. Fehlberg, "Low-order classical Runge-Kutta formulas with stepsize control
|
|
8
|
+
and their application to some heat transfer problems", NASA Technical Report 315, 1969.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {ODEs, max, abs, SAFETY, PSHRNK, PSGROW, REDUCE_COEF, GROW_COEF,
|
|
12
|
+
ERR_CONTR, TINY, ERROR_MSG} from './solver-defs';
|
|
13
|
+
import {Callback} from './callbacks/callback-base';
|
|
14
|
+
|
|
15
|
+
// Fehlberg 4(5) Butcher tableau coefficients
|
|
16
|
+
|
|
17
|
+
// Nodes (c_i)
|
|
18
|
+
const C2 = 1.0 / 4.0;
|
|
19
|
+
const C3 = 3.0 / 8.0;
|
|
20
|
+
const C4 = 12.0 / 13.0;
|
|
21
|
+
// C5 = 1
|
|
22
|
+
const C6 = 1.0 / 2.0;
|
|
23
|
+
|
|
24
|
+
// Matrix coefficients (a_ij)
|
|
25
|
+
const A21 = 1.0 / 4.0;
|
|
26
|
+
|
|
27
|
+
const A31 = 3.0 / 32.0;
|
|
28
|
+
const A32 = 9.0 / 32.0;
|
|
29
|
+
|
|
30
|
+
const A41 = 1932.0 / 2197.0;
|
|
31
|
+
const A42 = -7200.0 / 2197.0;
|
|
32
|
+
const A43 = 7296.0 / 2197.0;
|
|
33
|
+
|
|
34
|
+
const A51 = 439.0 / 216.0;
|
|
35
|
+
const A52 = -8.0;
|
|
36
|
+
const A53 = 3680.0 / 513.0;
|
|
37
|
+
const A54 = -845.0 / 4104.0;
|
|
38
|
+
|
|
39
|
+
const A61 = -8.0 / 27.0;
|
|
40
|
+
const A62 = 2.0;
|
|
41
|
+
const A63 = -3544.0 / 2565.0;
|
|
42
|
+
const A64 = 1859.0 / 4104.0;
|
|
43
|
+
const A65 = -11.0 / 40.0;
|
|
44
|
+
|
|
45
|
+
// 4th-order weights (b_i)
|
|
46
|
+
const B1 = 25.0 / 216.0;
|
|
47
|
+
// B2 = 0
|
|
48
|
+
const B3 = 1408.0 / 2565.0;
|
|
49
|
+
const B4 = 2197.0 / 4104.0;
|
|
50
|
+
const B5 = -1.0 / 5.0;
|
|
51
|
+
// B6 = 0
|
|
52
|
+
|
|
53
|
+
// Error coefficients: (b_i - bHat_i), where bHat are the 5th-order weights
|
|
54
|
+
const E1 = 1.0 / 360.0;
|
|
55
|
+
// E2 = 0
|
|
56
|
+
const E3 = -128.0 / 4275.0;
|
|
57
|
+
const E4 = -2197.0 / 75240.0;
|
|
58
|
+
const E5 = 1.0 / 50.0;
|
|
59
|
+
const E6 = 2.0 / 55.0;
|
|
60
|
+
|
|
61
|
+
/** Solve initial value problem using the Runge-Kutta-Fehlberg 4(5) method
|
|
62
|
+
* @param odes initial value problem for ordinary differential equations
|
|
63
|
+
* @param callback computations control callback
|
|
64
|
+
* @returns solution of the problem
|
|
65
|
+
* @example
|
|
66
|
+
* // Example. Solve the following initial value problem using the RK4 method:
|
|
67
|
+
* // dx/dt = x + y - t
|
|
68
|
+
* // dy/dt = x * y + t
|
|
69
|
+
* // x(0) = 1
|
|
70
|
+
* // y(0) = -1
|
|
71
|
+
* // on [0, 2] with the step 0.01.
|
|
72
|
+
* import { ODEs, rk4 } from 'diff-grok';
|
|
73
|
+
*
|
|
74
|
+
* const task: ODEs = {
|
|
75
|
+
* name: 'Example', // name of your model
|
|
76
|
+
* arg: {
|
|
77
|
+
* name: 't', // name of the argument
|
|
78
|
+
* start: 0, // initial value of the argument
|
|
79
|
+
* finish: 2, // final value of the argument
|
|
80
|
+
* step: 0.01, // solution grid step
|
|
81
|
+
* },
|
|
82
|
+
* initial: [1, -1], // initial values
|
|
83
|
+
* func: (t: number, y: Float64Array, output: Float64Array) => { // right-hand side of the system
|
|
84
|
+
* output[0] = y[0] + y[1] - t; // 1-st equation
|
|
85
|
+
* output[1] = y[0] * y[1] + t; // 2-nd equation
|
|
86
|
+
* },
|
|
87
|
+
* tolerance: 1e-7, // tolerance
|
|
88
|
+
* solutionColNames: ['x', 'y'], // names of solution functions
|
|
89
|
+
* };
|
|
90
|
+
*
|
|
91
|
+
* try {
|
|
92
|
+
* // Solve the problem using the RK4 method
|
|
93
|
+
* const solution = rk4(task);
|
|
94
|
+
*
|
|
95
|
+
* // Print a table with the results
|
|
96
|
+
* console.log(task.arg.name, task.solutionColNames[0], task.solutionColNames[1]);
|
|
97
|
+
* const length = solution[0].length;
|
|
98
|
+
* for (let i = 0; i < length; ++i)
|
|
99
|
+
* console.log(solution[0][i], solution[1][i], solution[2][i]);
|
|
100
|
+
* } catch (err) {
|
|
101
|
+
* console.log('Solver failed: ', err instanceof Error ? err.message : 'Unknown problem!');
|
|
102
|
+
* }
|
|
103
|
+
*/
|
|
104
|
+
export function rk4(odes: ODEs, callback?: Callback): Float64Array[] {
|
|
105
|
+
const f = odes.func;
|
|
106
|
+
|
|
107
|
+
// operating variables
|
|
108
|
+
const t0 = odes.arg.start;
|
|
109
|
+
const t1 = odes.arg.finish;
|
|
110
|
+
let h = odes.arg.step;
|
|
111
|
+
const hDataframe = h;
|
|
112
|
+
const hMax = hDataframe * 10;
|
|
113
|
+
const tolerance = odes.tolerance;
|
|
114
|
+
|
|
115
|
+
const rowCount = Math.trunc((t1 - t0) / h) + 1;
|
|
116
|
+
const dim = odes.initial.length;
|
|
117
|
+
|
|
118
|
+
// result arrays
|
|
119
|
+
const tArr = new Float64Array(rowCount);
|
|
120
|
+
const yArrs = Array<Float64Array>(dim);
|
|
121
|
+
|
|
122
|
+
for (let i = 0; i < dim; ++i)
|
|
123
|
+
yArrs[i] = new Float64Array(rowCount);
|
|
124
|
+
|
|
125
|
+
// method routine
|
|
126
|
+
let timeDataframe = t0 + hDataframe;
|
|
127
|
+
let t = t0;
|
|
128
|
+
let tPrev = t0;
|
|
129
|
+
let hNext = 0.0;
|
|
130
|
+
let flag = true;
|
|
131
|
+
let index = 1;
|
|
132
|
+
let errmax = 0;
|
|
133
|
+
let hTemp = 0;
|
|
134
|
+
let tNew = 0;
|
|
135
|
+
|
|
136
|
+
// buffers
|
|
137
|
+
const y = new Float64Array(odes.initial);
|
|
138
|
+
const yPrev = new Float64Array(odes.initial);
|
|
139
|
+
const dydt = new Float64Array(dim);
|
|
140
|
+
const yScale = new Float64Array(dim);
|
|
141
|
+
const yTemp = new Float64Array(dim);
|
|
142
|
+
const yErr = new Float64Array(dim);
|
|
143
|
+
|
|
144
|
+
const k1 = new Float64Array(dim);
|
|
145
|
+
const k2 = new Float64Array(dim);
|
|
146
|
+
const k3 = new Float64Array(dim);
|
|
147
|
+
const k4 = new Float64Array(dim);
|
|
148
|
+
const k5 = new Float64Array(dim);
|
|
149
|
+
const k6 = new Float64Array(dim);
|
|
150
|
+
|
|
151
|
+
// 1. SOLUTION AT THE POINT t0
|
|
152
|
+
tArr[0] = t0;
|
|
153
|
+
for (let i = 0; i < dim; ++i)
|
|
154
|
+
yArrs[i][0] = y[i];
|
|
155
|
+
|
|
156
|
+
// 2. COMPUTE NUMERICAL SOLUTION FOR THE POINTS FROM THE INTERVAL (t0, t1)
|
|
157
|
+
while (flag) {
|
|
158
|
+
// compute derivative
|
|
159
|
+
f(t, y, dydt);
|
|
160
|
+
|
|
161
|
+
// check whether to go on computations
|
|
162
|
+
if (callback)
|
|
163
|
+
callback.onIterationStart();
|
|
164
|
+
|
|
165
|
+
// compute scale vector
|
|
166
|
+
for (let i = 0; i < dim; ++i)
|
|
167
|
+
yScale[i] = abs(y[i]) + h * abs(dydt[i]) + TINY;
|
|
168
|
+
|
|
169
|
+
// check end point
|
|
170
|
+
if (t + h > t1) {
|
|
171
|
+
h = t1 - t;
|
|
172
|
+
flag = false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// adaptive step loop
|
|
176
|
+
while (true) {
|
|
177
|
+
// Stage 1: k1 = f(t, y)
|
|
178
|
+
f(t, y, k1);
|
|
179
|
+
|
|
180
|
+
// Stage 2: k2 = f(t + C2*h, y + h*A21*k1)
|
|
181
|
+
for (let i = 0; i < dim; ++i)
|
|
182
|
+
yTemp[i] = y[i] + h * A21 * k1[i];
|
|
183
|
+
f(t + C2 * h, yTemp, k2);
|
|
184
|
+
|
|
185
|
+
// Stage 3: k3 = f(t + C3*h, y + h*(A31*k1 + A32*k2))
|
|
186
|
+
for (let i = 0; i < dim; ++i)
|
|
187
|
+
yTemp[i] = y[i] + h * (A31 * k1[i] + A32 * k2[i]);
|
|
188
|
+
f(t + C3 * h, yTemp, k3);
|
|
189
|
+
|
|
190
|
+
// Stage 4: k4 = f(t + C4*h, y + h*(A41*k1 + A42*k2 + A43*k3))
|
|
191
|
+
for (let i = 0; i < dim; ++i)
|
|
192
|
+
yTemp[i] = y[i] + h * (A41 * k1[i] + A42 * k2[i] + A43 * k3[i]);
|
|
193
|
+
f(t + C4 * h, yTemp, k4);
|
|
194
|
+
|
|
195
|
+
// Stage 5: k5 = f(t + h, y + h*(A51*k1 + A52*k2 + A53*k3 + A54*k4))
|
|
196
|
+
for (let i = 0; i < dim; ++i)
|
|
197
|
+
yTemp[i] = y[i] + h * (A51 * k1[i] + A52 * k2[i] + A53 * k3[i] + A54 * k4[i]);
|
|
198
|
+
f(t + h, yTemp, k5);
|
|
199
|
+
|
|
200
|
+
// Stage 6: k6 = f(t + C6*h, y + h*(A61*k1 + A62*k2 + A63*k3 + A64*k4 + A65*k5))
|
|
201
|
+
for (let i = 0; i < dim; ++i)
|
|
202
|
+
yTemp[i] = y[i] + h * (A61 * k1[i] + A62 * k2[i] + A63 * k3[i] + A64 * k4[i] + A65 * k5[i]);
|
|
203
|
+
f(t + C6 * h, yTemp, k6);
|
|
204
|
+
|
|
205
|
+
// 4th-order solution
|
|
206
|
+
for (let i = 0; i < dim; ++i)
|
|
207
|
+
yTemp[i] = y[i] + h * (B1 * k1[i] + B3 * k3[i] + B4 * k4[i] + B5 * k5[i]);
|
|
208
|
+
|
|
209
|
+
// Error estimate: difference between 4th and 5th order solutions
|
|
210
|
+
for (let i = 0; i < dim; ++i)
|
|
211
|
+
yErr[i] = h * (E1 * k1[i] + E3 * k3[i] + E4 * k4[i] + E5 * k5[i] + E6 * k6[i]);
|
|
212
|
+
|
|
213
|
+
// estimating error
|
|
214
|
+
errmax = 0;
|
|
215
|
+
for (let i = 0; i < dim; ++i)
|
|
216
|
+
errmax = max(errmax, abs(yErr[i] / yScale[i]));
|
|
217
|
+
errmax /= tolerance;
|
|
218
|
+
|
|
219
|
+
// processing the error obtained
|
|
220
|
+
if (errmax > 1) {
|
|
221
|
+
hTemp = SAFETY * h * errmax**PSHRNK;
|
|
222
|
+
h = max(hTemp, REDUCE_COEF * h);
|
|
223
|
+
tNew = t + h;
|
|
224
|
+
if (tNew == t)
|
|
225
|
+
throw new Error(ERROR_MSG.RK4_FAILS);
|
|
226
|
+
} else {
|
|
227
|
+
if (errmax > ERR_CONTR)
|
|
228
|
+
hNext = SAFETY * h * errmax**PSGROW;
|
|
229
|
+
else
|
|
230
|
+
hNext = GROW_COEF * h;
|
|
231
|
+
|
|
232
|
+
if (hNext > hMax)
|
|
233
|
+
hNext = hMax;
|
|
234
|
+
|
|
235
|
+
t = t + h;
|
|
236
|
+
|
|
237
|
+
for (let i = 0; i < dim; ++i)
|
|
238
|
+
y[i] = yTemp[i];
|
|
239
|
+
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
} // while (true)
|
|
243
|
+
|
|
244
|
+
// compute linearly interpolated results and store them in dataframe
|
|
245
|
+
while (timeDataframe < t) {
|
|
246
|
+
const cLeft = (t - timeDataframe) / (t - tPrev);
|
|
247
|
+
const cRight = 1.0 - cLeft;
|
|
248
|
+
|
|
249
|
+
tArr[index] = timeDataframe;
|
|
250
|
+
|
|
251
|
+
for (let j = 0; j < dim; ++j)
|
|
252
|
+
yArrs[j][index] = cRight * y[j] + cLeft * yPrev[j];
|
|
253
|
+
|
|
254
|
+
timeDataframe += hDataframe;
|
|
255
|
+
++index;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
h = hNext;
|
|
259
|
+
tPrev = t;
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < dim; ++i)
|
|
262
|
+
yPrev[i] = y[i];
|
|
263
|
+
} // while (flag)
|
|
264
|
+
|
|
265
|
+
// perform final callback actions
|
|
266
|
+
if (callback)
|
|
267
|
+
callback.onComputationsCompleted();
|
|
268
|
+
|
|
269
|
+
// 3. solution at the point t1
|
|
270
|
+
tArr[rowCount - 1] = t1;
|
|
271
|
+
|
|
272
|
+
for (let i = 0; i < dim; ++i)
|
|
273
|
+
yArrs[i][rowCount - 1] = y[i];
|
|
274
|
+
|
|
275
|
+
// 4. prepare output
|
|
276
|
+
const solution = Array<Float64Array>(dim + 1);
|
|
277
|
+
|
|
278
|
+
// independent variable
|
|
279
|
+
solution[0] = tArr;
|
|
280
|
+
|
|
281
|
+
// functions
|
|
282
|
+
for (let i = 0; i < dim; ++i)
|
|
283
|
+
solution[i + 1] = yArrs[i];
|
|
284
|
+
|
|
285
|
+
return solution;
|
|
286
|
+
} // rk4
|