numeric_algs/integration/
rk8.rs1use super::{Integrator, StepSize};
2use crate::traits::State;
3
4pub struct RK8Integrator {
7 default_step: f64,
8}
9
10impl RK8Integrator {
11 pub fn new(step_size: f64) -> Self {
12 RK8Integrator {
13 default_step: step_size,
14 }
15 }
16
17 pub fn set_default_step(&mut self, step: f64) {
18 self.default_step = step;
19 }
20}
21
22impl<S: State> Integrator<S> for RK8Integrator {
23 fn propagate_in_place<D>(&mut self, start: &mut S, diff_eq: D, step_size: StepSize)
24 where
25 D: Fn(&S) -> S::Derivative,
26 {
27 let h = match step_size {
28 StepSize::UseDefault => self.default_step,
29 StepSize::Step(x) => x,
30 };
31
32 let mut f = vec![diff_eq(start)];
33
34 let a: [(f64, f64); 9] = [
35 (4.0, 27.0),
36 (2.0, 9.0),
37 (1.0, 3.0),
38 (1.0, 2.0),
39 (2.0, 3.0),
40 (1.0, 6.0),
41 (1.0, 1.0),
42 (5.0, 6.0),
43 (1.0, 1.0),
44 ];
45
46 let b: [(f64, Vec<f64>); 9] = [
47 (1.0, vec![1.0]),
48 (4.0, vec![1.0, 3.0]),
49 (4.0, vec![1.0, 0.0, 3.0]),
50 (4.0, vec![1.0, 0.0, 0.0, 3.0]),
51 (36.0, vec![13.0, 0.0, -27.0, 42.0, 8.0]),
52 (720.0, vec![389.0, 0.0, -54.0, 966.0, -824.0, 243.0]),
53 (20.0, vec![-231.0, 0.0, 81.0, -1164.0, 656.0, -122.0, 800.0]),
54 (
55 240.0,
56 vec![-127.0, 0.0, 18.0, -678.0, 456.0, -9.0, 576.0, 4.0],
57 ),
58 (
59 820.0,
60 vec![
61 1481.0, 0.0, -81.0, 7104.0, -3376.0, 72.0, -5040.0, -60.0, 720.0,
62 ],
63 ),
64 ];
65
66 for i in 0..9 {
67 assert_eq!(f.len(), b[i].1.len());
68 let k = f
69 .iter()
70 .zip(b[i].1.iter())
71 .map(|(f, b)| f.clone() * *b)
72 .reduce(|v1, v2| v1 + v2)
73 .unwrap()
74 / b[i].0;
75 let a = a[i];
76 let new_f = diff_eq(&start.shift(&k, h * a.0 / a.1));
77 f.push(new_f);
78 }
79
80 let c: [f64; 10] = [41.0, 0.0, 0.0, 27.0, 272.0, 27.0, 216.0, 0.0, 216.0, 41.0];
81
82 assert_eq!(f.len(), 10);
83
84 let shift = f
85 .iter()
86 .zip(c.iter())
87 .map(|(f, c)| f.clone() * *c)
88 .reduce(|v1, v2| v1 + v2)
89 .unwrap()
90 / 840.0;
91
92 start.shift_in_place(&shift, h);
93 }
94}