conspire/math/integrate/verner_8/
mod.rs

1#[cfg(test)]
2mod test;
3
4use super::{
5    super::{Scalar, Tensor, TensorVec, Vector, interpolate::InterpolateSolution},
6    Explicit, IntegrationError,
7};
8use crate::{ABS_TOL, REL_TOL};
9use std::ops::{Mul, Sub};
10
11const C_2: Scalar = 0.05;
12const C_3: Scalar = 0.1065625;
13const C_4: Scalar = 0.15984375;
14const C_5: Scalar = 0.39;
15const C_6: Scalar = 0.465;
16const C_7: Scalar = 0.155;
17const C_8: Scalar = 0.943;
18const C_9: Scalar = 0.901802041735857;
19const C_10: Scalar = 0.909;
20const C_11: Scalar = 0.94;
21
22const A_2_1: Scalar = 0.05;
23const A_3_1: Scalar = -0.0069931640625;
24const A_3_2: Scalar = 0.1135556640625;
25const A_4_1: Scalar = 0.0399609375;
26const A_4_3: Scalar = 0.1198828125;
27const A_5_1: Scalar = 0.36139756280045754;
28const A_5_3: Scalar = -1.3415240667004928;
29const A_5_4: Scalar = 1.3701265039000352;
30const A_6_1: Scalar = 0.049047202797202795;
31const A_6_4: Scalar = 0.23509720422144048;
32const A_6_5: Scalar = 0.18085559298135673;
33const A_7_1: Scalar = 0.06169289044289044;
34const A_7_4: Scalar = 0.11236568314640277;
35const A_7_5: Scalar = -0.03885046071451367;
36const A_7_6: Scalar = 0.01979188712522046;
37const A_8_1: Scalar = -1.767630240222327;
38const A_8_4: Scalar = -62.5;
39const A_8_5: Scalar = -6.061889377376669;
40const A_8_6: Scalar = 5.6508231982227635;
41const A_8_7: Scalar = 65.62169641937624;
42const A_9_1: Scalar = -1.1809450665549708;
43const A_9_4: Scalar = -41.50473441114321;
44const A_9_5: Scalar = -4.434438319103725;
45const A_9_6: Scalar = 4.260408188586133;
46const A_9_7: Scalar = 43.75364022446172;
47const A_9_8: Scalar = 0.00787142548991231;
48const A_10_1: Scalar = -1.2814059994414884;
49const A_10_4: Scalar = -45.047139960139866;
50const A_10_5: Scalar = -4.731362069449576;
51const A_10_6: Scalar = 4.514967016593808;
52const A_10_7: Scalar = 47.44909557172985;
53const A_10_8: Scalar = 0.01059228297111661;
54const A_10_9: Scalar = -0.0057468422638446166;
55const A_11_1: Scalar = -1.7244701342624853;
56const A_11_4: Scalar = -60.92349008483054;
57const A_11_5: Scalar = -5.951518376222392;
58const A_11_6: Scalar = 5.556523730698456;
59const A_11_7: Scalar = 63.98301198033305;
60const A_11_8: Scalar = 0.014642028250414961;
61const A_11_9: Scalar = 0.06460408772358203;
62const A_11_10: Scalar = -0.0793032316900888;
63const A_12_1: Scalar = -3.301622667747079;
64const A_12_4: Scalar = -118.01127235975251;
65const A_12_5: Scalar = -10.141422388456112;
66const A_12_6: Scalar = 9.139311332232058;
67const A_12_7: Scalar = 123.37594282840426;
68const A_12_8: Scalar = 4.62324437887458;
69const A_12_9: Scalar = -3.3832777380682018;
70const A_12_10: Scalar = 4.527592100324618;
71const A_12_11: Scalar = -5.828495485811623;
72const A_13_1: Scalar = -3.039515033766309;
73const A_13_4: Scalar = -109.26086808941763;
74const A_13_5: Scalar = -9.290642497400293;
75const A_13_6: Scalar = 8.43050498176491;
76const A_13_7: Scalar = 114.20100103783314;
77const A_13_8: Scalar = -0.9637271342145479;
78const A_13_9: Scalar = -5.0348840888021895;
79const A_13_10: Scalar = 5.958130824002923;
80
81const B_1: Scalar = 0.04427989419007951;
82const B_6: Scalar = 0.3541049391724449;
83const B_7: Scalar = 0.24796921549564377;
84const B_8: Scalar = -15.694202038838085;
85const B_9: Scalar = 25.084064965558564;
86const B_10: Scalar = -31.738367786260277;
87const B_11: Scalar = 22.938283273988784;
88const B_12: Scalar = -0.2361324633071542;
89
90const D_1: Scalar = -0.00003272103901028138;
91const D_6: Scalar = -0.0005046250618777704;
92const D_7: Scalar = 0.0001211723589784759;
93const D_8: Scalar = -20.142336771313868;
94const D_9: Scalar = 5.2371785994398286;
95const D_10: Scalar = -8.156744408794658;
96const D_11: Scalar = 22.938283273988784;
97const D_12: Scalar = -0.2361324633071542;
98const D_13: Scalar = 0.36016794372897754;
99
100/// Explicit, thirteen-stage, eighth-order, variable-step, Runge-Kutta method.[^cite]
101///
102/// [^cite]: J.H. Verner, [Numer. Algor. **53**, 383 (2010)](https://doi.org/10.1007/s11075-009-9290-3).
103///
104/// ```math
105/// \frac{dy}{dt} = f(t, y)
106/// ```
107/// ```math
108/// t_{n+1} = t_n + h
109/// ```
110/// ```math
111/// k_1 = f(t_n, y_n)
112/// ```
113/// ```math
114/// \cdots
115/// ```
116/// ```math
117/// h_{n+1} = \beta h \left(\frac{e_\mathrm{tol}}{e_{n+1}}\right)^{1/p}
118/// ```
119#[derive(Debug)]
120pub struct Verner8 {
121    /// Absolute error tolerance.
122    pub abs_tol: Scalar,
123    /// Relative error tolerance.
124    pub rel_tol: Scalar,
125    /// Multiplier for adaptive time steps.
126    pub dt_beta: Scalar,
127    /// Exponent for adaptive time steps.
128    pub dt_expn: Scalar,
129}
130
131impl Default for Verner8 {
132    fn default() -> Self {
133        Self {
134            abs_tol: ABS_TOL,
135            rel_tol: REL_TOL,
136            dt_beta: 0.9,
137            dt_expn: 8.0,
138        }
139    }
140}
141
142impl<Y, U> Explicit<Y, U> for Verner8
143where
144    Self: InterpolateSolution<Y, U>,
145    Y: Tensor,
146    for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
147    U: TensorVec<Item = Y>,
148{
149    const SLOPES: usize = 13;
150    fn slopes(
151        &self,
152        mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
153        y: &Y,
154        t: &Scalar,
155        dt: &Scalar,
156        k: &mut [Y],
157        y_trial: &mut Y,
158    ) -> Result<Scalar, String> {
159        k[0] = function(*t, y)?;
160        k[1] = function(t + C_2 * dt, &(&k[0] * (A_2_1 * dt) + y))?;
161        k[2] = function(
162            t + C_3 * dt,
163            &(&k[0] * (A_3_1 * dt) + &k[1] * (A_3_2 * dt) + y),
164        )?;
165        k[3] = function(
166            t + C_4 * dt,
167            &(&k[0] * (A_4_1 * dt) + &k[2] * (A_4_3 * dt) + y),
168        )?;
169        k[4] = function(
170            t + C_5 * dt,
171            &(&k[0] * (A_5_1 * dt) + &k[2] * (A_5_3 * dt) + &k[3] * (A_5_4 * dt) + y),
172        )?;
173        k[5] = function(
174            t + C_6 * dt,
175            &(&k[0] * (A_6_1 * dt) + &k[3] * (A_6_4 * dt) + &k[4] * (A_6_5 * dt) + y),
176        )?;
177        k[6] = function(
178            t + C_7 * dt,
179            &(&k[0] * (A_7_1 * dt)
180                + &k[3] * (A_7_4 * dt)
181                + &k[4] * (A_7_5 * dt)
182                + &k[5] * (A_7_6 * dt)
183                + y),
184        )?;
185        k[7] = function(
186            t + C_8 * dt,
187            &(&k[0] * (A_8_1 * dt)
188                + &k[3] * (A_8_4 * dt)
189                + &k[4] * (A_8_5 * dt)
190                + &k[5] * (A_8_6 * dt)
191                + &k[6] * (A_8_7 * dt)
192                + y),
193        )?;
194        k[8] = function(
195            t + C_9 * dt,
196            &(&k[0] * (A_9_1 * dt)
197                + &k[3] * (A_9_4 * dt)
198                + &k[4] * (A_9_5 * dt)
199                + &k[5] * (A_9_6 * dt)
200                + &k[6] * (A_9_7 * dt)
201                + &k[7] * (A_9_8 * dt)
202                + y),
203        )?;
204        k[9] = function(
205            t + C_10 * dt,
206            &(&k[0] * (A_10_1 * dt)
207                + &k[3] * (A_10_4 * dt)
208                + &k[4] * (A_10_5 * dt)
209                + &k[5] * (A_10_6 * dt)
210                + &k[6] * (A_10_7 * dt)
211                + &k[7] * (A_10_8 * dt)
212                + &k[8] * (A_10_9 * dt)
213                + y),
214        )?;
215        k[10] = function(
216            t + C_11 * dt,
217            &(&k[0] * (A_11_1 * dt)
218                + &k[3] * (A_11_4 * dt)
219                + &k[4] * (A_11_5 * dt)
220                + &k[5] * (A_11_6 * dt)
221                + &k[6] * (A_11_7 * dt)
222                + &k[7] * (A_11_8 * dt)
223                + &k[8] * (A_11_9 * dt)
224                + &k[9] * (A_11_10 * dt)
225                + y),
226        )?;
227        k[11] = function(
228            t + dt,
229            &(&k[0] * (A_12_1 * dt)
230                + &k[3] * (A_12_4 * dt)
231                + &k[4] * (A_12_5 * dt)
232                + &k[5] * (A_12_6 * dt)
233                + &k[6] * (A_12_7 * dt)
234                + &k[7] * (A_12_8 * dt)
235                + &k[8] * (A_12_9 * dt)
236                + &k[9] * (A_12_10 * dt)
237                + &k[10] * (A_12_11 * dt)
238                + y),
239        )?;
240        *y_trial = (&k[0] * B_1
241            + &k[5] * B_6
242            + &k[6] * B_7
243            + &k[7] * B_8
244            + &k[8] * B_9
245            + &k[9] * B_10
246            + &k[10] * B_11
247            + &k[11] * B_12)
248            * *dt
249            + y;
250        k[12] = function(
251            t + dt,
252            &(&k[0] * (A_13_1 * dt)
253                + &k[3] * (A_13_4 * dt)
254                + &k[4] * (A_13_5 * dt)
255                + &k[5] * (A_13_6 * dt)
256                + &k[6] * (A_13_7 * dt)
257                + &k[7] * (A_13_8 * dt)
258                + &k[8] * (A_13_9 * dt)
259                + &k[9] * (A_13_10 * dt)
260                + y),
261        )?;
262        Ok(((&k[0] * D_1
263            + &k[5] * D_6
264            + &k[6] * D_7
265            + &k[7] * D_8
266            + &k[8] * D_9
267            + &k[9] * D_10
268            + &k[10] * D_11
269            + &k[11] * D_12
270            + &k[12] * D_13)
271            * *dt)
272            .norm_inf())
273    }
274    fn step(
275        &self,
276        mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
277        y: &mut Y,
278        t: &mut Scalar,
279        y_sol: &mut U,
280        t_sol: &mut Vector,
281        dydt_sol: &mut U,
282        dt: &mut Scalar,
283        _k: &mut [Y],
284        y_trial: &Y,
285        e: &Scalar,
286    ) -> Result<(), String> {
287        if e < &self.abs_tol || e / y_trial.norm_inf() < self.rel_tol {
288            *t += *dt;
289            *y = y_trial.clone();
290            t_sol.push(*t);
291            y_sol.push(y.clone());
292            dydt_sol.push(function(*t, y)?);
293        }
294        if e > &0.0 {
295            *dt *= self.dt_beta * (self.abs_tol / e).powf(1.0 / self.dt_expn)
296        }
297        Ok(())
298    }
299}
300
301impl<Y, U> InterpolateSolution<Y, U> for Verner8
302where
303    Y: Tensor,
304    for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
305    U: TensorVec<Item = Y>,
306{
307    fn interpolate(
308        &self,
309        time: &Vector,
310        tp: &Vector,
311        yp: &U,
312        mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
313    ) -> Result<(U, U), IntegrationError> {
314        let mut dt;
315        let mut i;
316        let mut k_1;
317        let mut k_2;
318        let mut k_3;
319        let mut k_4;
320        let mut k_5;
321        let mut k_6;
322        let mut k_7;
323        let mut k_8;
324        let mut k_9;
325        let mut k_10;
326        let mut k_11;
327        let mut k_12;
328        let mut t;
329        let mut y;
330        let mut y_int = U::new();
331        let mut dydt_int = U::new();
332        let mut y_trial;
333        for time_k in time.iter() {
334            i = tp.iter().position(|tp_i| tp_i >= time_k).unwrap();
335            if time_k == &tp[i] {
336                t = tp[i];
337                y_trial = yp[i].clone();
338                dt = 0.0;
339            } else {
340                t = tp[i - 1];
341                y = yp[i - 1].clone();
342                dt = time_k - t;
343                k_1 = function(t, &y)?;
344                k_2 = function(t + C_2 * dt, &(&k_1 * (A_2_1 * dt) + &y))?;
345                k_3 = function(
346                    t + C_3 * dt,
347                    &(&k_1 * (A_3_1 * dt) + &k_2 * (A_3_2 * dt) + &y),
348                )?;
349                k_4 = function(
350                    t + C_4 * dt,
351                    &(&k_1 * (A_4_1 * dt) + &k_3 * (A_4_3 * dt) + &y),
352                )?;
353                k_5 = function(
354                    t + C_5 * dt,
355                    &(&k_1 * (A_5_1 * dt) + &k_3 * (A_5_3 * dt) + &k_4 * (A_5_4 * dt) + &y),
356                )?;
357                k_6 = function(
358                    t + C_6 * dt,
359                    &(&k_1 * (A_6_1 * dt) + &k_4 * (A_6_4 * dt) + &k_5 * (A_6_5 * dt) + &y),
360                )?;
361                k_7 = function(
362                    t + C_7 * dt,
363                    &(&k_1 * (A_7_1 * dt)
364                        + &k_4 * (A_7_4 * dt)
365                        + &k_5 * (A_7_5 * dt)
366                        + &k_6 * (A_7_6 * dt)
367                        + &y),
368                )?;
369                k_8 = function(
370                    t + C_8 * dt,
371                    &(&k_1 * (A_8_1 * dt)
372                        + &k_4 * (A_8_4 * dt)
373                        + &k_5 * (A_8_5 * dt)
374                        + &k_6 * (A_8_6 * dt)
375                        + &k_7 * (A_8_7 * dt)
376                        + &y),
377                )?;
378                k_9 = function(
379                    t + C_9 * dt,
380                    &(&k_1 * (A_9_1 * dt)
381                        + &k_4 * (A_9_4 * dt)
382                        + &k_5 * (A_9_5 * dt)
383                        + &k_6 * (A_9_6 * dt)
384                        + &k_7 * (A_9_7 * dt)
385                        + &k_8 * (A_9_8 * dt)
386                        + &y),
387                )?;
388                k_10 = function(
389                    t + C_10 * dt,
390                    &(&k_1 * (A_10_1 * dt)
391                        + &k_4 * (A_10_4 * dt)
392                        + &k_5 * (A_10_5 * dt)
393                        + &k_6 * (A_10_6 * dt)
394                        + &k_7 * (A_10_7 * dt)
395                        + &k_8 * (A_10_8 * dt)
396                        + &k_9 * (A_10_9 * dt)
397                        + &y),
398                )?;
399                k_11 = function(
400                    t + C_11 * dt,
401                    &(&k_1 * (A_11_1 * dt)
402                        + &k_4 * (A_11_4 * dt)
403                        + &k_5 * (A_11_5 * dt)
404                        + &k_6 * (A_11_6 * dt)
405                        + &k_7 * (A_11_7 * dt)
406                        + &k_8 * (A_11_8 * dt)
407                        + &k_9 * (A_11_9 * dt)
408                        + &k_10 * (A_11_10 * dt)
409                        + &y),
410                )?;
411                k_12 = function(
412                    t + dt,
413                    &(&k_1 * (A_12_1 * dt)
414                        + &k_4 * (A_12_4 * dt)
415                        + &k_5 * (A_12_5 * dt)
416                        + &k_6 * (A_12_6 * dt)
417                        + &k_7 * (A_12_7 * dt)
418                        + &k_8 * (A_12_8 * dt)
419                        + &k_9 * (A_12_9 * dt)
420                        + &k_10 * (A_12_10 * dt)
421                        + &k_11 * (A_12_11 * dt)
422                        + &y),
423                )?;
424                y_trial = (&k_1 * B_1
425                    + &k_6 * B_6
426                    + &k_7 * B_7
427                    + &k_8 * B_8
428                    + &k_9 * B_9
429                    + &k_10 * B_10
430                    + &k_11 * B_11
431                    + &k_12 * B_12)
432                    * dt
433                    + &y;
434            }
435            dydt_int.push(function(t + dt, &y_trial)?);
436            y_int.push(y_trial);
437        }
438        Ok((y_int, dydt_int))
439    }
440}