OdeSolverMethod

Trait OdeSolverMethod 

Source
pub trait OdeSolverMethod<'a, Eqn>: Clone
where Self: Sized, Eqn: 'a + OdeEquations,
{ type State: OdeSolverState<Eqn::V>; type Config: OdeSolverConfig<Eqn::T>;
Show 24 methods // Required methods fn problem(&self) -> &'a OdeSolverProblem<Eqn>; fn checkpoint(&mut self) -> Self::State; fn state_clone(&self) -> Self::State; fn set_state(&mut self, state: Self::State); fn into_state(self) -> Self::State; fn state(&self) -> StateRef<'_, Eqn::V>; fn state_mut(&mut self) -> StateRefMut<'_, Eqn::V>; fn config(&self) -> &Self::Config; fn config_mut(&mut self) -> &mut Self::Config; fn jacobian(&self) -> Option<Ref<'_, Eqn::M>>; fn mass(&self) -> Option<Ref<'_, Eqn::M>>; fn step(&mut self) -> Result<OdeSolverStopReason<Eqn::T>, DiffsolError>; fn set_stop_time(&mut self, tstop: Eqn::T) -> Result<(), DiffsolError>; fn interpolate_inplace( &self, t: Eqn::T, y: &mut Eqn::V, ) -> Result<(), DiffsolError>; fn interpolate_out_inplace( &self, t: Eqn::T, g: &mut Eqn::V, ) -> Result<(), DiffsolError>; fn interpolate_sens_inplace( &self, t: Eqn::T, sens: &mut [Eqn::V], ) -> Result<(), DiffsolError>; fn order(&self) -> usize; // Provided methods fn interpolate(&self, t: Eqn::T) -> Result<Eqn::V, DiffsolError> { ... } fn interpolate_out(&self, t: Eqn::T) -> Result<Eqn::V, DiffsolError> { ... } fn interpolate_sens(&self, t: Eqn::T) -> Result<Vec<Eqn::V>, DiffsolError> { ... } fn solve( &mut self, final_time: Eqn::T, ) -> Result<(<Eqn::V as DefaultDenseMatrix>::M, Vec<Eqn::T>), DiffsolError> where Eqn::V: DefaultDenseMatrix, Self: Sized { ... } fn solve_dense( &mut self, t_eval: &[Eqn::T], ) -> Result<<Eqn::V as DefaultDenseMatrix>::M, DiffsolError> where Eqn::V: DefaultDenseMatrix, Self: Sized { ... } fn solve_with_checkpointing( &mut self, final_time: Eqn::T, max_steps_between_checkpoints: Option<usize>, ) -> Result<(Checkpointing<'a, Eqn, Self>, <Eqn::V as DefaultDenseMatrix>::M, Vec<Eqn::T>), DiffsolError> where Eqn::V: DefaultDenseMatrix, Self: Sized { ... } fn solve_dense_with_checkpointing( &mut self, t_eval: &[Eqn::T], max_steps_between_checkpoints: Option<usize>, ) -> Result<(Checkpointing<'a, Eqn, Self>, <Eqn::V as DefaultDenseMatrix>::M), DiffsolError> where Eqn::V: DefaultDenseMatrix, 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, OdeEquationsImplicit, DefaultSolver };

fn solve_ode<'a, Eqn>(solver: &mut impl OdeSolverMethod<'a, Eqn>, t: Eqn::T) -> Eqn::V
where
   Eqn: OdeEquationsImplicit + 'a,
   Eqn::M: DefaultSolver,
{
    while solver.state().t <= t {
        solver.step().unwrap();
    }
    solver.interpolate(t).unwrap()
}

Required Associated Types§

Source

type State: OdeSolverState<Eqn::V>

The state type used by the solver

Source

type Config: OdeSolverConfig<Eqn::T>

The configuration type used by the solver

Required Methods§

Source

fn problem(&self) -> &'a OdeSolverProblem<Eqn>

Get the current problem

Source

fn checkpoint(&mut self) -> Self::State

