Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DiscreteCallback finalize not getting called at end of solve(). #931

Closed
staticfloat opened this issue Sep 18, 2023 · 7 comments · Fixed by SciML/OrdinaryDiffEq.jl#2061
Closed

Comments

@staticfloat
Copy link
Contributor

staticfloat commented Sep 18, 2023

I would expect that at the end of solve(), all finalize callback methods would be getting called, however that does not appear to be the case:

using OrdinaryDiffEq

f(u, p, t) = 1.01*u
u0 = 0.5
cb = DiscreteCallback(
    Returns(false),
    Returns(nothing);
    initialize=(args...)->@info("initialized"),
    finalize=(args...)->@info("finalized"),
)
prob = ODEProblem(f, u0, (0.0, 1.0); callback=cb)
sol = solve(prob, Rodas5P())

Only ever prints initialized

@ChrisRackauckas
Copy link
Member

I don't think finalize ever got finalized (pun not intended). It would be good to actually get that completed and documented.

@ChrisRackauckas
Copy link
Member

@oscardssmith could you help with this?

oscardssmith added a commit to oscardssmith/OrdinaryDiffEq.jl that referenced this issue Nov 15, 2023
fixes SciML/DiffEqBase.jl#931 (although we probably need a similar line added for `Sundials.jl`)
@oscardssmith
Copy link
Contributor

Do we have a good example of a use-case for this to add to the tests?

@staticfloat
Copy link
Contributor Author

It's pretty easy, just create a DiscreteCallback with a finalize, like in the OP

@oscardssmith
Copy link
Contributor

right, but testing for the presence of an @info isn't especially easy. I can always add a test that does something silly (like mutate a global in the finalizer) but a test where the finalization is actually doing something somewhat useful would likely be better at making sure errors aren't introduced (like running multiple times/running at the wrong point in time etc). Also, do we have a strong idea of where in the process this finalize call should happen? The place I put it seems reasonable, but I don't have a great sense of the semantic here other than "after the time-stepping but before the return from solve". Should the finalize be able to affect the final u values before they are saved? Should it be able to restart integration (e.g. by adding an extra tstop)? etc.

@staticfloat
Copy link
Contributor Author

The docs say:

finalize: This is a function (c,u,t,integrator) which can be used to finalize the state of the callback c. It can modify the argument c and the return is ignored.

So my intuition says that it should not be allowed to affect the final u values, and it should not be allowed to restart integration.

@staticfloat
Copy link
Contributor Author

I can always add a test that does something silly (like mutate a global in the finalizer)

That's exactly what I would do; just increment a global and check that it was incremented the correct number of times.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants