conspire/math/integrate/verner_8/
mod.rs1#[cfg(test)]
2mod test;
3
4use super::{
5 super::{Scalar, Tensor, TensorVec, Vector, interpolate::InterpolateSolution},
6 Explicit, IntegrationError, OdeSolver,
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#[doc = include_str!("doc.md")]
101#[derive(Debug)]
102pub struct Verner8 {
103 pub abs_tol: Scalar,
105 pub rel_tol: Scalar,
107 pub dt_beta: Scalar,
109 pub dt_expn: Scalar,
111 pub dt_cut: Scalar,
113 pub dt_min: Scalar,
115}
116
117impl Default for Verner8 {
118 fn default() -> Self {
119 Self {
120 abs_tol: ABS_TOL,
121 rel_tol: REL_TOL,
122 dt_beta: 0.9,
123 dt_expn: 8.0,
124 dt_cut: 0.5,
125 dt_min: ABS_TOL,
126 }
127 }
128}
129
130impl<Y, U> OdeSolver<Y, U> for Verner8
131where
132 Y: Tensor,
133 U: TensorVec<Item = Y>,
134{
135 fn abs_tol(&self) -> Scalar {
136 self.abs_tol
137 }
138 fn dt_cut(&self) -> Scalar {
139 self.dt_cut
140 }
141 fn dt_min(&self) -> Scalar {
142 self.dt_min
143 }
144}
145
146impl<Y, U> Explicit<Y, U> for Verner8
147where
148 Self: OdeSolver<Y, U>,
149 Y: Tensor,
150 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
151 U: TensorVec<Item = Y>,
152{
153 const SLOPES: usize = 13;
154 fn dt_beta(&self) -> Scalar {
155 self.dt_beta
156 }
157 fn dt_expn(&self) -> Scalar {
158 self.dt_expn
159 }
160 fn slopes(
161 &self,
162 mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
163 y: &Y,
164 t: Scalar,
165 dt: Scalar,
166 k: &mut [Y],
167 y_trial: &mut Y,
168 ) -> Result<Scalar, String> {
169 k[0] = function(t, y)?;
170 *y_trial = &k[0] * (A_2_1 * dt) + y;
171 k[1] = function(t + C_2 * dt, y_trial)?;
172 *y_trial = &k[0] * (A_3_1 * dt) + &k[1] * (A_3_2 * dt) + y;
173 k[2] = function(t + C_3 * dt, y_trial)?;
174 *y_trial = &k[0] * (A_4_1 * dt) + &k[2] * (A_4_3 * dt) + y;
175 k[3] = function(t + C_4 * dt, y_trial)?;
176 *y_trial = &k[0] * (A_5_1 * dt) + &k[2] * (A_5_3 * dt) + &k[3] * (A_5_4 * dt) + y;
177 k[4] = function(t + C_5 * dt, y_trial)?;
178 *y_trial = &k[0] * (A_6_1 * dt) + &k[3] * (A_6_4 * dt) + &k[4] * (A_6_5 * dt) + y;
179 k[5] = function(t + C_6 * dt, y_trial)?;
180 *y_trial = &k[0] * (A_7_1 * dt)
181 + &k[3] * (A_7_4 * dt)
182 + &k[4] * (A_7_5 * dt)
183 + &k[5] * (A_7_6 * dt)
184 + y;
185 k[6] = function(t + C_7 * dt, y_trial)?;
186 *y_trial = &k[0] * (A_8_1 * dt)
187 + &k[3] * (A_8_4 * dt)
188 + &k[4] * (A_8_5 * dt)
189 + &k[5] * (A_8_6 * dt)
190 + &k[6] * (A_8_7 * dt)
191 + y;
192 k[7] = function(t + C_8 * dt, y_trial)?;
193 *y_trial = &k[0] * (A_9_1 * dt)
194 + &k[3] * (A_9_4 * dt)
195 + &k[4] * (A_9_5 * dt)
196 + &k[5] * (A_9_6 * dt)
197 + &k[6] * (A_9_7 * dt)
198 + &k[7] * (A_9_8 * dt)
199 + y;
200 k[8] = function(t + C_9 * dt, y_trial)?;
201 *y_trial = &k[0] * (A_10_1 * dt)
202 + &k[3] * (A_10_4 * dt)
203 + &k[4] * (A_10_5 * dt)
204 + &k[5] * (A_10_6 * dt)
205 + &k[6] * (A_10_7 * dt)
206 + &k[7] * (A_10_8 * dt)
207 + &k[8] * (A_10_9 * dt)
208 + y;
209 k[9] = function(t + C_10 * dt, y_trial)?;
210 *y_trial = &k[0] * (A_11_1 * dt)
211 + &k[3] * (A_11_4 * dt)
212 + &k[4] * (A_11_5 * dt)
213 + &k[5] * (A_11_6 * dt)
214 + &k[6] * (A_11_7 * dt)
215 + &k[7] * (A_11_8 * dt)
216 + &k[8] * (A_11_9 * dt)
217 + &k[9] * (A_11_10 * dt)
218 + y;
219 k[10] = function(t + C_11 * dt, y_trial)?;
220 *y_trial = &k[0] * (A_12_1 * dt)
221 + &k[3] * (A_12_4 * dt)
222 + &k[4] * (A_12_5 * dt)
223 + &k[5] * (A_12_6 * dt)
224 + &k[6] * (A_12_7 * dt)
225 + &k[7] * (A_12_8 * dt)
226 + &k[8] * (A_12_9 * dt)
227 + &k[9] * (A_12_10 * dt)
228 + &k[10] * (A_12_11 * dt)
229 + y;
230 k[11] = function(t + dt, y_trial)?;
231 *y_trial = &k[0] * (A_13_1 * dt)
232 + &k[3] * (A_13_4 * dt)
233 + &k[4] * (A_13_5 * dt)
234 + &k[5] * (A_13_6 * dt)
235 + &k[6] * (A_13_7 * dt)
236 + &k[7] * (A_13_8 * dt)
237 + &k[8] * (A_13_9 * dt)
238 + &k[9] * (A_13_10 * dt)
239 + y;
240 k[12] = function(t + dt, y_trial)?;
241 *y_trial = (&k[0] * B_1
242 + &k[5] * B_6
243 + &k[6] * B_7
244 + &k[7] * B_8
245 + &k[8] * B_9
246 + &k[9] * B_10
247 + &k[10] * B_11
248 + &k[11] * B_12)
249 * dt
250 + y;
251 Ok(((&k[0] * D_1
252 + &k[5] * D_6
253 + &k[6] * D_7
254 + &k[7] * D_8
255 + &k[8] * D_9
256 + &k[9] * D_10
257 + &k[10] * D_11
258 + &k[11] * D_12
259 + &k[12] * D_13)
260 * dt)
261 .norm_inf())
262 }
263 fn step(
264 &self,
265 mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
266 y: &mut Y,
267 t: &mut Scalar,
268 y_sol: &mut U,
269 t_sol: &mut Vector,
270 dydt_sol: &mut U,
271 dt: &mut Scalar,
272 _k: &mut [Y],
273 y_trial: &Y,
274 e: Scalar,
275 ) -> Result<(), String> {
276 if e < self.abs_tol || e / y_trial.norm_inf() < self.rel_tol {
277 *t += *dt;
278 *y = y_trial.clone();
279 t_sol.push(*t);
280 y_sol.push(y.clone());
281 dydt_sol.push(function(*t, y)?);
282 }
283 self.time_step(e, dt);
284 Ok(())
285 }
286}
287
288impl<Y, U> InterpolateSolution<Y, U> for Verner8
289where
290 Y: Tensor,
291 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
292 U: TensorVec<Item = Y>,
293{
294 fn interpolate(
295 &self,
296 time: &Vector,
297 tp: &Vector,
298 yp: &U,
299 mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
300 ) -> Result<(U, U), IntegrationError> {
301 let mut dt;
302 let mut i;
303 let mut k_1;
304 let mut k_2;
305 let mut k_3;
306 let mut k_4;
307 let mut k_5;
308 let mut k_6;
309 let mut k_7;
310 let mut k_8;
311 let mut k_9;
312 let mut k_10;
313 let mut k_11;
314 let mut k_12;
315 let mut t;
316 let mut y;
317 let mut y_int = U::new();
318 let mut dydt_int = U::new();
319 let mut y_trial;
320 for time_k in time.iter() {
321 i = tp.iter().position(|tp_i| tp_i >= time_k).unwrap();
322 if time_k == &tp[i] {
323 t = tp[i];
324 y_trial = yp[i].clone();
325 dt = 0.0;
326 } else {
327 t = tp[i - 1];
328 y = yp[i - 1].clone();
329 dt = time_k - t;
330 k_1 = function(t, &y)?;
331 y_trial = &k_1 * (A_2_1 * dt) + &y;
332 k_2 = function(t + C_2 * dt, &y_trial)?;
333 y_trial = &k_1 * (A_3_1 * dt) + &k_2 * (A_3_2 * dt) + &y;
334 k_3 = function(t + C_3 * dt, &y_trial)?;
335 y_trial = &k_1 * (A_4_1 * dt) + &k_3 * (A_4_3 * dt) + &y;
336 k_4 = function(t + C_4 * dt, &y_trial)?;
337 y_trial = &k_1 * (A_5_1 * dt) + &k_3 * (A_5_3 * dt) + &k_4 * (A_5_4 * dt) + &y;
338 k_5 = function(t + C_5 * dt, &y_trial)?;
339 y_trial = &k_1 * (A_6_1 * dt) + &k_4 * (A_6_4 * dt) + &k_5 * (A_6_5 * dt) + &y;
340 k_6 = function(t + C_6 * dt, &y_trial)?;
341 y_trial = &k_1 * (A_7_1 * dt)
342 + &k_4 * (A_7_4 * dt)
343 + &k_5 * (A_7_5 * dt)
344 + &k_6 * (A_7_6 * dt)
345 + &y;
346 k_7 = function(t + C_7 * dt, &y_trial)?;
347 y_trial = &k_1 * (A_8_1 * dt)
348 + &k_4 * (A_8_4 * dt)
349 + &k_5 * (A_8_5 * dt)
350 + &k_6 * (A_8_6 * dt)
351 + &k_7 * (A_8_7 * dt)
352 + &y;
353 k_8 = function(t + C_8 * dt, &y_trial)?;
354 y_trial = &k_1 * (A_9_1 * dt)
355 + &k_4 * (A_9_4 * dt)
356 + &k_5 * (A_9_5 * dt)
357 + &k_6 * (A_9_6 * dt)
358 + &k_7 * (A_9_7 * dt)
359 + &k_8 * (A_9_8 * dt)
360 + &y;
361 k_9 = function(t + C_9 * dt, &y_trial)?;
362 y_trial = &k_1 * (A_10_1 * dt)
363 + &k_4 * (A_10_4 * dt)
364 + &k_5 * (A_10_5 * dt)
365 + &k_6 * (A_10_6 * dt)
366 + &k_7 * (A_10_7 * dt)
367 + &k_8 * (A_10_8 * dt)
368 + &k_9 * (A_10_9 * dt)
369 + &y;
370 k_10 = function(t + C_10 * dt, &y_trial)?;
371 y_trial = &k_1 * (A_11_1 * dt)
372 + &k_4 * (A_11_4 * dt)
373 + &k_5 * (A_11_5 * dt)
374 + &k_6 * (A_11_6 * dt)
375 + &k_7 * (A_11_7 * dt)
376 + &k_8 * (A_11_8 * dt)
377 + &k_9 * (A_11_9 * dt)
378 + &k_10 * (A_11_10 * dt)
379 + &y;
380 k_11 = function(t + C_11 * dt, &y_trial)?;
381 y_trial = &k_1 * (A_12_1 * dt)
382 + &k_4 * (A_12_4 * dt)
383 + &k_5 * (A_12_5 * dt)
384 + &k_6 * (A_12_6 * dt)
385 + &k_7 * (A_12_7 * dt)
386 + &k_8 * (A_12_8 * dt)
387 + &k_9 * (A_12_9 * dt)
388 + &k_10 * (A_12_10 * dt)
389 + &k_11 * (A_12_11 * dt)
390 + &y;
391 k_12 = function(t + dt, &y_trial)?;
392 y_trial = (&k_1 * B_1
393 + &k_6 * B_6
394 + &k_7 * B_7
395 + &k_8 * B_8
396 + &k_9 * B_9
397 + &k_10 * B_10
398 + &k_11 * B_11
399 + &k_12 * B_12)
400 * dt
401 + &y;
402 }
403 dydt_int.push(function(t + dt, &y_trial)?);
404 y_int.push(y_trial);
405 }
406 Ok((y_int, dydt_int))
407 }
408}