Take a checkpoint of the current state of the solver, returning it to the user. This is useful if you want to use this state in another solver or problem but want to keep this solver active. If you don’t need to use this solver again, you can use take_state instead. Note that this will force a reinitialisation of the internal Jacobian for the solver, if it has one.

Source

fn state_clone(&self) -> Self::State

Clone the current state of the solver without triggering any internal Jacobian reset.

Source

fn set_state(&mut self, state: Self::State)

Replace the current state of the solver with a new state.

Source

fn into_state(self) -> Self::State

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.

Source

fn state(&self) -> StateRef<'_, Eqn::V>

Get the current state of the solver

Source

fn state_mut(&mut self) -> StateRefMut<'_, Eqn::V>

Get a mutable reference to the current state of the solver 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 config(&self) -> &Self::Config

Get a reference to the current configuration of the solver

Source

fn config_mut(&mut self) -> &mut Self::Config

Get a mutable reference to the current configuration of the solver

Source

fn jacobian(&self) -> Option<Ref<'_, Eqn::M>>

Returns the current jacobian matrix of the solver, if it has one Note that this will force a full recalculation of the Jacobian.

Source

fn mass(&self) -> Option<Ref<'_, Eqn::M>>

Returns the current mass matrix of the solver, if it has one Note that this will force a full recalculation of the mass matrix.

Source

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

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<(), DiffsolError>

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_inplace( &self, t: Eqn::T, y: &mut Eqn::V, ) -> Result<(), DiffsolError>

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

Source

fn interpolate_out_inplace( &self, t: Eqn::T, g: &mut Eqn::V, ) -> Result<(), DiffsolError>

Interpolate the integral of the output function at a given time and place in g. This time should be between the current time and the last solver time step

Source

fn interpolate_sens_inplace( &self, t: Eqn::T, sens: &mut [Eqn::V], ) -> Result<(), DiffsolError>

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

Source

fn order(&self) -> usize

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

Provided Methods§

Source

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

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

Source

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

Interpolate the integral of the output function 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>, DiffsolError>

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

Source

fn solve( &mut self, final_time: Eqn::T, ) -> Result<(<Eqn::V as DefaultDenseMatrix>::M, Vec<Eqn::T>), DiffsolError>
where Eqn::V: DefaultDenseMatrix, Self: Sized,

Solve the ODE from the current time to final_time.

This method integrates the system and returns the solution at adaptive timepoints chosen by the solver’s internal error control mechanism. This is useful when you want the minimal number of timepoints for a given accuracy.

§Arguments
  • final_time: The time to integrate to
§Returns

A tuple of (solution_matrix, times) where:

  • solution_matrix is a dense matrix with one column per solution time and one row per state variable
  • times is a vector of times at which the solution was evaluated
§Post-condition

After the solver finishes, the internal state of the solver is at time final_time. If a root is found, the solver stops early. The internal state is moved to the root time, and the root time/value are returned as the last entry.

Source

fn solve_dense( &mut self, t_eval: &[Eqn::T], ) -> Result<<Eqn::V as DefaultDenseMatrix>::M, DiffsolError>
where Eqn::V: DefaultDenseMatrix, Self: Sized,

Solve the ODE from the current time to t_eval[t_eval.len()-1], evaluating at specified times.

This method integrates the system and returns the solution interpolated at the specified times. The solver uses its own internal timesteps for accuracy, but the output is interpolated to the requested evaluation times. This is useful when you need the solution at specific timepoints and want the solver’s adaptive stepping for accuracy.

§Arguments
  • t_eval: A slice of times at which to evaluate the solution. Times should be in increasing order.
§Returns

A dense matrix with one column per evaluation time (in the same order as t_eval) and one row per state variable.

§Post-condition

After the solver finishes, the internal state of the solver is at time t_eval[t_eval.len()-1]. If a root is found, the solver stops early. The internal state is moved to the root time, and the last column corresponds to the root time (which may not be in t_eval).

Source

