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