-
-
Notifications
You must be signed in to change notification settings - Fork 241
Description
This following report was generated by Claude Code, but I've verified that the bug manifests on 1.10 and not 1.11, and only occurs when DynamicQuantities is loaded as stated. This is causing test failures in the Catalyst tests as we update to MTK 11.
Issue: collect_vars! fails to discover parameters in defaults on Julia 1.10 when DynamicQuantities is loaded
Summary
On Julia 1.10 (but not 1.11), ModelingToolkitBase.collect_vars! fails to discover parameters used in default values of variables when DynamicQuantities is loaded.
Minimal Reproducer
# test_minimal.jl
using ModelingToolkitBase: @parameters
using Symbolics: @variables, unwrap, Operator
using DataStructures: OrderedSet
import ModelingToolkitBase as MT
using DynamicQuantities # THIS TRIGGERS THE BUG on 1.10
const SymbolicT = MT.SymbolicT
@variables t
@parameters X0
@variables X(t) = X0
us = OrderedSet{SymbolicT}()
ps = OrderedSet{SymbolicT}()
MT.collect_vars!(us, ps, unwrap(X), unwrap(t), Operator; depth=0)
println("Julia ", VERSION)
println("params: ", collect(ps))
println("Expected: [X0], Got: ", collect(ps))
# Julia 1.10: params = [] (BUG)
# Julia 1.11: params = [X0] (CORRECT)Root Cause Analysis
-
The bug only manifests when DynamicQuantities is loaded - Without it,
collect_vars!works correctly on Julia 1.10. -
collect_var!works correctly when called directly - The bug is in howcollect_vars!internally callscollect_var!, not incollect_var!itself. -
Workaround: Call
collect_var!first - Ifcollect_var!is called directly on any expression beforecollect_vars!is called, subsequentcollect_vars!calls work correctly:
# Workaround: "warm up" by calling collect_var! first
dummy_us = OrderedSet{SymbolicT}()
dummy_ps = OrderedSet{SymbolicT}()
MT.collect_var!(dummy_us, dummy_ps, some_expr, iv; depth=0)
# Now collect_vars! works correctly
MT.collect_vars!(us, ps, expr, iv, Operator; depth=0)- Not a world age issue -
Base.invokelatestdoes not fix the problem.
Proposed Fixes
Add a dummy collect_var! call in the extension's __init__ function to trigger proper method compilation:
function __init__()
# Existing code...
MTK.t = let
only(@independent_variables t [unit = DQ.u"s"])
end
SymbolicUtils.hashcons(unwrap(MTK.t), true)
MTK.D = Differential(MTK.t)
# NEW: Workaround for Julia 1.10 compiler bug
if VERSION < v"1.11"
# Force collect_var! compilation to fix collect_vars!
@variables _dummy_t
@parameters _dummy_p
@variables _dummy_x(_dummy_t) = _dummy_p
_us = OrderedSet{SymbolicT}()
_ps = OrderedSet{SymbolicT}()
MTK.collect_var!(_us, _ps, unwrap(_dummy_x), unwrap(_dummy_t); depth=0)
end
endEnvironment
Project.toml on 1.10
Status `~/.julia/dev/Catalyst/Project.toml`
⌅ [861a8166] Combinatorics v1.0.2
[864edb3b] DataStructures v0.19.3
[2b5f629d] DiffEqBase v6.199.0
[ffbed154] DocStringExtensions v0.9.5
[7c1d4256] DynamicPolynomials v0.6.4
[06fc5a27] DynamicQuantities v1.11.0
[4e289a0a] EnumX v1.0.6
[86223c79] Graphs v1.13.4
[ccbc3e58] JumpProcesses v9.21.0
[b964fa9f] LaTeXStrings v1.4.0
[23fbe1c1] Latexify v0.16.10
[1914dd2f] MacroTools v0.5.16
[7771a370] ModelingToolkitBase v1.6.3
[d96e819e] Parameters v0.12.3
[189a3867] Reexport v1.2.2
[ae029012] Requires v1.3.1
[7e49a35a] RuntimeGeneratedFunctions v0.5.16
[0bca4576] SciMLBase v2.134.0
[efcf1570] Setfield v1.1.2
[d1185830] SymbolicUtils v4.13.1
[0c5d862f] Symbolics v7.8.0
[1986cc42] Unitful v1.27.0
[37e2e46d] LinearAlgebra
[2f01184e] SparseArrays v1.10.0