Initialisation

Each solver has an internal state that holds information like the current state vector, the gradient of the state vector, the current time, and the current step size. When you create a solver using the bdf or sdirk methods on the OdeSolverProblem struct, the solver will be initialised with an initial state based on the initial conditions of the problem as well as satisfying any algebraic constraints. An initial time step will also be chosen based on your provided equations.

Each solver's state struct implements the OdeSolverState trait, and if you wish to manually create and setup a state, you can use the methods on this trait to do so.

For example, say that you wish to bypass the initialisation of the state as you already have the algebraic constraints and so don't need to solve for them. You can use the new_without_initialise method on the OdeSolverState trait to create a new state without initialising it. You can then use the as_mut method to get a mutable reference to the state and set the values manually.

use crate::{problem_implicit, LS};
use diffsol::{BdfState, OdeSolverState, RkState};

pub fn create_solvers_uninit() {
    let problem = problem_implicit();

    // Create a non-initialised state and manually set the values before
    // creating the solver
    let mut state = RkState::new_without_initialise(&problem).unwrap();
    // ... set the state values manually
    state.as_mut().y[0] = 0.1;
    let _solver = problem.tr_bdf2_solver::<LS>(state);

    // Do the same for a BDF solver
    let mut state = BdfState::new_without_initialise(&problem).unwrap();
    state.as_mut().y[0] = 0.1;
    let _solver = problem.bdf_solver::<LS>(state);
}

Note that each state struct has a as_ref and as_mut methods that return a StateRef or StateRefMut struct respectively. These structs provide a solver-independent way to access the state values so you can use the same code with different solvers.