Trait diffsol::ode_solver::method::OdeSolverMethod

source ·
pub trait OdeSolverMethod<Eqn: OdeEquations> {
    // Required methods
    fn problem(&self) -> Option<&OdeSolverProblem<Eqn>>;
    fn set_problem(
        &mut self,
        state: OdeSolverState<Eqn::V>,
        problem: &OdeSolverProblem<Eqn>
    );
    fn step(&mut self) -> Result<OdeSolverStopReason<Eqn::T>>;
    fn set_stop_time(&mut self, tstop: Eqn::T) -> Result<()>;
    fn interpolate(&self, t: Eqn::T) -> Result<Eqn::V>;
    fn interpolate_sens(&self, t: Eqn::T) -> Result<Vec<Eqn::V>>;
    fn state(&self) -> Option<&OdeSolverState<Eqn::V>>;
    fn state_mut(&mut self) -> Option<&mut OdeSolverState<Eqn::V>>;
    fn order(&self) -> usize;
    fn take_state(&mut self) -> Option<OdeSolverState<Eqn::V>>;

    // Provided method
    fn solve(
        &mut self,
        problem: &OdeSolverProblem<Eqn>,
        t: Eqn::T
    ) -> Result<Eqn::V>
       where Eqn::M: DefaultSolver,
             Self: Sized { ... }
}
Expand description

Trait for ODE solver methods. This is the main user interface for the ODE solvers. The solver is responsible for stepping the solution (given in the OdeSolverState), and interpolating the solution at a given time. However, the solver does not own the state, so the user is responsible for creating and managing the state. If the user wants to change the state, they should call set_problem again.

§Example

use diffsol::{ OdeSolverMethod, OdeSolverProblem, OdeSolverState, OdeEquations, DefaultSolver };

fn solve_ode<Eqn>(solver: &mut impl OdeSolverMethod<Eqn>, problem: &OdeSolverProblem<Eqn>, t: Eqn::T) -> Eqn::V
where
   Eqn: OdeEquations,
   Eqn::M: DefaultSolver,
{
    let state = OdeSolverState::new(problem, solver).unwrap();
    solver.set_problem(state, problem);
    while solver.state().unwrap().t <= t {
        solver.step().unwrap();
    }
    solver.interpolate(t).unwrap()
}

Required Methods§

source

fn problem(&self) -> Option<&OdeSolverProblem<Eqn>>

Get the current problem if it has been set

source

fn set_problem( &mut self, state: OdeSolverState<Eqn::V>, problem: &OdeSolverProblem<Eqn> )

Set the problem to solve, this performs any initialisation required by the solver. Call this before calling step or solve. The solver takes ownership of the initial state given by state, this is assumed to be consistent with any algebraic constraints, and the time step h is assumed to be set appropriately for the problem

source

fn step(&mut self) -> Result<OdeSolverStopReason<Eqn::T>>

Step the solution forward by one step, altering the internal state of the solver. The return value is a Result containing the reason for stopping the solver, possible reasons are:

  • InternalTimestep: The solver has taken a step forward in time, the internal state of the solver is at time self.state().t
  • RootFound(t_root): The solver has found a root at time t_root. Note that the internal state of the solver is at the internal time step self.state().t, not at time t_root.
  • TstopReached: The solver has reached the stop time set by Self::set_stop_time, the internal state of the solver is at time tstop, which is the same as self.state().t
source

fn set_stop_time(&mut self, tstop: Eqn::T) -> Result<()>

Set a stop time for the solver. The solver will stop when the internal time reaches this time. Once it stops, the stop time is unset. If tstop is at or before the current internal time, an error is returned.

source

fn interpolate(&self, t: Eqn::T) -> Result<Eqn::V>

Interpolate the solution at a given time. This time should be between the current time and the last solver time step

source

fn interpolate_sens(&self, t: Eqn::T) -> Result<Vec<Eqn::V>>

Interpolate the sensitivity vectors at a given time. This time should be between the current time and the last solver time step

source

fn state(&self) -> Option<&OdeSolverState<Eqn::V>>

Get the current state of the solver, if it exists

source

fn state_mut(&mut self) -> Option<&mut OdeSolverState<Eqn::V>>

Get a mutable reference to the current state of the solver, if it exists Note that calling this will cause the next call to step to perform some reinitialisation to take into account the mutated state, this could be expensive for multi-step methods.

source

fn order(&self) -> usize

Get the current order of accuracy of the solver (e.g. explict euler method is first-order)

source

fn take_state(&mut self) -> Option<OdeSolverState<Eqn::V>>

Take the current state of the solver, if it exists, returning it to the user. This is useful if you want to use this state in another solver or problem. Note that this will unset the current problem and solver state, so you will need to call set_problem again before calling step or solve.

Provided Methods§

source

fn solve( &mut self, problem: &OdeSolverProblem<Eqn>, t: Eqn::T ) -> Result<Eqn::V>
where Eqn::M: DefaultSolver, Self: Sized,

Reinitialise the solver state and solve the problem up to time t

Implementors§

source§

impl<Eqn> OdeSolverMethod<Eqn> for SundialsIda<Eqn>

source§

impl<M, Eqn, LS> OdeSolverMethod<Eqn> for Sdirk<M, Eqn, LS>
where LS: LinearSolver<SdirkCallable<Eqn>>, M: DenseMatrix<T = Eqn::T, V = Eqn::V>, Eqn: OdeEquations, for<'a> &'a Eqn::V: VectorRef<Eqn::V>, for<'a> &'a Eqn::M: MatrixRef<Eqn::M>,

source§

impl<M: DenseMatrix<T = Eqn::T, V = Eqn::V>, Eqn: OdeEquations, Nls> OdeSolverMethod<Eqn> for Bdf<M, Eqn, Nls>
where Nls: NonLinearSolver<BdfCallable<Eqn>>, for<'b> &'b Eqn::V: VectorRef<Eqn::V>, for<'b> &'b Eqn::M: MatrixRef<Eqn::M>,