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

Finalizer not called in Callbacks #1941

Closed
gzagatti opened this issue May 4, 2023 · 0 comments
Closed

Finalizer not called in Callbacks #1941

gzagatti opened this issue May 4, 2023 · 0 comments

Comments

@gzagatti
Copy link

gzagatti commented May 4, 2023

Unless I am missing something, callbacks are not being finalized at the end of the solver. For convenience, I have copied solve! below:

function DiffEqBase.solve!(integrator::ODEIntegrator)
    @inbounds while !isempty(integrator.opts.tstops)
        while integrator.tdir * integrator.t < first(integrator.opts.tstops)
            loopheader!(integrator)
            if integrator.do_error_check && check_error!(integrator) != ReturnCode.Success
                return integrator.sol
            end
            perform_step!(integrator, integrator.cache)
            loopfooter!(integrator)
            if isempty(integrator.opts.tstops)
                break
            end
        end
        handle_tstop!(integrator)
    end
    postamble!(integrator)

    f = integrator.sol.prob.f

    if DiffEqBase.has_analytic(f)
        DiffEqBase.calculate_solution_errors!(integrator.sol;
                                              timeseries_errors = integrator.opts.timeseries_errors,
                                              dense_errors = integrator.opts.dense_errors)
    end
    if integrator.sol.retcode != ReturnCode.Default
        return integrator.sol
    end
    integrator.sol = DiffEqBase.solution_new_retcode(integrator.sol, ReturnCode.Success)
end

Once the first loop (which steps through time) is complete, the function call postamble! which is reproduced below:

postamble!(integrator::ODEIntegrator) = _postamble!(integrator)

function _postamble!(integrator)
    solution_endpoint_match_cur_integrator!(integrator)
    resize!(integrator.sol.t, integrator.saveiter)
    resize!(integrator.sol.u, integrator.saveiter)
    if !(integrator.sol isa DAESolution)
        resize!(integrator.sol.k, integrator.saveiter_dense)
    end
    if integrator.opts.progress
        @logmsg(LogLevel(-1),
                integrator.opts.progress_name,
                _id=:OrdinaryDiffEq,
                message=integrator.opts.progress_message(integrator.dt, integrator.u,
                                                         integrator.p, integrator.t),
                progress="done")
    end
end

But at no point is the callback finalize function called.

I have tested this is indeed the case, below you can two find MWEs. Also, perhaps unrelated with this issue, the callbacks in the examples below trigger saving at the start and end twice only when save_positions = (false, false) this is not the case.

using OrdinaryDiffEq

f(u, p, t) = 1.

condition(u, t, integrator) = u[1]
function affect!(integrator) @info("affect! continuous callback") end
function initialize(cb, u, t, integrator) @info("initialize continuous callback") end
function finalize(cb, u, t, integrator) @info("finalize continuous callback") end

continuous_callback = ContinuousCallback(condition, affect!; initialize, finalize, save_positions = (true, true))
prob = ODEProblem(f, -1., (0.0, 2.0); callback = callback, saveat = 0.5)
sol = solve(prob, Tsit5())
sol = solve(prob, Tsit5())
[ Info: initialize continuous callback
[ Info: affect! continuous callback
retcode: Success
Interpolation: 1st order linear
t: 8-element Vector{Float64}:
 0.0
 0.0
 0.5
 1.0
 1.0000000000000002
 1.0000000000000002
 1.5
 2.0
u: 8-element Vector{Float64}:
 -1.0
 -1.0
 -0.5000000000000011
 -2.220446049250313e-16
 -2.465190328815662e-32
 -2.465190328815662e-32
  0.5
  0.9999999999999996
condition(u, t, integrator) = true
function affect!(integrator) @info("affect! discrete callback") end
function initialize(cb, u, t, integrator) @info("initialize discrete callback") end
function finalize(cb, u, t, integrator) @info("finalize discrete callback") end

callback = DiscreteCallback(condition, affect!; initialize, finalize, save_positions = (true, true))
prob = ODEProblem(f, -1., (0.0, 2.0); callback, saveat = 0.5)
sol = solve(prob, Tsit5())
sol = solve(prob, Tsit5())
[ Info: initialize discrete callback
[ Info: affect! discrete callback
[ Info: affect! discrete callback
retcode: Success
Interpolation: 1st order linear
t: 8-element Vector{Float64}:
 0.0
 0.0
 0.5
 1.0
 1.0
 1.5
 2.0
 2.0
u: 8-element Vector{Float64}:
 -1.0
 -1.0
 -0.5000000000000011
 -2.220446049250313e-16
 -2.220446049250313e-16
  0.49999999999999867
  0.9999999999999996
  0.9999999999999996
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

No branches or pull requests

2 participants