Skip to content

Question - ODE State at time of event #74

Closed

Description

@JEMH

Hello Martin,
I have a question concerning the detection of events.

I see that to detect events I need to provide a closure that has a zero crossing at the event and then I need to use the return value of OdeSolverMethod::step to check if an event has been detected.

In the documentation for OdeSolverStopReason it states:
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.

In my case I would like to know both t_root and also the state at time t=t_root. Is there an easy way to obtain this information?
I would then restart/continue the integration from the event onwards.

I am sorry if this has an obvious answer, but I am new to the Rust programming language and it is not immediately obvious to me.

Thanks,
James Housden

Activity

  1. martinjrobins commented on Jul 18, 2024

    @martinjrobins
    Owner

    Hi @JEMH, you can use OdeSolverMethod::interpolate to get the state vector at the time of the event (i.e. t_root).

    If you are happy then continuing the integration from the internal time of the solver, then great :). However, if you wanted to restart from exactly the time of the event, then you would have to mutate the state (using OdeSolverMethod::state_mut) and set it to the interpolated state.

    Perhaps something like this (I havn't tried compiling/running this!)

    let t = loop {
        match solver.step() {
            Ok(OdeSolverStopReason::InternalTimestep) => continue,
            Ok(OdeSolverStopReason::TstopReached) => panic!("We didn't set a stop time"),
            Ok(OdeSolverStopReason::RootFound(t)) => break t,
            Err(e) => panic!("Solver failed to converge: {}", e),
        }
    };
    println!("Root found at t = {}", t);
    let new_state = solver.interpolate(t).unwrap();
    solver.state_mut().unwrap().y.copy_from(&new_state);
    *solver.state_mut().unwrap().t = t;
    solver.step();

    Note that this is inefficient for some solvers (the BDF one) as it needs to be re-initialised after the call to state_mut, so if you are happy to just continue solving without mutating the state (the solver will carry on from its current internal timestep) this is the best.

  2. martinjrobins commented on Jul 18, 2024

    @martinjrobins
    Owner

    note I've just put together some docs on this: https://martinjrobins.github.io/diffsol/solving_the_problem.html

  3. JEMH commented on Jul 19, 2024

    @JEMH
    Author
  4. Repository owner locked and limited conversation to collaborators on Jul 19, 2024
  5. converted this issue into a discussion #77 on Jul 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions