Goal
Upgrade the MTK stack under a purely-discrete (clocked) model that we compile with SynchToolkit's stkcompile. We currently pin ModelingToolkit = "= 11.34.0" / ModelingToolkitBase = "= 1.54.1" / ModelingToolkitTearing = "= 1.19.3", and we'd like to move to current versions.
What fails
On the newer stack, split_system throws while shifting the discrete system:
ArgumentError: Cannot add arguments of different sizes -
encountered shapes UnitRange{Int64}[] and SymbolicUtils.Unknown(2).
[1] throw_unequal_shape_error(x::SymbolicUtils.Unknown, y::SymbolicUtils.SmallVec{UnitRange{Int64}, …})
@ SymbolicUtils src/symbolic_ops/addsub.jl:2
[2] promote_shape(::typeof(+), …)
@ SymbolicUtils src/symbolic_ops/addsub.jl:10
[3] maketerm(::Type{…BasicSymbolicImpl{SymReal}}, f, args, metadata; type)
@ SymbolicUtils src/terminterface.jl:354
[5] DefaultSubstituter{…}(ex)
@ SymbolicUtils src/substitute.jl:198
[9] shift_discrete_system(ts::TearingState)
@ ModelingToolkitTearing src/tearingstate.jl:1092
[10] mark_discrete
@ ModelingToolkitTearing src/clock_inference/interface.jl:127
Line 1092 is the equation-substitution loop in shift_discrete_system:
for k in discvars
k in fullvars_set || continue
MTKBase.isoperator(k, Union{Sample, Hold, Pre}) && continue
discmap[k] = MTKBase.simplify_shifts(Shift(iv, 1)(k))
end
...
for i in eachindex(eqs)
eqs[i] = MTKBase.simplify_shifts(substitute( # <-- throws here
eqs[i], discmap; filterer = Symbolics.FPSubFilterer{Union{Sample, Hold, Pre}}()))
end
So substituting k → Shift(iv, 1)(k) into an equation rebuilds a + whose operands no longer agree on shape: one side is scalar (UnitRange{Int64}[]), the other reports SymbolicUtils.Unknown(2). Every variable involved is scalar in our models — we have no array variables in these components.
infer_clocks! succeeds; it is split_system that throws:
state = MTKTearing.TearingState(expand_connections(sys))
ci = MTKTearing.infer_clocks!(MTKTearing.ClockInference(state))
MTKTearing.split_system(ci) # ArgumentError here
Versions
Fails with ModelingToolkit 11.37.1 (master), ModelingToolkitBase 1.57.1 (master), ModelingToolkitTearing 1.20.0 (main), SymbolicUtils 4.42.0, Symbolics 7.34.0, SciMLBase 3.39.1, on Julia 1.12.6.
Works with ModelingToolkit 11.34.0 / ModelingToolkitBase 1.54.1 / ModelingToolkitTearing 1.19.3 — our full test suite (5453 tests) passes there and exercises exactly this path.
Reproduction
Any of several clocked components in QuanserComponents reproduce it through the three lines above — GoHome, SwingupCatch, RuntimeController, SwingupWithHoming. They are ordinary controller blocks assembled from DiscreteComponents delay and filter primitives (UnitDelay, DiscreteDerivative, ExponentialFilter), i.e. the equations contain u@(clk-1)-style shifts, all on scalar signals. The simplest failing one is GoHome.
I have not reduced this to a dependency-free example, and I have not yet checked whether released 11.37.0 is also affected — in that configuration an unrelated SampleTime error (SynchToolkit#172, fixed on MTK master) aborted compilation before split_system was reached, so the two were masking each other. Happy to bisect further or produce a minimal case if that would help.
Question
Is there something our models should be doing differently for the shift pass on the newer stack — some shape or metadata expectation on scalar discrete variables that changed — or is shift_discrete_system reconstructing terms in a way that no longer satisfies the newer promote_shape? Also happy to move this issue if it belongs in ModelingToolkitBase or SymbolicUtils rather than here; I filed it where the throwing frame lives.
🤖 Generated with Claude Code
https://claude.ai/code/session_01GyRqJUikfxyEUKMcQaxBF9
Goal
Upgrade the MTK stack under a purely-discrete (clocked) model that we compile with SynchToolkit's
stkcompile. We currently pinModelingToolkit = "= 11.34.0"/ModelingToolkitBase = "= 1.54.1"/ModelingToolkitTearing = "= 1.19.3", and we'd like to move to current versions.What fails
On the newer stack,
split_systemthrows while shifting the discrete system:Line 1092 is the equation-substitution loop in
shift_discrete_system:So substituting
k → Shift(iv, 1)(k)into an equation rebuilds a+whose operands no longer agree on shape: one side is scalar (UnitRange{Int64}[]), the other reportsSymbolicUtils.Unknown(2). Every variable involved is scalar in our models — we have no array variables in these components.infer_clocks!succeeds; it issplit_systemthat throws:Versions
Fails with ModelingToolkit 11.37.1 (
master), ModelingToolkitBase 1.57.1 (master), ModelingToolkitTearing 1.20.0 (main), SymbolicUtils 4.42.0, Symbolics 7.34.0, SciMLBase 3.39.1, on Julia 1.12.6.Works with ModelingToolkit 11.34.0 / ModelingToolkitBase 1.54.1 / ModelingToolkitTearing 1.19.3 — our full test suite (5453 tests) passes there and exercises exactly this path.
Reproduction
Any of several clocked components in QuanserComponents reproduce it through the three lines above —
GoHome,SwingupCatch,RuntimeController,SwingupWithHoming. They are ordinary controller blocks assembled fromDiscreteComponentsdelay and filter primitives (UnitDelay,DiscreteDerivative,ExponentialFilter), i.e. the equations containu@(clk-1)-style shifts, all on scalar signals. The simplest failing one isGoHome.I have not reduced this to a dependency-free example, and I have not yet checked whether released 11.37.0 is also affected — in that configuration an unrelated
SampleTimeerror (SynchToolkit#172, fixed on MTK master) aborted compilation beforesplit_systemwas reached, so the two were masking each other. Happy to bisect further or produce a minimal case if that would help.Question
Is there something our models should be doing differently for the shift pass on the newer stack — some shape or metadata expectation on scalar discrete variables that changed — or is
shift_discrete_systemreconstructing terms in a way that no longer satisfies the newerpromote_shape? Also happy to move this issue if it belongs in ModelingToolkitBase or SymbolicUtils rather than here; I filed it where the throwing frame lives.🤖 Generated with Claude Code
https://claude.ai/code/session_01GyRqJUikfxyEUKMcQaxBF9