Skip to content

Commit 61b8ea9

Browse files
committed
introduce cache array to make discrete-time state update atomic
closes #2701
1 parent e1befe0 commit 61b8ea9

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/systems/clock_inference.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ function generate_discrete_affect(
321321
end)
322322
end
323323

324+
cache = copy(p[$disc_range]) # Cache needed for atomic state update
325+
324326
# @show disc_to_cont_idxs
325327
# @show cont_to_disc_idxs
326328
# @show disc_range
@@ -368,14 +370,16 @@ function generate_discrete_affect(
368370
if use_index_cache
369371
quote
370372
if !$empty_disc
371-
disc(disc_unknowns, integrator.u, p..., t)
372-
for (val, i) in zip(disc_unknowns, $disc_range)
373+
# NOTE: the first and third arguments to `disc` MAY NOT be aliased
374+
disc(cache, integrator.u, p..., t) # Cache needed for atomic state update
375+
for (val, i) in zip(cache, $disc_range)
373376
$(_set_parameter_unchecked!)(p, val, i; update_dependent = false)
374377
end
375378
end
376379
end
377380
else
378-
:($empty_disc || disc(disc_unknowns, disc_unknowns, p, t))
381+
:($empty_disc || disc(cache, disc_unknowns, p, t)) # Cache needed for atomic state update
382+
copyto!(disc_unknowns, cache)
379383
end
380384
)
381385
# @show "after state update", p

test/clock.jl

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,32 @@ prob = ODEProblem(sys, [], (0.0, 10.0), [x(k - 1) => 2.0])
528528
int = init(prob, Tsit5(); kwargshandle = KeywordArgSilent)
529529
@test int.ps[x] == 3.0
530530
@test int.ps[x(k - 1)] == 2.0
531+
532+
## Atomic state upadte tested using simple delay https://github.com/SciML/ModelingToolkit.jl/issues/2701
533+
534+
using ModelingToolkit: t_nounits as t, D_nounits as D
535+
##
536+
k = ShiftIndex(Clock(t, 1))
537+
@mtkmodel DelayModel begin
538+
@variables begin
539+
input(t) = 0
540+
delay(t) = 0
541+
x(t) = 0
542+
end
543+
@structural_parameters begin
544+
d
545+
end
546+
@equations begin
547+
input ~ (t >= 2)
548+
delay(k) ~ input(k - d)
549+
D(x) ~ (-x + Hold(delay)) / 1e-3
550+
end
551+
end
552+
553+
for d in 0:3
554+
@mtkbuild m = DelayModel(; d)
555+
prob = ODEProblem(
556+
m, [m.delay(k - 3) => 0, m.delay(k - 2) => 0, m.delay(k - 1) => 0], (0.0, 10.0))
557+
sol = solve(prob, Tsit5(), kwargshandle = KeywordArgSilent, dtmax = 0.5)
558+
@test reduce(vcat, sol((0:1:10) .+ 0.1)[:])[zeros(2 + d); ones(10 - 1 - d)] atol=1e-3
559+
end

0 commit comments

Comments
 (0)