DifferentialEquations.jl icon indicating copy to clipboard operation
DifferentialEquations.jl copied to clipboard

Please allow changing VectorContinuousCallback during affect! calls

Open evan-wehi opened this issue 1 year ago • 5 comments

Is your feature request related to a problem? Please describe.

I’m modelling cell population dynamics. Cells die and divide so the size of system is always changing. Most of my state variables can trigger events (i.e. death or division) so it seems that VectorContinuousCallback is the way to go. Unfortunately, the constructor for VectorContinuousCallback requires the length of the returned vector which in my case will change frequently. I could specify a very large length and pad the return vector with non-zero values but that seems inelegant and inefficient.

Describe the solution you’d like

To able to change the length of the returned vector. Changing during a affect! call is adequate for my use case.

Describe alternatives you’ve considered As suggested on the julialang forum: "a single ContinuousCallback that is the multiplication of conditions and then calculate which one had the crossing." I haven't tried this yet but seems like it should work.

Additional context

evan-wehi avatar Sep 19 '24 00:09 evan-wehi

I've started looking at this. I'm happy to have a go at it (it is important for me).

Should I open an issue in OrdinaryDiffEq.jl?

@ChrisRackauckas suggested an approach here: https://discourse.julialang.org/t/changing-the-size-of-vectorcontinuouscallback/119534/7?u=evan-wehi. Perhaps I didn't understand but I'm not sure this will work. It seems to assume the size of the VectorContiniousCallback is the same size as the state vector which I think is not always true (it is not in my use case). Also, there may be more than one call back.

Would it be enough to provide a couple of functions:

function resize!(cb::VectorContiniousCallback, i::Int)
function deleteat!(cb::VectorContiniousCallback, i::Int)

where cb is the original callback. This would be used to find the correct callback in integrator.opts.callback. Is it then simply case of changing the len field. Do I need to do anything with the entries under integrator.callback_cache other than make sure they are long enough?

evan-wehi avatar Dec 16 '24 05:12 evan-wehi

Perhaps I didn't understand but I'm not sure this will work. It seems to assume the size of the VectorContiniousCallback is the same size as the state vector which I think is not always true (it is not in my use case). Also, there may be more than one call back.

Of course it's not the same size as the state vector, that's not a requirement and it's generally false. It just needs a resize overload as I said.

ChrisRackauckas avatar Dec 16 '24 17:12 ChrisRackauckas

Is it then simply case of changing the len field.

There is no len field in the caches actually constructed, the constructed arrays just know the size and that's where it's encoded in the end. Those need to be resize!ed and it should be good.

ChrisRackauckas avatar Dec 16 '24 17:12 ChrisRackauckas

There is a len field in VectorContinuousCallback. This is used to know how much data to pull out of the cache.

https://github.com/SciML/DiffEqBase.jl/blob/ceec4c0ae42a5cf50b78ec876ed650993d7a55b5/src/callbacks.jl#L180

If it isn't updated there is either a bounds error if the vector is shortened or elements will be missed if the size is increased.

evan-wehi avatar Dec 17 '24 04:12 evan-wehi

Okay yeah then we should update that as well.

ChrisRackauckas avatar Dec 19 '24 12:12 ChrisRackauckas