I have opened PR #21741 to add callbacks in scipy.integrate.solve_ivp for use cases such as progress tracking and dynamic max step size control. This callback is not currently intended to directly control the state or RHS of the integration as currently solve_ivp is not equipped to handle this.
The current discussion has aligned on passing the callback an instance of class IntermediateOdeResult(current naming) inheriting from _RichResult It would contain attributes that have information about the integration, e.g. time, state, nsteps, etc.
In review, there was a desire to open a discussion on when the callback should be called and what information should be supplied to the callback in those cases. I am trying to distill a few different pieces of the conversation down, and the list is meant as a starting point for discussion.
First, some definitions used in the options related to timing/type of callback:
- after-step callback: callback that is called after every (successful) integration step of the algorithm.
- upon-event callback: callback that is called when any event occurs
- upon-event-type callback: callback that is called only when a specific event occurs
More definitions:
t_current: current integration time after stepy_currentcurrent integration state after stept: history of time for all steps including last stepy: history of state for all steps including last stept_events_current: times of events that occured at last stepy_events_current: states of system at times in above linet_eventshistory of times of events for all steps including last stepy_eventshistory of states of system at times in above lineevent_idindex of a specific event that occured over last stepevent_indicesindices of all events that occured over last stepcontextwhat triggered the callback
Options:
-
Only use a single after-step callback with history: include
t,y,t_events,y_events,event_indices. Thecurrentvalues could also be passed for convenience. -
Only use a single after-step callback without history: include
t_current,y_current,t_events_current,y_events_current,event_indices. -
Use a single callback, and call it after-step and upon-event without history.
- Using
contextto distinguish what triggered callback.
- Using
-
Use a single callback, and call it after-step and upon-event-type without history.
- Similar to 3, but it would be called per step type.
contextcould be the same asevent_idin this case.
- Similar to 3, but it would be called per step type.
-
Use different callbacks for after-step and upon-event without history.
- No need for
context.
- No need for
-
Use different callbacks for after-step and upon-event-type without history.
- Need
event_idand could be same ascontext. - 1 callback per event type could also be considered.
event_id/contextis possibly unneeded, but could be useful.
- Need
I chose to include with history for option 1, but it could potentially be considered for any option 3-6, particularly for the after-step context.
For options 3-6 we could choose to limit the information available to the different types of callback calls, e.g. only after step information in after-step context and only the state at the time of event in the upon-event context. Or we could chose to provide similar types of information to all contexts.