conspire/math/integrate/ode/implicit/backward_euler/
mod.rs

1#[cfg(test)]
2mod test;
3
4use crate::math::{
5    Scalar, Tensor, TensorArray, TensorVec,
6    integrate::{
7        FixedStep, ImplicitFirstOrder, ImplicitZerothOrder, IntegrationError, OdeIntegrator,
8    },
9};
10use std::{
11    fmt::Debug,
12    ops::{Mul, Sub},
13};
14
15#[doc = include_str!("doc.md")]
16#[derive(Debug, Default)]
17pub struct BackwardEuler {
18    /// Fixed value for the time step.
19    dt: Scalar,
20}
21
22impl<Y, U> OdeIntegrator<Y, U> for BackwardEuler
23where
24    Y: Tensor,
25    U: TensorVec<Item = Y>,
26{
27}
28
29impl FixedStep for BackwardEuler {
30    fn dt(&self) -> Scalar {
31        self.dt
32    }
33}
34
35impl<Y, U> ImplicitZerothOrder<Y, U> for BackwardEuler
36where
37    Y: Tensor,
38    for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
39    U: TensorVec<Item = Y>,
40{
41    fn residual(
42        &self,
43        mut function: impl FnMut(Scalar, &Y) -> Result<Y, IntegrationError>,
44        _t: Scalar,
45        y: &Y,
46        t_trial: Scalar,
47        y_trial: &Y,
48        dt: Scalar,
49    ) -> Result<Y, String> {
50        Ok(y_trial - y - function(t_trial, y_trial)? * dt)
51    }
52}
53
54impl<Y, J, U> ImplicitFirstOrder<Y, J, U> for BackwardEuler
55where
56    Y: Tensor,
57    for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
58    J: Tensor + TensorArray,
59    U: TensorVec<Item = Y>,
60{
61    fn hessian(
62        &self,
63        mut jacobian: impl FnMut(Scalar, &Y) -> Result<J, IntegrationError>,
64        _t: Scalar,
65        _y: &Y,
66        t_trial: Scalar,
67        y_trial: &Y,
68        dt: Scalar,
69    ) -> Result<J, String> {
70        Ok(J::identity() - jacobian(t_trial, y_trial)? * dt)
71    }
72}