conspire/math/integrate/ode/explicit/variable_step/bogacki_shampine/
mod.rs1#[cfg(test)]
2mod test;
3
4use crate::math::Norm;
5use crate::math::{
6 Scalar, Tensor, TensorVec, Vector,
7 integrate::{
8 Explicit, FreeInterpolant, IntegrationError, OdeIntegrator, VariableStep,
9 VariableStepExplicit, VariableStepExplicitFirstSameAsLast,
10 },
11 interpolate::InterpolateSolution,
12};
13use crate::{ABS_TOL, REL_TOL};
14use std::ops::{Mul, Sub};
15
16#[doc = include_str!("doc.md")]
17#[derive(Debug)]
18pub struct BogackiShampine {
19 pub abs_tol: Scalar,
21 pub rel_tol: Scalar,
23 pub dt_beta: Scalar,
25 pub dt_expn: Scalar,
27 pub dt_cut: Scalar,
29 pub dt_min: Scalar,
31 pub norm: Norm,
33}
34
35impl Default for BogackiShampine {
36 fn default() -> Self {
37 Self {
38 abs_tol: ABS_TOL,
39 rel_tol: REL_TOL,
40 dt_beta: 0.9,
41 dt_expn: 3.0,
42 dt_cut: 0.5,
43 dt_min: ABS_TOL,
44 norm: Norm::Chebyshev,
45 }
46 }
47}
48
49impl<Y, U> OdeIntegrator<Y, U> for BogackiShampine
50where
51 Y: Tensor,
52 U: TensorVec<Item = Y>,
53{
54}
55
56impl VariableStep for BogackiShampine {
57 fn abs_tol(&self) -> Scalar {
58 self.abs_tol
59 }
60 fn rel_tol(&self) -> Scalar {
61 self.rel_tol
62 }
63 fn dt_beta(&self) -> Scalar {
64 self.dt_beta
65 }
66 fn dt_expn(&self) -> Scalar {
67 self.dt_expn
68 }
69 fn dt_cut(&self) -> Scalar {
70 self.dt_cut
71 }
72 fn dt_min(&self) -> Scalar {
73 self.dt_min
74 }
75 fn norm(&self) -> &Norm {
76 &self.norm
77 }
78}
79
80impl<Y, U> Explicit<Y, U> for BogackiShampine
81where
82 Y: Tensor,
83 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
84 U: TensorVec<Item = Y>,
85{
86 const SLOPES: usize = 4;
87 fn integrate(
88 &self,
89 function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
90 time: &[Scalar],
91 initial_condition: Y,
92 ) -> Result<(Vector, U, U), IntegrationError> {
93 self.integrate_variable_step(function, time, initial_condition)
94 }
95}
96
97impl<Y, U> VariableStepExplicit<Y, U> for BogackiShampine
98where
99 Self: Explicit<Y, U>,
100 Y: Tensor,
101 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
102 U: TensorVec<Item = Y>,
103{
104 fn error(&self, dt: Scalar, k: &[Y]) -> Result<Scalar, String> {
105 Ok(self
106 .norm
107 .apply(&((&k[0] * -5.0 + &k[1] * 6.0 + &k[2] * 8.0 + &k[3] * -9.0) * (dt / 72.0))))
108 }
109 fn slopes(
110 mut function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
111 y: &Y,
112 t: Scalar,
113 dt: Scalar,
114 k: &mut [Y],
115 y_trial: &mut Y,
116 ) -> Result<(), String> {
117 *y_trial = &k[0] * (0.5 * dt) + y;
118 k[1] = function(t + 0.5 * dt, y_trial)?;
119 *y_trial = &k[1] * (0.75 * dt) + y;
120 k[2] = function(t + 0.75 * dt, y_trial)?;
121 *y_trial = (&k[0] * 2.0 + &k[1] * 3.0 + &k[2] * 4.0) * (dt / 9.0) + y;
122 Ok(())
123 }
124 fn slopes_and_error(
125 &self,
126 function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
127 y: &Y,
128 t: Scalar,
129 dt: Scalar,
130 k: &mut [Y],
131 y_trial: &mut Y,
132 ) -> Result<Scalar, String> {
133 self.slopes_and_error_fsal(function, y, t, dt, k, y_trial)
134 }
135 fn step(
136 &self,
137 _function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
138 y: &mut Y,
139 t: &mut Scalar,
140 y_sol: &mut U,
141 t_sol: &mut Vector,
142 dydt_sol: &mut U,
143 k_sol: &mut Vec<U>,
144 dt: &mut Scalar,
145 k: &mut [Y],
146 y_trial: &Y,
147 e: Scalar,
148 ) -> Result<(), String> {
149 let dt_0 = *dt;
150 self.step_fsal(y, t, y_sol, t_sol, dydt_sol, k_sol, dt, k, y_trial, e)?;
151 if e > 0.0 {
152 *dt = dt_0;
153 *dt *= self.dt_beta() * (self.abs_tol() / e).powf(1.0 / self.dt_expn())
154 }
155 Ok(()) }
157}
158
159impl<Y, U> VariableStepExplicitFirstSameAsLast<Y, U> for BogackiShampine
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}
166
167impl<Y, U> FreeInterpolant<Y, U> for BogackiShampine
168where
169 Y: Tensor,
170 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
171 U: TensorVec<Item = Y>,
172{
173}
174
175impl<Y, U> InterpolateSolution<Y, U> for BogackiShampine
176where
177 Y: Tensor,
178 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
179 U: TensorVec<Item = Y>,
180{
181 fn interpolate(
182 &self,
183 time: &Vector,
184 tp: &Vector,
185 yp: &U,
186 dydtp: &U,
187 _k_sol: &[U],
188 _function: impl FnMut(Scalar, &Y) -> Result<Y, String>,
189 ) -> Result<(U, U), IntegrationError> {
190 Ok(Self::interpolate_free(time, tp, yp, dydtp))
191 }
192}