conspire/math/integrate/ode/explicit/variable_step/verner_8/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::math::{
5 Scalar, Tensor, TensorVec, Vector,
6 integrate::{Explicit, IntegrationError, OdeIntegrator, VariableStep, VariableStepExplicit},
7 interpolate::InterpolateSolution,
8};
9use crate::{ABS_TOL, REL_TOL};
10use std::ops::{Mul, Sub};
11
12pub const C_2: Scalar = 0.05;
13pub const C_3: Scalar = 0.1065625;
14pub const C_4: Scalar = 0.15984375;
15pub const C_5: Scalar = 0.39;
16pub const C_6: Scalar = 0.465;
17pub const C_7: Scalar = 0.155;
18pub const C_8: Scalar = 0.943;
19pub const C_9: Scalar = 0.901802041735857;
20pub const C_10: Scalar = 0.909;
21pub const C_11: Scalar = 0.94;
22
23pub const A_2_1: Scalar = 0.05;
24pub const A_3_1: Scalar = -0.0069931640625;
25pub const A_3_2: Scalar = 0.1135556640625;
26pub const A_4_1: Scalar = 0.0399609375;
27pub const A_4_3: Scalar = 0.1198828125;
28pub const A_5_1: Scalar = 0.36139756280045754;
29pub const A_5_3: Scalar = -1.3415240667004928;
30pub const A_5_4: Scalar = 1.3701265039000352;
31pub const A_6_1: Scalar = 0.049047202797202795;
32pub const A_6_4: Scalar = 0.23509720422144048;
33pub const A_6_5: Scalar = 0.18085559298135673;
34pub const A_7_1: Scalar = 0.06169289044289044;
35pub const A_7_4: Scalar = 0.11236568314640277;
36pub const A_7_5: Scalar = -0.03885046071451367;
37pub const A_7_6: Scalar = 0.01979188712522046;
38pub const A_8_1: Scalar = -1.767630240222327;
39pub const A_8_4: Scalar = -62.5;
40pub const A_8_5: Scalar = -6.061889377376669;
41pub const A_8_6: Scalar = 5.6508231982227635;
42pub const A_8_7: Scalar = 65.62169641937624;
43pub const A_9_1: Scalar = -1.1809450665549708;
44pub const A_9_4: Scalar = -41.50473441114321;
45pub const A_9_5: Scalar = -4.434438319103725;
46pub const A_9_6: Scalar = 4.260408188586133;
47pub const A_9_7: Scalar = 43.75364022446172;
48pub const A_9_8: Scalar = 0.00787142548991231;
49pub const A_10_1: Scalar = -1.2814059994414884;
50pub const A_10_4: Scalar = -45.047139960139866;
51pub const A_10_5: Scalar = -4.731362069449576;
52pub const A_10_6: Scalar = 4.514967016593808;
53pub const A_10_7: Scalar = 47.44909557172985;
54pub const A_10_8: Scalar = 0.01059228297111661;
55pub const A_10_9: Scalar = -0.0057468422638446166;
56pub const A_11_1: Scalar = -1.7244701342624853;
57pub const A_11_4: Scalar = -60.92349008483054;
58pub const A_11_5: Scalar = -5.951518376222392;
59pub const A_11_6: Scalar = 5.556523730698456;
60pub const A_11_7: Scalar = 63.98301198033305;
61pub const A_11_8: Scalar = 0.014642028250414961;
62pub const A_11_9: Scalar = 0.06460408772358203;
63pub const A_11_10: Scalar = -0.0793032316900888;
64pub const A_12_1: Scalar = -3.301622667747079;
65pub const A_12_4: Scalar = -118.01127235975251;
66pub const A_12_5: Scalar = -10.141422388456112;
67pub const A_12_6: Scalar = 9.139311332232058;
68pub const A_12_7: Scalar = 123.37594282840426;
69pub const A_12_8: Scalar = 4.62324437887458;
70pub const A_12_9: Scalar = -3.3832777380682018;
71pub const A_12_10: Scalar = 4.527592100324618;
72pub const A_12_11: Scalar = -5.828495485811623;
73pub const A_13_1: Scalar = -3.039515033766309;
74pub const A_13_4: Scalar = -109.26086808941763;
75pub const A_13_5: Scalar = -9.290642497400293;
76pub const A_13_6: Scalar = 8.43050498176491;
77pub const A_13_7: Scalar = 114.20100103783314;
78pub const A_13_8: Scalar = -0.9637271342145479;
79pub const A_13_9: Scalar = -5.0348840888021895;
80pub const A_13_10: Scalar = 5.958130824002923;
81
82pub const B_1: Scalar = 0.04427989419007951;
83pub const B_6: Scalar = 0.3541049391724449;
84pub const B_7: Scalar = 0.24796921549564377;
85pub const B_8: Scalar = -15.694202038838085;
86pub const B_9: Scalar = 25.084064965558564;
87pub const B_10: Scalar = -31.738367786260277;
88pub const B_11: Scalar = 22.938283273988784;
89pub const B_12: Scalar = -0.2361324633071542;
90
91pub const D_1: Scalar = -0.00003272103901028138;
92pub const D_6: Scalar = -0.0005046250618777704;
93pub const D_7: Scalar = 0.0001211723589784759;
94pub const D_8: Scalar = -20.142336771313868;
95pub const D_9: Scalar = 5.2371785994398286;
96pub const D_10: Scalar = -8.156744408794658;
97pub const D_11: Scalar = 22.938283273988784;
98pub const D_12: Scalar = -0.2361324633071542;
99pub const D_13: Scalar = 0.36016794372897754;
100
101#[doc = include_str!("doc.md")]
102#[derive(Debug)]
103pub struct Verner8 {
104 pub abs_tol: Scalar,
106 pub rel_tol: Scalar,
108 pub dt_beta: Scalar,
110 pub dt_expn: Scalar,
112 pub dt_cut: Scalar,
114 pub dt_min: Scalar,
116}
117
118impl Default for Verner8 {
119 fn default() -> Self {
120 Self {
121 abs_tol: ABS_TOL,
122 rel_tol: REL_TOL,
123 dt_beta: 0.9,
124 dt_expn: 8.0,
125 dt_cut: 0.5,
126 dt_min: ABS_TOL,
127 }
128 }
129}
130
131impl<Y, U> OdeIntegrator<Y, U> for Verner8
132where
133 Y: Tensor,
134 U: TensorVec<Item = Y>,
135{
136}
137
138impl VariableStep for Verner8 {
139 fn abs_tol(&self) -> Scalar {
140 self.abs_tol
141 }
142 fn rel_tol(&self) -> Scalar {
143 self.rel_tol
144 }
145 fn dt_beta(&self) -> Scalar {
146 self.dt_beta
147 }
148 fn dt_expn(&self) -> Scalar {
149 self.dt_expn
150 }
151 fn dt_cut(&self) -> Scalar {
152 self.dt_cut
153 }
154 fn dt_min(&self) -> Scalar {
155 self.dt_min
156 }
157}
158
159impl<Y, U> Explicit<Y, U> for Verner8
160where
161 Y: Tensor,
162 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
163 U: TensorVec<Item = Y>,
164{
165 const SLOPES: usize = 13;
166 fn integrate(
167 &self,
168 function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
169 time: &[Scalar],
170 initial_condition: Y,
171 ) -> Result<(Vector, U, U), IntegrationError> {
172 self.integrate_variable_step(function, time, initial_condition)
173 }
174}
175
176impl<Y, U> VariableStepExplicit<Y, U> for Verner8
177where
178 Self: Explicit<Y, U>,
179 Y: Tensor,
180 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
181 U: TensorVec<Item = Y>,
182{
183 fn error(dt: Scalar, k: &[Y]) -> Result<Scalar, String> {
184 Ok(((&k[0] * D_1
185 + &k[5] * D_6
186 + &k[6] * D_7
187 + &k[7] * D_8
188 + &k[8] * D_9
189 + &k[9] * D_10
190 + &k[10] * D_11
191 + &k[11] * D_12
192 + &k[12] * D_13)
193 * dt)
194 .norm_inf())
195 }
196 fn slopes(
197 mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
198 y: &Y,
199 t: Scalar,
200 dt: Scalar,
201 k: &mut [Y],
202 y_trial: &mut Y,
203 ) -> Result<(), String> {
204 k[0] = function(t, y)?;
205 *y_trial = &k[0] * (A_2_1 * dt) + y;
206 k[1] = function(t + C_2 * dt, y_trial)?;
207 *y_trial = &k[0] * (A_3_1 * dt) + &k[1] * (A_3_2 * dt) + y;
208 k[2] = function(t + C_3 * dt, y_trial)?;
209 *y_trial = &k[0] * (A_4_1 * dt) + &k[2] * (A_4_3 * dt) + y;
210 k[3] = function(t + C_4 * dt, y_trial)?;
211 *y_trial = &k[0] * (A_5_1 * dt) + &k[2] * (A_5_3 * dt) + &k[3] * (A_5_4 * dt) + y;
212 k[4] = function(t + C_5 * dt, y_trial)?;
213 *y_trial = &k[0] * (A_6_1 * dt) + &k[3] * (A_6_4 * dt) + &k[4] * (A_6_5 * dt) + y;
214 k[5] = function(t + C_6 * dt, y_trial)?;
215 *y_trial = &k[0] * (A_7_1 * dt)
216 + &k[3] * (A_7_4 * dt)
217 + &k[4] * (A_7_5 * dt)
218 + &k[5] * (A_7_6 * dt)
219 + y;
220 k[6] = function(t + C_7 * dt, y_trial)?;
221 *y_trial = &k[0] * (A_8_1 * dt)
222 + &k[3] * (A_8_4 * dt)
223 + &k[4] * (A_8_5 * dt)
224 + &k[5] * (A_8_6 * dt)
225 + &k[6] * (A_8_7 * dt)
226 + y;
227 k[7] = function(t + C_8 * dt, y_trial)?;
228 *y_trial = &k[0] * (A_9_1 * dt)
229 + &k[3] * (A_9_4 * dt)
230 + &k[4] * (A_9_5 * dt)
231 + &k[5] * (A_9_6 * dt)
232 + &k[6] * (A_9_7 * dt)
233 + &k[7] * (A_9_8 * dt)
234 + y;
235 k[8] = function(t + C_9 * dt, y_trial)?;
236 *y_trial = &k[0] * (A_10_1 * dt)
237 + &k[3] * (A_10_4 * dt)
238 + &k[4] * (A_10_5 * dt)
239 + &k[5] * (A_10_6 * dt)
240 + &k[6] * (A_10_7 * dt)
241 + &k[7] * (A_10_8 * dt)
242 + &k[8] * (A_10_9 * dt)
243 + y;
244 k[9] = function(t + C_10 * dt, y_trial)?;
245 *y_trial = &k[0] * (A_11_1 * dt)
246 + &k[3] * (A_11_4 * dt)
247 + &k[4] * (A_11_5 * dt)
248 + &k[5] * (A_11_6 * dt)
249 + &k[6] * (A_11_7 * dt)
250 + &k[7] * (A_11_8 * dt)
251 + &k[8] * (A_11_9 * dt)
252 + &k[9] * (A_11_10 * dt)
253 + y;
254 k[10] = function(t + C_11 * dt, y_trial)?;
255 *y_trial = &k[0] * (A_12_1 * dt)
256 + &k[3] * (A_12_4 * dt)
257 + &k[4] * (A_12_5 * dt)
258 + &k[5] * (A_12_6 * dt)
259 + &k[6] * (A_12_7 * dt)
260 + &k[7] * (A_12_8 * dt)
261 + &k[8] * (A_12_9 * dt)
262 + &k[9] * (A_12_10 * dt)
263 + &k[10] * (A_12_11 * dt)
264 + y;
265 k[11] = function(t + dt, y_trial)?;
266 *y_trial = &k[0] * (A_13_1 * dt)
267 + &k[3] * (A_13_4 * dt)
268 + &k[4] * (A_13_5 * dt)
269 + &k[5] * (A_13_6 * dt)
270 + &k[6] * (A_13_7 * dt)
271 + &k[7] * (A_13_8 * dt)
272 + &k[8] * (A_13_9 * dt)
273 + &k[9] * (A_13_10 * dt)
274 + y;
275 if k.len() == Self::SLOPES {
276 k[12] = function(t + dt, y_trial)?;
277 }
278 *y_trial = (&k[0] * B_1
279 + &k[5] * B_6
280 + &k[6] * B_7
281 + &k[7] * B_8
282 + &k[8] * B_9
283 + &k[9] * B_10
284 + &k[10] * B_11
285 + &k[11] * B_12)
286 * dt
287 + y;
288 Ok(())
289 }
290}
291
292impl<Y, U> InterpolateSolution<Y, U> for Verner8
293where
294 Y: Tensor,
295 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
296 U: TensorVec<Item = Y>,
297{
298 fn interpolate(
299 &self,
300 time: &Vector,
301 tp: &Vector,
302 yp: &U,
303 function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
304 ) -> Result<(U, U), IntegrationError> {
305 Self::interpolate_variable_step(time, tp, yp, function)
306 }
307}