Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/integrators/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ end
# DefaultCache sumtype does lazy initializations of sub-caches
# Need to overload this function so that the history function has initialized caches
# https://github.com/SciML/DelayDiffEq.jl/issues/329
function OrdinaryDiffEqCore.perform_step!(integrator::DDEIntegrator, cache::OrdinaryDiffEqCore.DefaultCache, repeat_step = false)
function OrdinaryDiffEqCore.perform_step!(integrator::DDEIntegrator,
cache::OrdinaryDiffEqCore.DefaultCache, repeat_step = false)
algs = integrator.alg.algs
OrdinaryDiffEqCore.init_ith_default_cache(cache, algs, cache.current)
if cache.current == 1
Expand Down Expand Up @@ -445,7 +446,8 @@ function DiffEqBase.reinit!(integrator::DDEIntegrator, u0 = integrator.sol.prob.
# erase array of tracked discontinuities
if order_discontinuity_t0 ≤ OrdinaryDiffEqCore.alg_maximum_order(integrator.alg)
resize!(integrator.tracked_discontinuities, 1)
integrator.tracked_discontinuities[1] = Discontinuity(integrator.tdir * integrator.t, order_discontinuity_t0)
integrator.tracked_discontinuities[1] = Discontinuity(
integrator.tdir * integrator.t, order_discontinuity_t0)
else
resize!(integrator.tracked_discontinuities, 0)
end
Expand Down Expand Up @@ -537,6 +539,16 @@ function DiffEqBase.change_t_via_interpolation!(integrator::DDEIntegrator,
OrdinaryDiffEqCore._change_t_via_interpolation!(integrator, t, modify_save_endpoint, reinitialize_alg)
end

# tstops interface for PeriodicCallback support (issue #341)
DiffEqBase.get_tstops(integrator::DDEIntegrator) = integrator.opts.tstops
function DiffEqBase.get_tstops_array(integrator::DDEIntegrator)
DiffEqBase.get_tstops(integrator).valtree
end
function DiffEqBase.get_tstops_max(integrator::DDEIntegrator)
tstops_array = DiffEqBase.get_tstops_array(integrator)
isempty(tstops_array) ? integrator.sol.prob.tspan[end] : maximum(tstops_array)
end

# update integrator when u is modified by callbacks
function OrdinaryDiffEqCore.handle_callback_modifiers!(integrator::DDEIntegrator)
integrator.reeval_fsal = true # recalculate fsalfirst after applying step
Expand Down
22 changes: 22 additions & 0 deletions test/integrators/events.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,25 @@ end
@test sol.u[iter + 1] == [0.0]
@test sol.u[iter + 2] != [0.0]
end

# Issue #341: PeriodicCallback support for DDEIntegrator
@testset "periodic callback" begin
# Simple DDE with constant delay
function f(du, u, h, p, t)
du[1] = -u[1] + h(p, t - 1.0)[1]
end
h(p, t) = [1.0]
prob = DDEProblem(f, [1.0], h, (0.0, 10.0); constant_lags = [1.0])

# Count how many times the callback is triggered
counter = Ref(0)
function affect!(integrator)
counter[] += 1
end
cb = PeriodicCallback(affect!, 1.0)

sol = solve(prob, MethodOfSteps(Tsit5()), callback = cb)
@test sol.retcode == ReturnCode.Success
# Should be triggered approximately 10 times (at t=1,2,3,...,10)
@test counter[] >= 9
end
6 changes: 3 additions & 3 deletions test/integrators/rosenbrock.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const algs = [Rosenbrock23(), Rosenbrock32(), ROS3P(), Rodas3(),
sol_ip = solve(prob_ip, stepsalg)
sol_scalar = solve(prob_scalar, stepsalg)

@test sol_ip(ts, idxs = 1)sol_scalar(ts)
@test sol_ip.tsol_scalar.t
@test sol_ip[1, :]sol_scalar.u
@test isapprox(sol_ip(ts, idxs = 1), sol_scalar(ts), rtol = 1e-4)
@test isapprox(sol_ip.t, sol_scalar.t, rtol = 1e-4)
@test isapprox(sol_ip[1, :], sol_scalar.u, rtol = 1e-4)
end
Loading