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    /// Initial relative time step.
154    pub dt_init: TensorRank0,
155}
156
157impl Default for Verner9 {
158    fn default() -> Self {
159        Self {
160            abs_tol: ABS_TOL,
161            rel_tol: REL_TOL,
162            dt_beta: 0.9,
163            dt_expn: 9.0,
164            dt_init: 0.1,
165        }
166    }
167}
168
169impl<Y, U> Explicit<Y, U> for Verner9
170where
171    Self: InterpolateSolution<Y, U>,
172    Y: Tensor,
173    for<'a> &'a Y: Mul<TensorRank0, Output = Y> + Sub<&'a Y, Output = Y>,
174    U: TensorVec<Item = Y>,
175{
176    fn integrate(
177        &self,
178        function: impl Fn(TensorRank0, &Y) -> Result<Y, IntegrationError>,
179        time: &[TensorRank0],
180        initial_condition: Y,
181    ) -> Result<(Vector, U, U), IntegrationError> {
182        if time.len() < 2 {
183            return Err(IntegrationError::LengthTimeLessThanTwo);
184        } else if time[0] >= time[time.len() - 1] {
185            return Err(IntegrationError::InitialTimeNotLessThanFinalTime);
186        }
187        let mut t = time[0];
188        let mut dt = self.dt_init * time[time.len() - 1];
189        let mut e;
190        let mut k_1 = function(t, &initial_condition)?;
191        let mut k_2;
192        let mut k_3;
193        let mut k_4;
194        let mut k_5;
195        let mut k_6;
196        let mut k_7;
197        let mut k_8;
198        let mut k_9;
199        let mut k_10;
200        let mut k_11;
201        let mut k_12;
202        let mut k_13;
203        let mut k_14;
204        let mut k_15;
205        let mut k_16;
206        let mut t_sol = Vector::zero(0);
207        t_sol.push(time[0]);
208        let mut y = initial_condition.clone();
209        let mut y_sol = U::zero(0);
210        y_sol.push(initial_condition.clone());
211        let mut dydt_sol = U::zero(0);
212        dydt_sol.push(k_1.clone());
213        let mut y_trial;
214        while t < time[time.len() - 1] {
215            k_1 = function(t, &y)?;
216            k_2 = function(t + C_2 * dt, &(&k_1 * (A_2_1 * dt) + &y))?;
217            k_3 = function(
218                t + C_3 * dt,
219                &(&k_1 * (A_3_1 * dt) + &k_2 * (A_3_2 * dt) + &y),
220            )?;
221            k_4 = function(
222                t + C_4 * dt,
223                &(&k_1 * (A_4_1 * dt) + &k_3 * (A_4_3 * dt) + &y),
224            )?;
225            k_5 = function(
226                t + C_5 * dt,
227                &(&k_1 * (A_5_1 * dt) + &k_3 * (A_5_3 * dt) + &k_4 * (A_5_4 * dt) + &y),
228            )?;
229            k_6 = function(
230                t + C_6 * dt,
231                &(&k_1 * (A_6_1 * dt) + &k_4 * (A_6_4 * dt) + &k_5 * (A_6_5 * dt) + &y),
232            )?;
233            k_7 = function(
234                t + C_7 * dt,
235                &(&k_1 * (A_7_1 * dt)
236                    + &k_4 * (A_7_4 * dt)
237                    + &k_5 * (A_7_5 * dt)
238                    + &k_6 * (A_7_6 * dt)
239                    + &y),
240            )?;
241            k_8 = function(
242                t + C_8 * dt,
243                &(&k_1 * (A_8_1 * dt) + &k_6 * (A_8_6 * dt) + &k_7 * (A_8_7 * dt) + &y),
244            )?;
245            k_9 = function(
246                t + C_9 * dt,
247                &(&k_1 * (A_9_1 * dt)
248                    + &k_6 * (A_9_6 * dt)
249                    + &k_7 * (A_9_7 * dt)
250                    + &k_8 * (A_9_8 * dt)
251                    + &y),
252            )?;
253            k_10 = function(
254                t + C_10 * dt,
255                &(&k_1 * (A_10_1 * dt)
256                    + &k_6 * (A_10_6 * dt)
257                    + &k_7 * (A_10_7 * dt)
258                    + &k_8 * (A_10_8 * dt)
259                    + &k_9 * (A_10_9 * dt)
260                    + &y),
261            )?;
262            k_11 = function(
263                t + C_11 * dt,
264                &(&k_1 * (A_11_1 * dt)
265                    + &k_6 * (A_11_6 * dt)
266                    + &k_7 * (A_11_7 * dt)
267                    + &k_8 * (A_11_8 * dt)
268                    + &k_9 * (A_11_9 * dt)
269                    + &k_10 * (A_11_10 * dt)
270                    + &y),
271            )?;
272            k_12 = function(
273                t + C_12 * dt,
274                &(&k_1 * (A_12_1 * dt)
275                    + &k_6 * (A_12_6 * dt)
276                    + &k_7 * (A_12_7 * dt)
277                    + &k_8 * (A_12_8 * dt)
278                    + &k_9 * (A_12_9 * dt)
279                    + &k_10 * (A_12_10 * dt)
280                    + &k_11 * (A_12_11 * dt)
281                    + &y),
282            )?;
283            k_13 = function(
284                t + C_13 * dt,
285                &(&k_1 * (A_13_1 * dt)
286                    + &k_6 * (A_13_6 * dt)
287                    + &k_7 * (A_13_7 * dt)
288                    + &k_8 * (A_13_8 * dt)
289                    + &k_9 * (A_13_9 * dt)
290                    + &k_10 * (A_13_10 * dt)
291                    + &k_11 * (A_13_11 * dt)
292                    + &k_12 * (A_13_12 * dt)
293                    + &y),
294            )?;
295            k_14 = function(
296                t + C_14 * dt,
297                &(&k_1 * (A_14_1 * dt)
298                    + &k_6 * (A_14_6 * dt)
299                    + &k_7 * (A_14_7 * dt)
300                    + &k_8 * (A_14_8 * dt)
301                    + &k_9 * (A_14_9 * dt)
302                    + &k_10 * (A_14_10 * dt)
303                    + &k_11 * (A_14_11 * dt)
304                    + &k_12 * (A_14_12 * dt)
305                    + &k_13 * (A_14_13 * dt)
306                    + &y),
307            )?;
308            k_15 = function(
309                t + dt,
310                &(&k_1 * (A_15_1 * dt)
311                    + &k_6 * (A_15_6 * dt)
312                    + &k_7 * (A_15_7 * dt)
313                    + &k_8 * (A_15_8 * dt)
314                    + &k_9 * (A_15_9 * dt)
315                    + &k_10 * (A_15_10 * dt)
316                    + &k_11 * (A_15_11 * dt)
317                    + &k_12 * (A_15_12 * dt)
318                    + &k_13 * (A_15_13 * dt)
319                    + &k_14 * (A_15_14 * dt)
320                    + &y),
321            )?;
322            y_trial = (&k_1 * B_1
323                + &k_8 * B_8
324                + &k_9 * B_9
325                + &k_10 * B_10
326                + &k_11 * B_11
327                + &k_12 * B_12
328                + &k_13 * B_13
329                + &k_14 * B_14
330                + &k_15 * B_15)
331                * dt
332                + &y;
333            k_16 = function(
334                t + dt,
335                &(&k_1 * (A_16_1 * dt)
336                    + &k_6 * (A_16_6 * dt)
337                    + &k_7 * (A_16_7 * dt)
338                    + &k_8 * (A_16_8 * dt)
339                    + &k_9 * (A_16_9 * dt)
340                    + &k_10 * (A_16_10 * dt)
341                    + &k_11 * (A_16_11 * dt)
342                    + &k_12 * (A_16_12 * dt)
343                    + &k_13 * (A_16_13 * dt)
344                    + &y),
345            )?;
346            e = ((&k_1 * D_1
347                + &k_8 * D_8
348                + &k_9 * D_9
349                + &k_10 * D_10
350                + &k_11 * D_11
351                + &k_12 * D_12
352                + &k_13 * D_13
353                + &k_14 * D_14
354                + &k_15 * D_15
355                + &k_16 * D_16)
356                * dt)
357                .norm_inf();
358            if e < self.abs_tol || e / y_trial.norm_inf() < self.rel_tol {
359                t += dt;
360                y = y_trial;
361                t_sol.push(t);
362                y_sol.push(y.clone());
363                dydt_sol.push(function(t, &y)?);
364            }
365            dt *= self.dt_beta * (self.abs_tol / e).powf(1.0 / self.dt_expn);
366        }
367        if time.len() > 2 {
368            let t_int = Vector::new(time);
369            let (y_int, dydt_int) = self.interpolate(&t_int, &t_sol, &y_sol, function)?;
370            Ok((t_int, y_int, dydt_int))
371        } else {
372            Ok((t_sol, y_sol, dydt_sol))
373        }
374    }
375}
376
377impl<Y, U> InterpolateSolution<Y, U> for Verner9
378where
379    Y: Tensor,
380    for<'a> &'a Y: Mul<TensorRank0, Output = Y> + Sub<&'a Y, Output = Y>,
381    U: TensorVec<Item = Y>,
382{
383    fn interpolate(
384        &self,
385        time: &Vector,
386        tp: &Vector,
387        yp: &U,
388        function: impl Fn(TensorRank0, &Y) -> Result<Y, IntegrationError>,
389    ) -> Result<(U, U), IntegrationError> {
390        let mut dt;
391        let mut i;
392        let mut k_1;
393        let mut k_2;
394        let mut k_3;
395        let mut k_4;
396        let mut k_5;
397        let mut k_6;
398        let mut k_7;
399        let mut k_8;
400        let mut k_9;
401        let mut k_10;
402        let mut k_11;
403        let mut k_12;
404        let mut k_13;
405        let mut k_14;
406        let mut k_15;
407        let mut t;
408        let mut y;
409        let mut y_int = U::zero(0);
410        let mut dydt_int = U::zero(0);
411        let mut y_trial;
412        for time_k in time.iter() {
413            i = tp.iter().position(|tp_i| tp_i > time_k).unwrap();
414            t = tp[i - 1];
415            y = yp[i - 1].clone();
416            dt = time_k - t;
417            k_1 = function(t, &y)?;
418            k_2 = function(t + C_2 * dt, &(&k_1 * (A_2_1 * dt) + &y))?;
419            k_3 = function(
420                t + C_3 * dt,
421                &(&k_1 * (A_3_1 * dt) + &k_2 * (A_3_2 * dt) + &y),
422            )?;
423            k_4 = function(
424                t + C_4 * dt,
425                &(&k_1 * (A_4_1 * dt) + &k_3 * (A_4_3 * dt) + &y),
426            )?;
427            k_5 = function(
428                t + C_5 * dt,
429                &(&k_1 * (A_5_1 * dt) + &k_3 * (A_5_3 * dt) + &k_4 * (A_5_4 * dt) + &y),
430            )?;
431            k_6 = function(
432                t + C_6 * dt,
433                &(&k_1 * (A_6_1 * dt) + &k_4 * (A_6_4 * dt) + &k_5 * (A_6_5 * dt) + &y),
434            )?;
435            k_7 = function(
436                t + C_7 * dt,
437                &(&k_1 * (A_7_1 * dt)
438                    + &k_4 * (A_7_4 * dt)
439                    + &k_5 * (A_7_5 * dt)
440                    + &k_6 * (A_7_6 * dt)
441                    + &y),
442            )?;
443            k_8 = function(
444                t + C_8 * dt,
445                &(&k_1 * (A_8_1 * dt) + &k_6 * (A_8_6 * dt) + &k_7 * (A_8_7 * dt) + &y),
446            )?;
447            k_9 = function(
448                t + C_9 * dt,
449                &(&k_1 * (A_9_1 * dt)
450                    + &k_6 * (A_9_6 * dt)
451                    + &k_7 * (A_9_7 * dt)
452                    + &k_8 * (A_9_8 * dt)
453                    + &y),
454            )?;
455            k_10 = function(
456                t + C_10 * dt,
457                &(&k_1 * (A_10_1 * dt)
458                    + &k_6 * (A_10_6 * dt)
459                    + &k_7 * (A_10_7 * dt)
460                    + &k_8 * (A_10_8 * dt)
461                    + &k_9 * (A_10_9 * dt)
462                    + &y),
463            )?;
464            k_11 = function(
465                t + C_11 * dt,
466                &(&k_1 * (A_11_1 * dt)
467                    + &k_6 * (A_11_6 * dt)
468                    + &k_7 * (A_11_7 * dt)
469                    + &k_8 * (A_11_8 * dt)
470                    + &k_9 * (A_11_9 * dt)
471                    + &k_10 * (A_11_10 * dt)
472                    + &y),
473            )?;
474            k_12 = function(
475                t + C_12 * dt,
476                &(&k_1 * (A_12_1 * dt)
477                    + &k_6 * (A_12_6 * dt)
478                    + &k_7 * (A_12_7 * dt)
479                    + &k_8 * (A_12_8 * dt)
480                    + &k_9 * (A_12_9 * dt)
481                    + &k_10 * (A_12_10 * dt)
482                    + &k_11 * (A_12_11 * dt)
483                    + &y),
484            )?;
485            k_13 = function(
486                t + C_13 * dt,
487                &(&k_1 * (A_13_1 * dt)
488                    + &k_6 * (A_13_6 * dt)
489                    + &k_7 * (A_13_7 * dt)
490                    + &k_8 * (A_13_8 * dt)
491                    + &k_9 * (A_13_9 * dt)
492                    + &k_10 * (A_13_10 * dt)
493                    + &k_11 * (A_13_11 * dt)
494                    + &k_12 * (A_13_12 * dt)
495                    + &y),
496            )?;
497            k_14 = function(
498                t + C_14 * dt,
499                &(&k_1 * (A_14_1 * dt)
500                    + &k_6 * (A_14_6 * dt)
501                    + &k_7 * (A_14_7 * dt)
502                    + &k_8 * (A_14_8 * dt)
503                    + &k_9 * (A_14_9 * dt)
504                    + &k_10 * (A_14_10 * dt)
505                    + &k_11 * (A_14_11 * dt)
506                    + &k_12 * (A_14_12 * dt)
507                    + &k_13 * (A_14_13 * dt)
508                    + &y),
509            )?;
510            k_15 = function(
511                t + dt,
512                &(&k_1 * (A_15_1 * dt)
513                    + &k_6 * (A_15_6 * dt)
514                    + &k_7 * (A_15_7 * dt)
515                    + &k_8 * (A_15_8 * dt)
516                    + &k_9 * (A_15_9 * dt)
517                    + &k_10 * (A_15_10 * dt)
518                    + &k_11 * (A_15_11 * dt)
519                    + &k_12 * (A_15_12 * dt)
520                    + &k_13 * (A_15_13 * dt)
521                    + &k_14 * (A_15_14 * dt)
522                    + &y),
523            )?;
524            y_trial = (&k_1 * B_1
525                + &k_8 * B_8
526                + &k_9 * B_9
527                + &k_10 * B_10
528                + &k_11 * B_11
529                + &k_12 * B_12
530                + &k_13 * B_13
531                + &k_14 * B_14
532                + &k_15 * B_15)
533                * dt
534                + &y;
535            dydt_int.push(function(t + dt, &y_trial)?);
536            y_int.push(y_trial);
537        }
538        Ok((y_int, dydt_int))
539    }
540}