Search code examples
pythonscipysimulationnumerical-methods

Checking Event in solve_ivp


What is a fast way of checking which event has been triggered in scipy.solve_ivp()? For context, I am simulating a double pendulum. I want to check if either the first rod or the second rod has been flipped. I have created two event functions for each, but once the event is triggered, is there any way I can retrieve which event has been triggered? Thanks :)


Solution

  • Oops, I see there's an answer. Might as well post, since it's already written:

    There are two terminal events in the following code, which represents a simple harmonic oscilator.

    import numpy as np
    from scipy import integrate
    
    def dy(t, y):
        return [y[1], -y[0]]
    
    def event1(t, y):
        return y[0]
    event1.terminal = True
    
    def event2(t, y):
        return y[1]
    event2.terminal = True
    
    tspan = [0, 10]
    y0 = [0.1, -0.1]
    sol = integrate.solve_ivp(dy, tspan, y0, events=[event1, event2])
    

    According to the solve_ivp documentation, sol.t_events is a list of arrays of times at which an event occured. The first array in the list corresponds with the first event; the second array corresponds with the second event. In case some of the events are non-terminal, create a list with time of the last event in each array:

    last_events = [(t_event[-1] if len(t_event) else tspan[0]) for t_event in sol.t_events]
    

    The event which occured is the argmax of these.

    np.argmax(last_events)  # 0 
    

    In this case, the first event (event 0) occured, which means that the "position" y[0] has crossed zero. You can change the initial "velocity" to y0[1] = -y0[1] to see that the argmax becomes 1, so the second event (event 1) occurs, which means that the velocity has crossed zero.