conspire/math/integrate/verner_9/
mod.rs1#[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#[derive(Debug)]
144pub struct Verner9 {
145 pub abs_tol: TensorRank0,
147 pub rel_tol: TensorRank0,
149 pub dt_beta: TensorRank0,
151 pub dt_expn: TensorRank0,
153 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}