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.
Files changed (226) hide show
  1. package/.claude/settings.local.json +11 -0
  2. package/.claude/skills/license-updater/SKILL.md +149 -0
  3. package/.claude/skills/license-updater/references/compatibility.md +68 -0
  4. package/.claude/skills/license-updater/references/templates.md +151 -0
  5. package/.claude/skills/license-updater/scripts/generate_license_files.py +467 -0
  6. package/CLAUDE.md +104 -0
  7. package/LICENSE +1 -1
  8. package/README.MD +121 -27
  9. package/THIRD_PARTY_LICENSES +135 -0
  10. package/docs/assets/hierarchy.js +1 -1
  11. package/docs/assets/navigation.js +1 -1
  12. package/docs/assets/search.js +1 -1
  13. package/docs/classes/BasicModelPipelineCreator.html +4 -4
  14. package/docs/classes/Callback.html +5 -5
  15. package/docs/classes/CyclicModelPipelineCreator.html +4 -4
  16. package/docs/classes/IterCheckerCallback.html +5 -5
  17. package/docs/classes/PipelineCreator.html +4 -4
  18. package/docs/classes/TimeCheckerCallback.html +5 -5
  19. package/docs/classes/UpdatesModelPipelineCreator.html +4 -4
  20. package/docs/functions/ab4.html +8 -0
  21. package/docs/functions/ab5.html +8 -0
  22. package/docs/functions/applyPipeline.html +2 -2
  23. package/docs/functions/getCallback.html +2 -2
  24. package/docs/functions/getIVP.html +2 -2
  25. package/docs/functions/getInputVector.html +2 -2
  26. package/docs/functions/getIvp2WebWorker.html +2 -2
  27. package/docs/functions/getJScode.html +2 -2
  28. package/docs/functions/getOutputNames.html +2 -2
  29. package/docs/functions/getPipelineCreator.html +2 -2
  30. package/docs/functions/lsoda.html +8 -0
  31. package/docs/functions/mrt.html +2 -2
  32. package/docs/functions/printE5.html +2 -2
  33. package/docs/functions/printHires.html +2 -2
  34. package/docs/functions/printOrego.html +2 -2
  35. package/docs/functions/printPollution.html +2 -2
  36. package/docs/functions/printRobertson.html +2 -2
  37. package/docs/functions/printVdpol.html +2 -2
  38. package/docs/functions/rk3.html +8 -0
  39. package/docs/functions/rk4.html +8 -0
  40. package/docs/functions/rkdp.html +8 -0
  41. package/docs/functions/ros34prw.html +2 -2
  42. package/docs/functions/ros3prw.html +2 -2
  43. package/docs/functions/solveIvp.html +2 -2
  44. package/docs/hierarchy.html +1 -1
  45. package/docs/index.html +100 -15
  46. package/docs/media/E5.png +0 -0
  47. package/docs/media/HIRES.png +0 -0
  48. package/docs/media/OREGO.png +0 -0
  49. package/docs/media/POLL-full.png +0 -0
  50. package/docs/media/ROBER.png +0 -0
  51. package/docs/media/VDP0L.png +0 -0
  52. package/docs/media/cyclic-model.js +3 -1
  53. package/docs/media/cyclic-model.js.map +1 -1
  54. package/docs/media/cyclic-model.ts +3 -1
  55. package/docs/modules.html +1 -1
  56. package/docs/types/Arg.html +7 -7
  57. package/docs/types/DifEqs.html +4 -4
  58. package/docs/types/Func.html +2 -2
  59. package/docs/types/IVP.html +20 -20
  60. package/docs/types/IVP2WebWorker.html +7 -7
  61. package/docs/types/Input.html +4 -4
  62. package/docs/types/Loop.html +4 -4
  63. package/docs/types/ODEs.html +8 -8
  64. package/docs/types/Output.html +4 -4
  65. package/docs/types/Pipeline.html +4 -4
  66. package/docs/types/SolverOptions.html +5 -5
  67. package/docs/types/Update.html +5 -5
  68. package/docs/types/Wrapper.html +5 -5
  69. package/images/E5.png +0 -0
  70. package/images/HIRES.png +0 -0
  71. package/images/OREGO.png +0 -0
  72. package/images/POLL-full.png +0 -0
  73. package/images/ROBER.png +0 -0
  74. package/images/VDP0L.png +0 -0
  75. package/index.js +1 -1
  76. package/index.js.map +1 -1
  77. package/index.ts +2 -1
  78. package/jest.config.js +1 -0
  79. package/package.json +4 -2
  80. package/src/examples/check-methods.js +15 -3
  81. package/src/examples/check-methods.js.map +1 -1
  82. package/src/examples/check-methods.ts +18 -3
  83. package/src/examples/cyclic-model.js +3 -1
  84. package/src/examples/cyclic-model.js.map +1 -1
  85. package/src/examples/cyclic-model.ts +3 -1
  86. package/src/solver-tools/ab4-method.js +332 -0
  87. package/src/solver-tools/ab4-method.js.map +1 -0
  88. package/src/solver-tools/ab4-method.ts +395 -0
  89. package/src/solver-tools/ab5-method.js +334 -0
  90. package/src/solver-tools/ab5-method.js.map +1 -0
  91. package/src/solver-tools/ab5-method.ts +397 -0
  92. package/src/solver-tools/cvode/common.js +487 -0
  93. package/src/solver-tools/cvode/common.js.map +1 -0
  94. package/src/solver-tools/cvode/common.ts +549 -0
  95. package/src/solver-tools/cvode/cvode.js +1062 -0
  96. package/src/solver-tools/cvode/cvode.js.map +1 -0
  97. package/src/solver-tools/cvode/cvode.ts +1226 -0
  98. package/src/solver-tools/cvode/cvode_adams.js +124 -0
  99. package/src/solver-tools/cvode/cvode_adams.js.map +1 -0
  100. package/src/solver-tools/cvode/cvode_adams.ts +142 -0
  101. package/src/solver-tools/cvode/cvode_bdf.js +153 -0
  102. package/src/solver-tools/cvode/cvode_bdf.js.map +1 -0
  103. package/src/solver-tools/cvode/cvode_bdf.ts +164 -0
  104. package/src/solver-tools/cvode/cvode_class.js +158 -0
  105. package/src/solver-tools/cvode/cvode_class.js.map +1 -0
  106. package/src/solver-tools/cvode/cvode_class.ts +271 -0
  107. package/src/solver-tools/cvode/cvode_hin.js +119 -0
  108. package/src/solver-tools/cvode/cvode_hin.js.map +1 -0
  109. package/src/solver-tools/cvode/cvode_hin.ts +150 -0
  110. package/src/solver-tools/cvode/cvode_io.js +203 -0
  111. package/src/solver-tools/cvode/cvode_io.js.map +1 -0
  112. package/src/solver-tools/cvode/cvode_io.ts +258 -0
  113. package/src/solver-tools/cvode/cvode_ls.js +210 -0
  114. package/src/solver-tools/cvode/cvode_ls.js.map +1 -0
  115. package/src/solver-tools/cvode/cvode_ls.ts +249 -0
  116. package/src/solver-tools/cvode/cvode_nls.js +220 -0
  117. package/src/solver-tools/cvode/cvode_nls.js.map +1 -0
  118. package/src/solver-tools/cvode/cvode_nls.ts +259 -0
  119. package/src/solver-tools/cvode/cvode_root.js +415 -0
  120. package/src/solver-tools/cvode/cvode_root.js.map +1 -0
  121. package/src/solver-tools/cvode/cvode_root.ts +503 -0
  122. package/src/solver-tools/cvode/dense_linalg.js +131 -0
  123. package/src/solver-tools/cvode/dense_linalg.js.map +1 -0
  124. package/src/solver-tools/cvode/dense_linalg.ts +144 -0
  125. package/src/solver-tools/cvode/index.js +26 -0
  126. package/src/solver-tools/cvode/index.js.map +1 -0
  127. package/src/solver-tools/cvode/index.ts +64 -0
  128. package/src/solver-tools/cvode-method.js +114 -0
  129. package/src/solver-tools/cvode-method.js.map +1 -0
  130. package/src/solver-tools/cvode-method.ts +129 -0
  131. package/src/solver-tools/index.js +7 -0
  132. package/src/solver-tools/index.js.map +1 -1
  133. package/src/solver-tools/index.ts +7 -0
  134. package/src/solver-tools/lsoda/blas.js +257 -0
  135. package/src/solver-tools/lsoda/blas.js.map +1 -0
  136. package/src/solver-tools/lsoda/blas.ts +279 -0
  137. package/src/solver-tools/lsoda/cfode.js +84 -0
  138. package/src/solver-tools/lsoda/cfode.js.map +1 -0
  139. package/src/solver-tools/lsoda/cfode.ts +95 -0
  140. package/src/solver-tools/lsoda/common.js +94 -0
  141. package/src/solver-tools/lsoda/common.js.map +1 -0
  142. package/src/solver-tools/lsoda/common.ts +135 -0
  143. package/src/solver-tools/lsoda/corfailure.js +36 -0
  144. package/src/solver-tools/lsoda/corfailure.js.map +1 -0
  145. package/src/solver-tools/lsoda/corfailure.ts +42 -0
  146. package/src/solver-tools/lsoda/correction.js +112 -0
  147. package/src/solver-tools/lsoda/correction.js.map +1 -0
  148. package/src/solver-tools/lsoda/correction.ts +131 -0
  149. package/src/solver-tools/lsoda/dense.js +121 -0
  150. package/src/solver-tools/lsoda/dense.js.map +1 -0
  151. package/src/solver-tools/lsoda/dense.ts +141 -0
  152. package/src/solver-tools/lsoda/index.js +15 -0
  153. package/src/solver-tools/lsoda/index.js.map +1 -0
  154. package/src/solver-tools/lsoda/index.ts +17 -0
  155. package/src/solver-tools/lsoda/intdy.js +54 -0
  156. package/src/solver-tools/lsoda/intdy.js.map +1 -0
  157. package/src/solver-tools/lsoda/intdy.ts +62 -0
  158. package/src/solver-tools/lsoda/lsoda.js +578 -0
  159. package/src/solver-tools/lsoda/lsoda.js.map +1 -0
  160. package/src/solver-tools/lsoda/lsoda.ts +644 -0
  161. package/src/solver-tools/lsoda/methodswitch.js +108 -0
  162. package/src/solver-tools/lsoda/methodswitch.js.map +1 -0
  163. package/src/solver-tools/lsoda/methodswitch.ts +119 -0
  164. package/src/solver-tools/lsoda/orderswitch.js +97 -0
  165. package/src/solver-tools/lsoda/orderswitch.js.map +1 -0
  166. package/src/solver-tools/lsoda/orderswitch.ts +107 -0
  167. package/src/solver-tools/lsoda/prja.js +54 -0
  168. package/src/solver-tools/lsoda/prja.js.map +1 -0
  169. package/src/solver-tools/lsoda/prja.ts +61 -0
  170. package/src/solver-tools/lsoda/scaleh.js +41 -0
  171. package/src/solver-tools/lsoda/scaleh.js.map +1 -0
  172. package/src/solver-tools/lsoda/scaleh.ts +45 -0
  173. package/src/solver-tools/lsoda/solsy.js +25 -0
  174. package/src/solver-tools/lsoda/solsy.js.map +1 -0
  175. package/src/solver-tools/lsoda/solsy.ts +30 -0
  176. package/src/solver-tools/lsoda/stoda.js +270 -0
  177. package/src/solver-tools/lsoda/stoda.js.map +1 -0
  178. package/src/solver-tools/lsoda/stoda.ts +298 -0
  179. package/src/solver-tools/lsoda-method.js +134 -0
  180. package/src/solver-tools/lsoda-method.js.map +1 -0
  181. package/src/solver-tools/lsoda-method.ts +154 -0
  182. package/src/solver-tools/mrt-method.js +81 -18
  183. package/src/solver-tools/mrt-method.js.map +1 -1
  184. package/src/solver-tools/mrt-method.ts +111 -21
  185. package/src/solver-tools/rk3-method.js +210 -0
  186. package/src/solver-tools/rk3-method.js.map +1 -0
  187. package/src/solver-tools/rk3-method.ts +257 -0
  188. package/src/solver-tools/rk4-method.js +236 -0
  189. package/src/solver-tools/rk4-method.js.map +1 -0
  190. package/src/solver-tools/rk4-method.ts +286 -0
  191. package/src/solver-tools/rkdp-method.js +247 -0
  192. package/src/solver-tools/rkdp-method.js.map +1 -0
  193. package/src/solver-tools/rkdp-method.ts +300 -0
  194. package/src/solver-tools/ros34prw-method.js +1 -1
  195. package/src/solver-tools/ros34prw-method.js.map +1 -1
  196. package/src/solver-tools/ros34prw-method.ts +1 -1
  197. package/src/solver-tools/ros3prw-method.js +1 -1
  198. package/src/solver-tools/ros3prw-method.js.map +1 -1
  199. package/src/solver-tools/ros3prw-method.ts +1 -1
  200. package/src/solver-tools/solver-defs.js +7 -0
  201. package/src/solver-tools/solver-defs.js.map +1 -1
  202. package/src/solver-tools/solver-defs.ts +7 -0
  203. package/src/tests/correctness.test.js +6 -4
  204. package/src/tests/correctness.test.js.map +1 -1
  205. package/src/tests/correctness.test.ts +6 -4
  206. package/src/tests/cvode-lib-correctness.test.js +404 -0
  207. package/src/tests/cvode-lib-correctness.test.js.map +1 -0
  208. package/src/tests/cvode-lib-correctness.test.ts +505 -0
  209. package/src/tests/cvode-lib-performance.test.js +103 -0
  210. package/src/tests/cvode-lib-performance.test.js.map +1 -0
  211. package/src/tests/cvode-lib-performance.test.ts +128 -0
  212. package/src/tests/lsoda-lib-correctness.test.js +223 -0
  213. package/src/tests/lsoda-lib-correctness.test.js.map +1 -0
  214. package/src/tests/lsoda-lib-correctness.test.ts +283 -0
  215. package/src/tests/lsoda-lib-performance.test.js +95 -0
  216. package/src/tests/lsoda-lib-performance.test.js.map +1 -0
  217. package/src/tests/lsoda-lib-performance.test.ts +126 -0
  218. package/src/tests/performance.test.js +12 -8
  219. package/src/tests/performance.test.js.map +1 -1
  220. package/src/tests/performance.test.ts +12 -8
  221. package/src/tests/test-defs.js +20 -1
  222. package/src/tests/test-defs.js.map +1 -1
  223. package/src/tests/test-defs.ts +22 -1
  224. package/src/worker-tools/solving.js +15 -1
  225. package/src/worker-tools/solving.js.map +1 -1
  226. 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