From 6299aa5d9e4b3a123431519148fe43a077572614 Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Mon, 19 Jan 2026 14:09:16 +0000 Subject: [PATCH 01/10] feat: allow SCP passes to Systems --- src/ModelingToolkit.jl | 4 ++++ src/systems/codegen.jl | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 850a45a5e8..7215acdc2f 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -75,6 +75,10 @@ import Symbolics: rename, get_variables!, _solve, hessian_sparsity, scalarize, hasderiv import ModelingToolkitBase as MTKBase +import SymbolicCompilerPasses as SCP +import SCP: MATMUL_ADD_RULE, LDIV_RULE, HVNCAT_STATIC_RULE, + TRIU_RULE, TRIL_RULE, NORMALIZE_RULE, ORTHO_INV_RULE + import DiffEqBase: @add_kwonly @reexport using Symbolics @reexport using UnPack diff --git a/src/systems/codegen.jl b/src/systems/codegen.jl index a70ec0f558..fd17e2ae71 100644 --- a/src/systems/codegen.jl +++ b/src/systems/codegen.jl @@ -575,3 +575,17 @@ function get_semiquadratic_W_sparsity( SparseMatrixCSC{Bool, Int64}((!iszero).(mm)) return (!_iszero).(jac) .| M_sparsity end + +const SCP_BASIC = [ + MATMUL_ADD_RULE, + TRIU_RULE, + TRIL_RULE, + NORMALIZE_RULE, + LDIV_RULE, +] + +const SCP_AGGRESSIVE = [ + SCP_BASIC; + HVNCAT_STATIC_RULE; + ORTHO_INV_RULE; +] \ No newline at end of file From 1428ece8c303c90bf4b966ad7ae68efe1cd255fb Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Mon, 19 Jan 2026 15:38:08 +0000 Subject: [PATCH 02/10] feat: add frontend to consume ints, bool, symbols and vectors --- .../src/systems/codegen_utils.jl | 10 ++++++-- src/systems/codegen.jl | 25 ++++++++++++++++++- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/ModelingToolkitBase/src/systems/codegen_utils.jl b/lib/ModelingToolkitBase/src/systems/codegen_utils.jl index a59e3efbbc..623c1c926d 100644 --- a/lib/ModelingToolkitBase/src/systems/codegen_utils.jl +++ b/lib/ModelingToolkitBase/src/systems/codegen_utils.jl @@ -252,7 +252,8 @@ function build_function_wrapper( wrap_delays = is_dde(sys), histfn = DDE_HISTORY_FUN, histfn_symbolic = histfn, wrap_code = identity, add_observed = true, filter_observed = Returns(true), create_bindings = false, output_type = nothing, mkarray = nothing, - wrap_mtkparameters = true, extra_assignments = Assignment[], cse = true, kwargs... + wrap_mtkparameters = true, extra_assignments = Assignment[], cse = true, + optimize = nothing, kwargs... ) isscalar = !(expr isa AbstractArray || symbolic_type(expr) == ArraySymbolic()) # filter observed equations @@ -375,9 +376,14 @@ function build_function_wrapper( if wrap_code isa Tuple && symbolic_type(expr) == ScalarSymbolic() wrap_code = wrap_code[1] end - return build_function(expr, args...; wrap_code, similarto, cse, kwargs...) + + optimize = resolve_optimize_option(optimize) + return build_function(expr, args...; wrap_code, similarto, cse, optimize, kwargs...) end +resolve_optimize_option(x) = x +resolve_optimize_option(::Nothing) = nothing + """ $(TYPEDEF) diff --git a/src/systems/codegen.jl b/src/systems/codegen.jl index fd17e2ae71..ee06490da2 100644 --- a/src/systems/codegen.jl +++ b/src/systems/codegen.jl @@ -588,4 +588,27 @@ const SCP_AGGRESSIVE = [ SCP_BASIC; HVNCAT_STATIC_RULE; ORTHO_INV_RULE; -] \ No newline at end of file +] + +const SCP_OPTIONS = Dict(:basic => SCP_BASIC, :aggressive => SCP_AGGRESSIVE) + +function MTKBase.resolve_optimize_option(o::Bool) + resolve_optimize_option(o ? SCP_BASIC : nothing) +end + +function MTKBase.resolve_optimize_option(o::Symbol) + rules = get(SCP_OPTIONS, o, nothing) + resolve_optimize_option(rules) +end + +function MTKBase.resolve_optimize_option(o::Int) + if o == 0 + return resolve_optimize_option(false) + elseif o == 1 + return resolve_optimize_option(:basic) + elseif o == 2 + return resolve_optimize_option(:aggressive) + else + throw(ArgumentError("Invalid optimize option integer: $o")) + end +end \ No newline at end of file From cf00c82f0d619aac90de73a37c9f8295dd340759 Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Mon, 19 Jan 2026 15:41:03 +0000 Subject: [PATCH 03/10] chore: refactor options dict --- src/systems/codegen.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/systems/codegen.jl b/src/systems/codegen.jl index ee06490da2..2f4a4b6221 100644 --- a/src/systems/codegen.jl +++ b/src/systems/codegen.jl @@ -590,7 +590,10 @@ const SCP_AGGRESSIVE = [ ORTHO_INV_RULE; ] -const SCP_OPTIONS = Dict(:basic => SCP_BASIC, :aggressive => SCP_AGGRESSIVE) +const SCP_OPTIONS = Dict(:basic => SCP_BASIC, + :aggressive => SCP_AGGRESSIVE, + :none => nothing + ) function MTKBase.resolve_optimize_option(o::Bool) resolve_optimize_option(o ? SCP_BASIC : nothing) From 056d99016ada7963b625c0a38b067da647eca4df Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Tue, 20 Jan 2026 11:26:41 +0000 Subject: [PATCH 04/10] chore: import SCP explicitly --- src/ModelingToolkit.jl | 2 +- src/systems/codegen.jl | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 7215acdc2f..0b35771037 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -76,7 +76,7 @@ import Symbolics: rename, get_variables!, _solve, hessian_sparsity, import ModelingToolkitBase as MTKBase import SymbolicCompilerPasses as SCP -import SCP: MATMUL_ADD_RULE, LDIV_RULE, HVNCAT_STATIC_RULE, +import SymbolicCompilerPasses: MATMUL_ADD_RULE, LDIV_RULE, HVNCAT_STATIC_RULE, TRIU_RULE, TRIL_RULE, NORMALIZE_RULE, ORTHO_INV_RULE import DiffEqBase: @add_kwonly diff --git a/src/systems/codegen.jl b/src/systems/codegen.jl index 2f4a4b6221..beabf2dfa7 100644 --- a/src/systems/codegen.jl +++ b/src/systems/codegen.jl @@ -611,7 +611,6 @@ function MTKBase.resolve_optimize_option(o::Int) return resolve_optimize_option(:basic) elseif o == 2 return resolve_optimize_option(:aggressive) - else - throw(ArgumentError("Invalid optimize option integer: $o")) end + throw(ArgumentError("Invalid optimize option integer: $o")) end \ No newline at end of file From 0383849e0f422240bdcc03e892aab7840679f9fd Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Tue, 20 Jan 2026 11:27:57 +0000 Subject: [PATCH 05/10] build: add SCP to deps --- Project.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Project.toml b/Project.toml index 52c4a234c1..7c2770d36f 100644 --- a/Project.toml +++ b/Project.toml @@ -39,6 +39,7 @@ SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StateSelection = "64909d44-ed92-46a8-bbd9-f047dfbdc84b" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" +SymbolicCompilerPasses = "3384d301-0fbe-4b40-9ae0-b0e68bedb069" SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5" SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" @@ -108,6 +109,7 @@ StaticArrays = "1.9.14" StochasticDelayDiffEq = "1.11" StochasticDiffEq = "6.82.0" SymbolicIndexingInterface = "0.3.39" +SymbolicCompilerPasses = "0.1.0" SymbolicUtils = "4.11" Symbolics = "7" UnPack = "0.1, 1.0" From 3b1563c0ff757288912a03044f23954d516c0b07 Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Tue, 27 Jan 2026 10:27:36 +0000 Subject: [PATCH 06/10] chore: rm ORTHO_INV_RULE for now --- src/ModelingToolkit.jl | 2 +- src/systems/codegen.jl | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ModelingToolkit.jl b/src/ModelingToolkit.jl index 0b35771037..3cf41c8441 100644 --- a/src/ModelingToolkit.jl +++ b/src/ModelingToolkit.jl @@ -77,7 +77,7 @@ import ModelingToolkitBase as MTKBase import SymbolicCompilerPasses as SCP import SymbolicCompilerPasses: MATMUL_ADD_RULE, LDIV_RULE, HVNCAT_STATIC_RULE, - TRIU_RULE, TRIL_RULE, NORMALIZE_RULE, ORTHO_INV_RULE + TRIU_RULE, TRIL_RULE, NORMALIZE_RULE import DiffEqBase: @add_kwonly @reexport using Symbolics diff --git a/src/systems/codegen.jl b/src/systems/codegen.jl index beabf2dfa7..6dae61ccce 100644 --- a/src/systems/codegen.jl +++ b/src/systems/codegen.jl @@ -587,7 +587,6 @@ const SCP_BASIC = [ const SCP_AGGRESSIVE = [ SCP_BASIC; HVNCAT_STATIC_RULE; - ORTHO_INV_RULE; ] const SCP_OPTIONS = Dict(:basic => SCP_BASIC, From 03d617bfa58aca05b6b5cead02a8807946dcf125 Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Wed, 28 Jan 2026 14:06:06 +0000 Subject: [PATCH 07/10] test: check SCP lowering works as expected --- test/structural_transformation/index_reduction.jl | 1 + test/structural_transformation/tearing.jl | 2 ++ 2 files changed, 3 insertions(+) diff --git a/test/structural_transformation/index_reduction.jl b/test/structural_transformation/index_reduction.jl index 41b0290e92..e65e07f052 100644 --- a/test/structural_transformation/index_reduction.jl +++ b/test/structural_transformation/index_reduction.jl @@ -82,4 +82,5 @@ let sol = solve(prob, Rodas5P()) @test SciMLBase.successful_retcode(sol) @test sol[x^2 + y^2][end] < 1.1 + @test_throws ArgumentError ODEProblem(sys, [x => 1, y => 0, D(x) => 0.0, g => 1], (0.0, 10.0), guesses = [λ => 0.0], optimize = 7) end diff --git a/test/structural_transformation/tearing.jl b/test/structural_transformation/tearing.jl index 725bfa325f..3554d45fb9 100644 --- a/test/structural_transformation/tearing.jl +++ b/test/structural_transformation/tearing.jl @@ -219,6 +219,8 @@ prob_complex = ODEProblem(sys, u0, (0, 1.0)) sol = solve(prob_complex, Tsit5()) @test all(sol[mass.v] .== 1) +@test_throws ArgumentError ODEProblem(sys, u0, (0, 1.0), optimize = 7) + using ModelingToolkitStandardLibrary.Electrical using ModelingToolkitStandardLibrary.Blocks: Constant From 106d67e30956dfbb27b6997c7273bcba4109c124 Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Wed, 28 Jan 2026 14:06:39 +0000 Subject: [PATCH 08/10] chore: qualfy names --- src/systems/codegen.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/systems/codegen.jl b/src/systems/codegen.jl index 6dae61ccce..fc8a19cd32 100644 --- a/src/systems/codegen.jl +++ b/src/systems/codegen.jl @@ -595,21 +595,21 @@ const SCP_OPTIONS = Dict(:basic => SCP_BASIC, ) function MTKBase.resolve_optimize_option(o::Bool) - resolve_optimize_option(o ? SCP_BASIC : nothing) + MTKBase.resolve_optimize_option(o ? SCP_BASIC : nothing) end function MTKBase.resolve_optimize_option(o::Symbol) rules = get(SCP_OPTIONS, o, nothing) - resolve_optimize_option(rules) + MTKBase.resolve_optimize_option(rules) end function MTKBase.resolve_optimize_option(o::Int) if o == 0 - return resolve_optimize_option(false) + return MTKBase.resolve_optimize_option(false) elseif o == 1 - return resolve_optimize_option(:basic) + return MTKBase.resolve_optimize_option(:basic) elseif o == 2 - return resolve_optimize_option(:aggressive) + return MTKBase.resolve_optimize_option(:aggressive) end throw(ArgumentError("Invalid optimize option integer: $o")) end \ No newline at end of file From 3a702d9a9d7f609db919b3e772c00fbb18a61039 Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Thu, 29 Jan 2026 07:42:35 +0000 Subject: [PATCH 09/10] build: bump minimum SU --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 268dcb8a8f..c2aff6ac2b 100644 --- a/Project.toml +++ b/Project.toml @@ -110,7 +110,7 @@ StochasticDelayDiffEq = "1.11" StochasticDiffEq = "6.82.0" SymbolicIndexingInterface = "0.3.39" SymbolicCompilerPasses = "0.1.0" -SymbolicUtils = "4.11" +SymbolicUtils = "4.13" Symbolics = "7" UnPack = "0.1, 1.0" julia = "1.9" From eab24fd5ed42a877732d7b9fce1d1cb96ddd6787 Mon Sep 17 00:00:00 2001 From: Dhairya Gandhi Date: Thu, 29 Jan 2026 11:22:27 +0000 Subject: [PATCH 10/10] chore: formatting --- src/systems/codegen.jl | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/systems/codegen.jl b/src/systems/codegen.jl index fc8a19cd32..14223590a4 100644 --- a/src/systems/codegen.jl +++ b/src/systems/codegen.jl @@ -589,18 +589,19 @@ const SCP_AGGRESSIVE = [ HVNCAT_STATIC_RULE; ] -const SCP_OPTIONS = Dict(:basic => SCP_BASIC, - :aggressive => SCP_AGGRESSIVE, - :none => nothing - ) +const SCP_OPTIONS = Dict( + :basic => SCP_BASIC, + :aggressive => SCP_AGGRESSIVE, + :none => nothing +) function MTKBase.resolve_optimize_option(o::Bool) - MTKBase.resolve_optimize_option(o ? SCP_BASIC : nothing) + return MTKBase.resolve_optimize_option(o ? SCP_BASIC : nothing) end function MTKBase.resolve_optimize_option(o::Symbol) rules = get(SCP_OPTIONS, o, nothing) - MTKBase.resolve_optimize_option(rules) + return MTKBase.resolve_optimize_option(rules) end function MTKBase.resolve_optimize_option(o::Int) @@ -612,4 +613,4 @@ function MTKBase.resolve_optimize_option(o::Int) return MTKBase.resolve_optimize_option(:aggressive) end throw(ArgumentError("Invalid optimize option integer: $o")) -end \ No newline at end of file +end