SciML / DifferentialEquations.jl

Multi-language suite for high-performance solvers of differential equations and scientific machine learning (SciML) components. Ordinary differential equations (ODEs), stochastic differential equations (SDEs), delay differential equations (DDEs), differential-algebraic equations (DAEs), and more in Julia.
https://docs.sciml.ai/DiffEqDocs/stable/
Other
2.86k stars 228 forks source link

Idea for unique names for time indices in solution #511

Open goretkin opened 5 years ago

goretkin commented 5 years ago

Due to callbacks, a solution can have repetition in solution.t. This is an idea for introducing a new field, maybe solution.t_discrete`, which would contain an ID for which callback (or none) has just been applied.

I think it could be beneficial to include an additional field in the integration state which is "last callback applied". Each callback (discrete or continuous) could contain some isbitstype unique ID. Since callbacks need to have some order defined on them (in case multiple of them trigger at the same time), it could be integer ID for each callback. At the end of perform_step, do integrator.last_callback = 0, and then while handling callbacks, if any of them trigger, update integrator.last_callback. (Though continuous and discrete callbacks are handled separately, so perhaps it's easier if the ID doesn't correspond to the order).

When doing savevalues!, also save last_callback. integrator.t and integrator.last_callback uniquely name a "saveable" timepoint of the integrator, and there would be no reason to have repeated timepoints in a solution.

This would replace the purpose of saved_in_cb in

  if !integrator.force_stepfail && !(typeof(discrete_callbacks)<:Tuple{})
    discrete_modified,saved_in_cb = DiffEqBase.apply_discrete_callback!(integrator,discrete_callbacks...)
  end
  if !saved_in_cb
    savevalues!(integrator)
  end

I can't tell if this is related to event_last_time for continuous callbacks.

ChrisRackauckas commented 5 years ago

At the end of perform_step, do integrator.last_callback = 0, and then while handling callbacks, if any of them trigger, update integrator.last_callback. (Though continuous and discrete callbacks are handled separately, so perhaps it's easier if the ID doesn't correspond to the order).

More than 1 callback can trigger for step.

When doing savevalues!, also save last_callback. integrator.t and integrator.last_callback uniquely name a "saveable" timepoint of the integrator, and there would be no reason to have repeated timepoints in a solution.

You still need two time points at time t to resolve a discontinuity.

I can't tell if this is related to event_last_time for continuous callbacks.

It's not.

goretkin commented 5 years ago

More than 1 callback can trigger for step. Yes, that's the point. You can save the solution before and after each callback. So, e.g. you could have solution.t[2:5] = [1.0, 1.0, 1.0, 1.0] if multiple callbacks get triggered at t=1.0 My proposal is that there would also be a (up to naming) solution.tdiscrete[2:5] = [0, 1, 3, 6] if callbacks named1,3, and6got triggered att=1.0`

You still need two time points at time t to resolve a discontinuity. Sorry, I was unclear. By "timepoint" I meant a tuple/product of t and tdiscrete (to continue on which my last paragraph).