SolverSensi

Struct SolverSensi 

Source
pub struct SolverSensi<UserData, F, FS, const N: usize, const N_SENSI: usize> { /* private fields */ }
Expand description

The ODE solver with sensitivities.

§Type Arguments

  • F is the type of the right-hand side function

  • FS is the type of the sensitivities right-hand side function

  • UserData is the type of the supplementary arguments for the right-hand-side. If unused, should be ().

  • N is the “problem size”, that is the dimension of the state space.

  • N_SENSI is the number of sensitivities computed

Implementations§

Source§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> Solver<UserData, F, FS, N, N_SENSI>
where F: Fn(Realtype, &[Realtype; N], &mut [Realtype; N], &UserData) -> RhsResult, FS: Fn(Realtype, &[Realtype; N], &[Realtype; N], [&[Realtype; N]; N_SENSI], [&mut [Realtype; N]; N_SENSI], &UserData) -> RhsResult,

Source

pub fn new( method: LinearMultistepMethod, f: F, f_sens: FS, t0: Realtype, y0: &[Realtype; N], y_s0: &[[Realtype; N]; N_SENSI], rtol: Realtype, atol: AbsTolerance<N>, atol_sens: SensiAbsTolerance<N, N_SENSI>, user_data: UserData, ) -> Result<Self>

Creates a new solver.

Examples found in repository?
examples/oscillator_sensi.rs (lines 34-45)
3fn main() {
4    let y0 = [0., 1.];
5    //define the right-hand-side
6    fn f(_t: Realtype, y: &[Realtype; 2], ydot: &mut [Realtype; 2], k: &Realtype) -> RhsResult {
7        *ydot = [y[1], -y[0] * k];
8        RhsResult::Ok
9    }
10    //define the sensitivity function for the right hand side
11    fn fs(
12        _t: Realtype,
13        y: &[Realtype; 2],
14        _ydot: &[Realtype; 2],
15        ys: [&[Realtype; 2]; N_SENSI],
16        ysdot: [&mut [Realtype; 2]; N_SENSI],
17        k: &Realtype,
18    ) -> RhsResult {
19        // Mind that when indexing sensitivities, the first index
20        // is the parameter index, and the second the state variable
21        // index
22        *ysdot[0] = [ys[0][1], -ys[0][0] * k];
23        *ysdot[1] = [ys[1][1], -ys[1][0] * k];
24        *ysdot[2] = [ys[2][1], -ys[2][0] * k - y[0]];
25        RhsResult::Ok
26    }
27
28    const N_SENSI: usize = 3;
29
30    // the sensitivities in order are d/dy0[0], d/dy0[1] and d/dk
31    let ys0 = [[1., 0.], [0., 1.], [0., 0.]];
32
33    //initialize the solver
34    let mut solver = SolverSensi::new(
35        LinearMultistepMethod::Adams,
36        f,
37        fs,
38        0.,
39        &y0,
40        &ys0,
41        1e-4,
42        AbsTolerance::scalar(1e-4),
43        SensiAbsTolerance::scalar([1e-4; N_SENSI]),
44        1e-2,
45    )
46    .unwrap();
47    //and solve
48    let ts: Vec<_> = (1..100).collect();
49    println!("0,{},{}", y0[0], y0[1]);
50    for &t in &ts {
51        let (_tret, &[x, xdot], [&[dy0_dy00, dy1_dy00], &[dy0_dy01, dy1_dy01], &[dy0_dk, dy1_dk]]) =
52            solver.step(t as _, StepKind::Normal).unwrap();
53        println!(
54            "{},{},{},{},{},{},{},{},{}",
55            t, x, xdot, dy0_dy00, dy1_dy00, dy0_dy01, dy1_dy01, dy0_dk, dy1_dk
56        );
57    }
58}
Source

pub fn step( &mut self, tout: Realtype, step_kind: StepKind, ) -> Result<(Realtype, &[Realtype; N], [&[Realtype; N]; N_SENSI])>

Takes a step according to step_kind (see StepKind).

Returns a tuple (t_out,&y(t_out),[&dy_dp(tout)]) where t_out is the time reached by the solver as dictated by step_kind, y(t_out) is an array of the state variables at that time, and the i-th dy_dp(tout) is an array of the sensitivities of all variables with respect to parameter i.

Examples found in repository?
examples/oscillator_sensi.rs (line 52)
3fn main() {
4    let y0 = [0., 1.];
5    //define the right-hand-side
6    fn f(_t: Realtype, y: &[Realtype; 2], ydot: &mut [Realtype; 2], k: &Realtype) -> RhsResult {
7        *ydot = [y[1], -y[0] * k];
8        RhsResult::Ok
9    }
10    //define the sensitivity function for the right hand side
11    fn fs(
12        _t: Realtype,
13        y: &[Realtype; 2],
14        _ydot: &[Realtype; 2],
15        ys: [&[Realtype; 2]; N_SENSI],
16        ysdot: [&mut [Realtype; 2]; N_SENSI],
17        k: &Realtype,
18    ) -> RhsResult {
19        // Mind that when indexing sensitivities, the first index
20        // is the parameter index, and the second the state variable
21        // index
22        *ysdot[0] = [ys[0][1], -ys[0][0] * k];
23        *ysdot[1] = [ys[1][1], -ys[1][0] * k];
24        *ysdot[2] = [ys[2][1], -ys[2][0] * k - y[0]];
25        RhsResult::Ok
26    }
27
28    const N_SENSI: usize = 3;
29
30    // the sensitivities in order are d/dy0[0], d/dy0[1] and d/dk
31    let ys0 = [[1., 0.], [0., 1.], [0., 0.]];
32
33    //initialize the solver
34    let mut solver = SolverSensi::new(
35        LinearMultistepMethod::Adams,
36        f,
37        fs,
38        0.,
39        &y0,
40        &ys0,
41        1e-4,
42        AbsTolerance::scalar(1e-4),
43        SensiAbsTolerance::scalar([1e-4; N_SENSI]),
44        1e-2,
45    )
46    .unwrap();
47    //and solve
48    let ts: Vec<_> = (1..100).collect();
49    println!("0,{},{}", y0[0], y0[1]);
50    for &t in &ts {
51        let (_tret, &[x, xdot], [&[dy0_dy00, dy1_dy00], &[dy0_dy01, dy1_dy01], &[dy0_dk, dy1_dk]]) =
52            solver.step(t as _, StepKind::Normal).unwrap();
53        println!(
54            "{},{},{},{},{},{},{},{},{}",
55            t, x, xdot, dy0_dy00, dy1_dy00, dy0_dy01, dy1_dy01, dy0_dk, dy1_dk
56        );
57    }
58}

Trait Implementations§

Source§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> Drop for Solver<UserData, F, FS, N, N_SENSI>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> Freeze for Solver<UserData, F, FS, N, N_SENSI>

§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> RefUnwindSafe for Solver<UserData, F, FS, N, N_SENSI>
where UserData: RefUnwindSafe, F: RefUnwindSafe, FS: RefUnwindSafe,

§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> !Send for Solver<UserData, F, FS, N, N_SENSI>

§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> !Sync for Solver<UserData, F, FS, N, N_SENSI>

§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> Unpin for Solver<UserData, F, FS, N, N_SENSI>

§

impl<UserData, F, FS, const N: usize, const N_SENSI: usize> UnwindSafe for Solver<UserData, F, FS, N, N_SENSI>
where UserData: UnwindSafe, F: UnwindSafe, FS: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.