fn solve_with_checkpointing( &mut self, final_time: Eqn::T, max_steps_between_checkpoints: Option<usize>, ) -> Result<(Checkpointing<'a, Eqn, Self>, <Eqn::V as DefaultDenseMatrix>::M, Vec<Eqn::T>), DiffsolError>
where Eqn::V: DefaultDenseMatrix, Self: Sized,

Solve the ODE from the current time to final_time, saving checkpoints at regular intervals.

This method is useful for adjoint sensitivity analysis, where you need to store the solution at intermediate times to efficiently compute gradients.

§Arguments
  • final_time: The time to integrate to
  • max_steps_between_checkpoints: The maximum number of solver steps to take between saving checkpoints (if None, defaults to 500)
§Returns

A tuple of (checkpointer, output_matrix, output_times) where:

  • checkpointer implements the Checkpointing trait and can be used for adjoint integrations
  • output_matrix a dense matrix containing the solution at each output time
  • output_times a vector of timepoints corresponding to the columns of output_matrix
Source

fn solve_dense_with_checkpointing( &mut self, t_eval: &[Eqn::T], max_steps_between_checkpoints: Option<usize>, ) -> Result<(Checkpointing<'a, Eqn, Self>, <Eqn::V as DefaultDenseMatrix>::M), DiffsolError>
where Eqn::V: DefaultDenseMatrix, Self: Sized,

Solve the ODE from the current time to t_eval[t_eval.len()-1] with checkpointing, evaluating at specified times.

This method is similar to Self::solve_dense but additionally saves checkpoints of the solver state at regular intervals. Checkpointing enables efficient adjoint sensitivity analysis by storing the forward integration state, allowing backward integration to compute gradients without recomputing the entire forward solution.

§Arguments
  • t_eval: A slice of times at which to evaluate the solution. Times should be in increasing order.
  • max_steps_between_checkpoints: The maximum number of solver steps to take between saving checkpoints. If None, defaults to 500.
§Returns

A tuple of (checkpointer, solution_matrix) where:

  • checkpointer implements the Checkpointing trait and stores the forward integration state for use in adjoint integrations
  • solution_matrix is a dense matrix with one column per evaluation time and one row per state variable
§Post-condition

After the solver finishes, the internal state of the solver is at time t_eval[t_eval.len()-1].

§See also

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<'a, Eqn, M, AugmentedEqn> OdeSolverMethod<'a, Eqn> for ExplicitRk<'a, Eqn, M, AugmentedEqn>
where Eqn: OdeEquations, M: DenseMatrix<V = Eqn::V, T = Eqn::T, C = Eqn::C>, AugmentedEqn: AugmentedOdeEquations<Eqn>, Eqn::V: DefaultDenseMatrix<T = Eqn::T, C = Eqn::C>,

Source§

type State = RkState<<Eqn as Op>::V>

Source§

type Config = ExplicitRkConfig<<Eqn as Op>::T>

Source§

impl<'a, M, Eqn, AugmentedEqn, LS> OdeSolverMethod<'a, Eqn> for Sdirk<'a, Eqn, LS, M, AugmentedEqn>
where LS: LinearSolver<Eqn::M>, M: DenseMatrix<T = Eqn::T, V = Eqn::V, C = Eqn::C>, Eqn: OdeEquationsImplicit, Eqn::V: DefaultDenseMatrix<T = Eqn::T, C = Eqn::C>, AugmentedEqn: AugmentedOdeEquationsImplicit<Eqn>,

Source§

type State = RkState<<Eqn as Op>::V>

Source§

type Config = SdirkConfig<<Eqn as Op>::T>

Source§

impl<'a, M, Eqn, Nls, AugmentedEqn> OdeSolverMethod<'a, Eqn> for Bdf<'a, Eqn, Nls, M, AugmentedEqn>
where Eqn: OdeEquationsImplicit, AugmentedEqn: AugmentedOdeEquations<Eqn> + OdeEquationsImplicit, M: DenseMatrix<T = Eqn::T, V = Eqn::V, C = Eqn::C>, Eqn::V: DefaultDenseMatrix, Nls: NonLinearSolver<Eqn::M>, for<'b> &'b Eqn::V: VectorRef<Eqn::V>, for<'b> &'b Eqn::M: MatrixRef<Eqn::M>,

Source§

type State = BdfState<<Eqn as Op>::V, M>

Source§

type Config = BdfConfig<<Eqn as Op>::T>