conspire/math/integrate/verner_9/
mod.rs

1#[cfg(test)]
2mod test;
3
4use super::{
5    super::{Tensor, TensorRank0, TensorVec, Vector, interpolate::InterpolateSolution},
6    Explicit, IntegrationError,
7};
8use crate::{ABS_TOL, REL_TOL};
9use std::ops::{Mul, Sub};
10
11const C_2: TensorRank0 = 0.03462;
12const C_3: TensorRank0 = 0.097_024_350_638_780_44;
13const C_4: TensorRank0 = 0.145_536_525_958_170_67;
14const C_5: TensorRank0 = 0.561;
15const C_6: TensorRank0 = 0.229_007_911_590_485;
16const C_7: TensorRank0 = 0.544_992_088_409_515;
17const C_8: TensorRank0 = 0.645;
18const C_9: TensorRank0 = 0.48375;
19const C_10: TensorRank0 = 0.06757;
20const C_11: TensorRank0 = 0.2500;
21const C_12: TensorRank0 = 0.659_065_061_873_099_9;
22const C_13: TensorRank0 = 0.8206;
23const C_14: TensorRank0 = 0.9012;
24
25const A_2_1: TensorRank0 = 0.03462;
26const A_3_1: TensorRank0 = -0.03893354388572875;
27const A_3_2: TensorRank0 = 0.13595789452450918;
28const A_4_1: TensorRank0 = 0.03638413148954267;
29const A_4_3: TensorRank0 = 0.10915239446862801;
30const A_5_1: TensorRank0 = 2.0257639143939694;
31const A_5_3: TensorRank0 = -7.638023836496291;
32const A_5_4: TensorRank0 = 6.173259922102322;
33const A_6_1: TensorRank0 = 0.05112275589406061;
34const A_6_4: TensorRank0 = 0.17708237945550218;
35const A_6_5: TensorRank0 = 0.0008027762409222536;
36const A_7_1: TensorRank0 = 0.13160063579752163;
37const A_7_4: TensorRank0 = -0.2957276252669636;
38const A_7_5: TensorRank0 = 0.08781378035642955;
39const A_7_6: TensorRank0 = 0.6213052975225274;
40const A_8_1: TensorRank0 = 0.07166666666666667;
41const A_8_6: TensorRank0 = 0.33055335789153195;
42const A_8_7: TensorRank0 = 0.2427799754418014;
43const A_9_1: TensorRank0 = 0.071806640625;
44const A_9_6: TensorRank0 = 0.3294380283228177;
45const A_9_7: TensorRank0 = 0.1165190029271823;
46const A_9_8: TensorRank0 = -0.034013671875;
47const A_10_1: TensorRank0 = 0.04836757646340646;
48const A_10_6: TensorRank0 = 0.03928989925676164;
49const A_10_7: TensorRank0 = 0.10547409458903446;
50const A_10_8: TensorRank0 = -0.021438652846483126;
51const A_10_9: TensorRank0 = -0.10412291746271944;
52const A_11_1: TensorRank0 = -0.026645614872014785;
53const A_11_6: TensorRank0 = 0.03333333333333333;
54const A_11_7: TensorRank0 = -0.1631072244872467;
55const A_11_8: TensorRank0 = 0.03396081684127761;
56const A_11_9: TensorRank0 = 0.1572319413814626;
57const A_11_10: TensorRank0 = 0.21522674780318796;
58const A_12_1: TensorRank0 = 0.03689009248708622;
59const A_12_6: TensorRank0 = -0.1465181576725543;
60const A_12_7: TensorRank0 = 0.2242577768172024;
61const A_12_8: TensorRank0 = 0.02294405717066073;
62const A_12_9: TensorRank0 = -0.0035850052905728597;
63const A_12_10: TensorRank0 = 0.08669223316444385;
64const A_12_11: TensorRank0 = 0.43838406519683376;
65const A_13_1: TensorRank0 = -0.4866012215113341;
66const A_13_6: TensorRank0 = -6.304602650282853;
67const A_13_7: TensorRank0 = -0.2812456182894729;
68const A_13_8: TensorRank0 = -2.679019236219849;
69const A_13_9: TensorRank0 = 0.5188156639241577;
70const A_13_10: TensorRank0 = 1.3653531876033418;
71const A_13_11: TensorRank0 = 5.8850910885039465;
72const A_13_12: TensorRank0 = 2.8028087862720628;
73const A_14_1: TensorRank0 = 0.4185367457753472;
74const A_14_6: TensorRank0 = 6.724547581906459;
75const A_14_7: TensorRank0 = -0.42544428016461133;
76const A_14_8: TensorRank0 = 3.3432791530012653;
77const A_14_9: TensorRank0 = 0.6170816631175374;
78const A_14_10: TensorRank0 = -0.9299661239399329;
79const A_14_11: TensorRank0 = -6.099948804751011;
80const A_14_12: TensorRank0 = -3.002206187889399;
81const A_14_13: TensorRank0 = 0.2553202529443446;
82const A_15_1: TensorRank0 = -0.7793740861228848;
83const A_15_6: TensorRank0 = -13.937342538107776;
84const A_15_7: TensorRank0 = 1.2520488533793563;
85const A_15_8: TensorRank0 = -14.691500408016868;
86const A_15_9: TensorRank0 = -0.494705058533141;
87const A_15_10: TensorRank0 = 2.2429749091462368;
88const A_15_11: TensorRank0 = 13.367893803828643;
89const A_15_12: TensorRank0 = 14.396650486650687;
90const A_15_13: TensorRank0 = -0.79758133317768;
91const A_15_14: TensorRank0 = 0.4409353709534278;
92const A_16_1: TensorRank0 = 2.0580513374668867;
93const A_16_6: TensorRank0 = 22.357937727968032;
94const A_16_7: TensorRank0 = 0.9094981099755646;
95const A_16_8: TensorRank0 = 35.89110098240264;
96const A_16_9: TensorRank0 = -3.442515027624454;
97const A_16_10: TensorRank0 = -4.865481358036369;
98const A_16_11: TensorRank0 = -18.909803813543427;
99const A_16_12: TensorRank0 = -34.26354448030452;
100const A_16_13: TensorRank0 = 1.2647565216956427;
101
102const B_1: TensorRank0 = 0.014611976858423152;
103const B_8: TensorRank0 = -0.3915211862331339;
104const B_9: TensorRank0 = 0.23109325002895065;
105const B_10: TensorRank0 = 0.12747667699928525;
106const B_11: TensorRank0 = 0.2246434176204158;
107const B_12: TensorRank0 = 0.5684352689748513;
108const B_13: TensorRank0 = 0.058258715572158275;
109const B_14: TensorRank0 = 0.13643174034822156;
110const B_15: TensorRank0 = 0.030570139830827976;
111
112const D_1: TensorRank0 = -0.005357988290444578;
113const D_8: TensorRank0 = -2.583020491182464;
114const D_9: TensorRank0 = 0.14252253154686625;
115const D_10: TensorRank0 = 0.013420653512688676;
116const D_11: TensorRank0 = -0.02867296291409493;
117const D_12: TensorRank0 = 2.624999655215792;
118const D_13: TensorRank0 = -0.2825509643291537;
119const D_14: TensorRank0 = 0.13643174034822156;
120const D_15: TensorRank0 = 0.030570139830827976;
121const D_16: TensorRank0 = -0.04834231373823958;
122
123/// Explicit, sixteen-stage, ninth-order, variable-step, Runge-Kutta method.[^cite]
124///
125/// [^cite]: J.H. Verner, [Numer. Algor. **53**, 383 (2010)](https://doi.org/10.1007/s11075-009-9290-3).
126///
127/// ```math
128/// \frac{dy}{dt} = f(t, y)
129/// ```
130/// ```math
131/// t_{n+1} = t_n + h
132/// ```
133/// ```math
134/// k_1 = f(t_n, y_n)
135/// ```
136/// ```math
137/// \cdots
138/// ```
139/// ```math
140/// h_{n+1} = \beta h \left(\frac{e_\mathrm{tol}}{e_{n+1}}\right)^{1/p}
141/// ```
142
143#[derive(Debug)]
144pub struct Verner9 {
145    /// Absolute error tolerance.
146    pub abs_tol: TensorRank0,
147    /// Relative error tolerance.
148    pub rel_tol: TensorRank0,
149    /// Multiplier for adaptive time steps.
150    pub dt_beta: TensorRank0,
151    /// Exponent for adaptive time steps.
152    pub dt_expn: TensorRank0,
153}
154
155impl Default for Verner9 {
156    fn default() -> Self {
157        Self {
158            abs_tol: ABS_TOL,
159            rel_tol: REL_TOL,
160            dt_beta: 0.9,
161            dt_expn: 9.0,
162        }
163    }
164}
165
166impl<Y, U> Explicit<Y, U> for Verner9
167where
168    Self: InterpolateSolution<Y, U>,
169    Y: Tensor,
170    for<'a> &'a Y: Mul<TensorRank0, Output = Y> + Sub<&'a Y, Output = Y>,
171    U: TensorVec<Item = Y>,
172{
173    fn integrate(
174        &self,
175        mut function: impl FnMut(TensorRank0, &Y) -> Result<Y, IntegrationError>,
176        time: &[TensorRank0],
177        initial_condition: Y,
178    ) -> Result<(Vector, U, U), IntegrationError> {
179        let t_0 = time[0];
180        let t_f = time[time.len() - 1];
181        if time.len() < 2 {
182            return Err(IntegrationError::LengthTimeLessThanTwo);
183        } else if t_0 >= t_f {
184            return Err(IntegrationError::InitialTimeNotLessThanFinalTime);
185        }
186        let mut t = t_0;
187        let mut dt = t_f;
188        let mut e;
189        let mut k_1 = function(t, &initial_condition)?;
190        let mut k_2;
191        let mut k_3;
192        let mut k_4;
193        let mut k_5;
194        let mut k_6;
195        let mut k_7;
196        let mut k_8;
197        let mut k_9;
198        let mut k_10;
199        let mut k_11;
200        let mut k_12;
201        let mut k_13;
202        let mut k_14;
203        let mut k_15;
204        let mut k_16;
205        let mut t_sol = Vector::zero(0);
206        t_sol.push(t_0);
207        let mut y = initial_condition.clone();
208        let mut y_sol = U::zero(0);
209        y_sol.push(initial_condition.clone());
210        let mut dydt_sol = U::zero(0);
211        dydt_sol.push(k_1.clone());
212        let mut y_trial;
213        while t < t_f {
214            k_1 = function(t, &y)?;
215            k_2 = function(t + C_2 * dt, &(&k_1 * (A_2_1 * dt) + &y))?;
216            k_3 = function(
217                t + C_3 * dt,
218                &(&k_1 * (A_3_1 * dt) + &k_2 * (A_3_2 * dt) + &y),
219            )?;
220            k_4 = function(
221                t + C_4 * dt,
222                &(&k_1 * (A_4_1 * dt) + &k_3 * (A_4_3 * dt) + &y),
223            )?;
224            k_5 = function(
225                t + C_5 * dt,
226                &(&k_1 * (A_5_1 * dt) + &k_3 * (A_5_3 * dt) + &k_4 * (A_5_4 * dt) + &y),
227            )?;
228            k_6 = function(
229                t + C_6 * dt,
230                &(&k_1 * (A_6_1 * dt) + &k_4 * (A_6_4 * dt) + &k_5 * (A_6_5 * dt) + &y),
231            )?;
232            k_7 = function(
233                t + C_7 * dt,
234                &(&k_1 * (A_7_1 * dt)
235                    + &k_4 * (A_7_4 * dt)
236                    + &k_5 * (A_7_5 * dt)
237                    + &k_6 * (A_7_6 * dt)
238                    + &y),
239            )?;
240            k_8 = function(
241                t + C_8 * dt,
242                &(&k_1 * (A_8_1 * dt) + &k_6 * (A_8_6 * dt) + &k_7 * (A_8_7 * dt) + &y),
243            )?;
244            k_9 = function(
245                t + C_9 * dt,
246                &(&k_1 * (A_9_1 * dt)
247                    + &k_6 * (A_9_6 * dt)
248                    + &k_7 * (A_9_7 * dt)
249                    + &k_8 * (A_9_8 * dt)
250                    + &y),
251            )?;
252            k_10 = function(
253                t + C_10 * dt,
254                &(&k_1 * (A_10_1 * dt)
255                    + &k_6 * (A_10_6 * dt)
256                    + &k_7 * (A_10_7 * dt)
257                    + &k_8 * (A_10_8 * dt)
258                    + &k_9 * (A_10_9 * dt)
259                    + &y),
260            )?;
261            k_11 = function(
262                t + C_11 * dt,
263                &(&k_1 * (A_11_1 * dt)
264                    + &k_6 * (A_11_6 * dt)
265                    + &k_7 * (A_11_7 * dt)
266                    + &k_8 * (A_11_8 * dt)
267                    + &k_9 * (A_11_9 * dt)
268                    + &k_10 * (A_11_10 * dt)
269                    + &y),
270            )?;
271            k_12 = function(
272                t + C_12 * dt,
273                &(&k_1 * (A_12_1 * dt)
274                    + &k_6 * (A_12_6 * dt)
275                    + &k_7 * (A_12_7 * dt)
276                    + &k_8 * (A_12_8 * dt)
277                    + &k_9 * (A_12_9 * dt)
278                    + &k_10 * (A_12_10 * dt)
279                    + &k_11 * (A_12_11 * dt)
280                    + &y),
281            )?;
282            k_13 = function(
283                t + C_13 * dt,
284                &(&k_1 * (A_13_1 * dt)
285                    + &k_6 * (A_13_6 * dt)
286                    + &k_7 * (A_13_7 * dt)
287                    + &k_8 * (A_13_8 * dt)
288                    + &k_9 * (A_13_9 * dt)
289                    + &k_10 * (A_13_10 * dt)
290                    + &k_11 * (A_13_11 * dt)
291                    + &k_12 * (A_13_12 * dt)
292                    + &y),
293            )?;
294            k_14 = function(
295                t + C_14 * dt,
296                &(&k_1 * (A_14_1 * dt)
297                    + &k_6 * (A_14_6 * dt)
298                    + &k_7 * (A_14_7 * dt)
299                    + &k_8 * (A_14_8 * dt)
300                    + &k_9 * (A_14_9 * dt)
301                    + &k_10 * (A_14_10 * dt)
302                    + &k_11 * (A_14_11 * dt)
303                    + &k_12 * (A_14_12 * dt)
304                    + &k_13 * (A_14_13 * dt)
305                    + &y),
306            )?;
307            k_15 = function(
308                t + dt,
309                &(&k_1 * (A_15_1 * dt)
310                    + &k_6 * (A_15_6 * dt)
311                    + &k_7 * (A_15_7 * dt)
312                    + &k_8 * (A_15_8 * dt)
313                    + &k_9 * (A_15_9 * dt)
314                    + &k_10 * (A_15_10 * dt)
315                    + &k_11 * (A_15_11 * dt)
316                    + &k_12 * (A_15_12 * dt)
317                    + &k_13 * (A_15_13 * dt)
318                    + &k_14 * (A_15_14 * dt)
319                    + &y),
320            )?;
321            y_trial = (&k_1 * B_1
322                + &k_8 * B_8
323                + &k_9 * B_9
324                + &k_10 * B_10
325                + &k_11 * B_11
326                + &k_12 * B_12
327                + &k_13 * B_13
328                + &k_14 * B_14
329                + &k_15 * B_15)
330                * dt
331                + &y;
332            k_16 = function(
333                t + dt,
334                &(&k_1 * (A_16_1 * dt)
335                    + &k_6 * (A_16_6 * dt)
336                    + &k_7 * (A_16_7 * dt)
337                    + &k_8 * (A_16_8 * dt)
338                    + &k_9 * (A_16_9 * dt)
339                    + &k_10 * (A_16_10 * dt)
340                    + &k_11 * (A_16_11 * dt)
341                    + &k_12 * (A_16_12 * dt)
342                    + &k_13 * (A_16_13 * dt)
343                    + &y),
344            )?;
345            e = ((&k_1 * D_1
346                + &k_8 * D_8
347                + &k_9 * D_9
348                + &k_10 * D_10
349                + &k_11 * D_11
350                + &k_12 * D_12
351                + &k_13 * D_13
352                + &k_14 * D_14
353                + &k_15 * D_15
354                + &k_16 * D_16)
355                * dt)
356                .norm_inf();
357            if e < self.abs_tol || e / y_trial.norm_inf() < self.rel_tol {
358                t += dt;
359                y = y_trial;
360                t_sol.push(t);
361                y_sol.push(y.clone());
362                dydt_sol.push(function(t, &y)?);
363            }
364            if e > 0.0 {
365                dt *= self.dt_beta * (self.abs_tol / e).powf(1.0 / self.dt_expn)
366            }
367            dt = dt.min(t_f - t)
368        }
369        if time.len() > 2 {
370            let t_int = Vector::new(time);
371            let (y_int, dydt_int) = self.interpolate(&t_int, &t_sol, &y_sol, function)?;
372            Ok((t_int, y_int, dydt_int))
373        } else {
374            Ok((t_sol, y_sol, dydt_sol))
375        }
376    }
377}
378
379impl<Y, U> InterpolateSolution<Y, U> for Verner9
380where
381    Y: Tensor,
382    for<'a> &'a Y: Mul<TensorRank0, Output = Y> + Sub<&'a Y, Output = Y>,
383    U: TensorVec<Item = Y>,
384{
385    fn interpolate(
386        &self,
387        time: &Vector,
388        tp: &Vector,
389        yp: &U,
390        mut function: impl FnMut(TensorRank0, &Y) -> Result<Y, IntegrationError>,
391    ) -> Result<(U, U), IntegrationError> {
392        let mut dt;
393        let mut i;
394        let mut k_1;
395        let mut k_2;
396        let mut k_3;
397        let mut k_4;
398        let mut k_5;
399        let mut k_6;
400        let mut k_7;
401        let mut k_8;
402        let mut k_9;
403        let mut k_10;
404        let mut k_11;
405        let mut k_12;
406        let mut k_13;
407        let mut k_14;
408        let mut k_15;
409        let mut t;
410        let mut y;
411        let mut y_int = U::zero(0);
412        let mut dydt_int = U::zero(0);
413        let mut y_trial;
414        for time_k in time.iter() {
415            i = tp.iter().position(|tp_i| tp_i >= time_k).unwrap();
416            if time_k == &tp[i] {
417                t = tp[i];
418                y_trial = yp[i].clone();
419                dt = 0.0;
420            } else {
421                t = tp[i - 1];
422                y = yp[i - 1].clone();
423                dt = time_k - t;
424                k_1 = function(t, &y)?;
425                k_2 = function(t + C_2 * dt, &(&k_1 * (A_2_1 * dt) + &y))?;
426                k_3 = function(
427                    t + C_3 * dt,
428                    &(&k_1 * (A_3_1 * dt) + &k_2 * (A_3_2 * dt) + &y),
429                )?;
430                k_4 = function(
431                    t + C_4 * dt,
432                    &(&k_1 * (A_4_1 * dt) + &k_3 * (A_4_3 * dt) + &y),
433                )?;
434                k_5 = function(
435                    t + C_5 * dt,
436                    &(&k_1 * (A_5_1 * dt) + &k_3 * (A_5_3 * dt) + &k_4 * (A_5_4 * dt) + &y),
437                )?;
438                k_6 = function(
439                    t + C_6 * dt,
440                    &(&k_1 * (A_6_1 * dt) + &k_4 * (A_6_4 * dt) + &k_5 * (A_6_5 * dt) + &y),
441                )?;
442                k_7 = function(
443                    t + C_7 * dt,
444                    &(&k_1 * (A_7_1 * dt)
445                        + &k_4 * (A_7_4 * dt)
446                        + &k_5 * (A_7_5 * dt)
447                        + &k_6 * (A_7_6 * dt)
448                        + &y),
449                )?;
450                k_8 = function(
451                    t + C_8 * dt,
452                    &(&k_1 * (A_8_1 * dt) + &k_6 * (A_8_6 * dt) + &k_7 * (A_8_7 * dt) + &y),
453                )?;
454                k_9 = function(
455                    t + C_9 * dt,
456                    &(&k_1 * (A_9_1 * dt)
457                        + &k_6 * (A_9_6 * dt)
458                        + &k_7 * (A_9_7 * dt)
459                        + &k_8 * (A_9_8 * dt)
460                        + &y),
461                )?;
462                k_10 = function(
463                    t + C_10 * dt,
464                    &(&k_1 * (A_10_1 * dt)
465                        + &k_6 * (A_10_6 * dt)
466                        + &k_7 * (A_10_7 * dt)
467                        + &k_8 * (A_10_8 * dt)
468                        + &k_9 * (A_10_9 * dt)
469                        + &y),
470                )?;
471                k_11 = function(
472                    t + C_11 * dt,
473                    &(&k_1 * (A_11_1 * dt)
474                        + &k_6 * (A_11_6 * dt)
475                        + &k_7 * (A_11_7 * dt)
476                        + &k_8 * (A_11_8 * dt)
477                        + &k_9 * (A_11_9 * dt)
478                        + &k_10 * (A_11_10 * dt)
479                        + &y),
480                )?;
481                k_12 = function(
482                    t + C_12 * dt,
483                    &(&k_1 * (A_12_1 * dt)
484                        + &k_6 * (A_12_6 * dt)
485                        + &k_7 * (A_12_7 * dt)
486                        + &k_8 * (A_12_8 * dt)
487                        + &k_9 * (A_12_9 * dt)
488                        + &k_10 * (A_12_10 * dt)
489                        + &k_11 * (A_12_11 * dt)
490                        + &y),
491                )?;
492                k_13 = function(
493                    t + C_13 * dt,
494                    &(&k_1 * (A_13_1 * dt)
495                        + &k_6 * (A_13_6 * dt)
496                        + &k_7 * (A_13_7 * dt)
497                        + &k_8 * (A_13_8 * dt)
498                        + &k_9 * (A_13_9 * dt)
499                        + &k_10 * (A_13_10 * dt)
500                        + &k_11 * (A_13_11 * dt)
501                        + &k_12 * (A_13_12 * dt)
502                        + &y),
503                )?;
504                k_14 = function(
505                    t + C_14 * dt,
506                    &(&k_1 * (A_14_1 * dt)
507                        + &k_6 * (A_14_6 * dt)
508                        + &k_7 * (A_14_7 * dt)
509                        + &k_8 * (A_14_8 * dt)
510                        + &k_9 * (A_14_9 * dt)
511                        + &k_10 * (A_14_10 * dt)
512                        + &k_11 * (A_14_11 * dt)
513                        + &k_12 * (A_14_12 * dt)
514                        + &k_13 * (A_14_13 * dt)
515                        + &y),
516                )?;
517                k_15 = function(
518                    t + dt,
519                    &(&k_1 * (A_15_1 * dt)
520                        + &k_6 * (A_15_6 * dt)
521                        + &k_7 * (A_15_7 * dt)
522                        + &k_8 * (A_15_8 * dt)
523                        + &k_9 * (A_15_9 * dt)
524                        + &k_10 * (A_15_10 * dt)
525                        + &k_11 * (A_15_11 * dt)
526                        + &k_12 * (A_15_12 * dt)
527                        + &k_13 * (A_15_13 * dt)
528                        + &k_14 * (A_15_14 * dt)
529                        + &y),
530                )?;
531                y_trial = (&k_1 * B_1
532                    + &k_8 * B_8
533                    + &k_9 * B_9
534                    + &k_10 * B_10
535                    + &k_11 * B_11
536                    + &k_12 * B_12
537                    + &k_13 * B_13
538                    + &k_14 * B_14
539                    + &k_15 * B_15)
540                    * dt
541                    + &y;
542            }
543            dydt_int.push(function(t + dt, &y_trial)?);
544            y_int.push(y_trial);
545        }
546        Ok((y_int, dydt_int))
547    }
548}