ModelingToolkit.jl
ModelingToolkit.jl copied to clipboard
Sanity type-checking for equations
Guess where the error message happens from in this snippet:
using ModelingToolkit
@variables t x(t)
@parameters a = 1
D = Differential(t)
Dx = D(x)
eqs = [ Dx ~ "a"] # Ooopsy....
sys = ODESystem(eqs, name = :sys)
p = [a]
tspan = [0, 1]
u0 = [1]
prob = ODEProblem(sys, u0, tspan p)
sol = solve(prob, Tsit5())
Error message
On the final line, the generated function tries to assign a string to a float.
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Float64
Closest candidates are:
convert(::Type{R}, ::T) where {R<:Real, T<:ReverseDiff.TrackedReal} at C:\Users\lucas\.julia\packages\ReverseDiff\5MMPp\src\tracked.jl:260
convert(::Type{T}, ::Gain) where T<:Real at C:\Users\lucas\.julia\packages\Unitful\SUQzL\src\logarithm.jl:62
convert(::Type{T}, ::Level) where T<:Real at C:\Users\lucas\.julia\packages\Unitful\SUQzL\src\logarithm.jl:22
...
Stacktrace:
[1] setindex!(A::Vector{Float64}, x::String, i1::Int64)
@ Base .\array.jl:966
[2] macro expansion
@ C:\Users\lucas\.julia\packages\SymbolicUtils\qulQp\src\code.jl:394 [inlined]
[3] macro expansion
@ C:\Users\lucas\.julia\packages\Symbolics\J8IHJ\src\build_function.jl:504 [inlined]
[4] macro expansion
@ C:\Users\lucas\.julia\packages\SymbolicUtils\qulQp\src\code.jl:351 [inlined]
[5] macro expansion
@ C:\Users\lucas\.julia\packages\RuntimeGeneratedFunctions\KrkGo\src\RuntimeGeneratedFunctions.jl:129 [inlined]
[6] macro expansion
@ .\none:0 [inlined]
[7] generated_callfunc
@ .\none:0 [inlined]
[8] (::RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)})(::Vector{Float64}, ::Vector{Float64}, ::Vector{Num}, ::Float64)
@ RuntimeGeneratedFunctions C:\Users\lucas\.julia\packages\RuntimeGeneratedFunctions\KrkGo\src\RuntimeGeneratedFunctions.jl:117
[9] (::ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}})(du::Vector{Float64}, u::Vector{Float64}, p::Vector{Num}, t::Float64)
@ ModelingToolkit C:\Users\lucas\Documents\Code\Jdev\ModelingToolkit\src\systems\diffeqs\abstractodesystem.jl:268
[10] (::ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem})(::Vector{Float64}, ::Vararg{Any})
@ SciMLBase C:\Users\lucas\.julia\packages\SciMLBase\UY87O\src\scimlfunctions.jl:1655
[11] initialize!(integrator::OrdinaryDiffEq.ODEIntegrator{Tsit5{typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False}, true, Vector{Float64}, Nothing, Float64, Vector{Num}, Float64, Float64, Float64, Float64, Vector{Vector{Float64}}, ODESolution{Float64, 2, Vector{Vector{Float64}}, Nothing, Nothing, Vector{Float64}, Vector{Vector{Vector{Float64}}}, ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Vector{Num}, ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing,
Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, SciMLBase.StandardODEProblem}, Tsit5{typeof(OrdinaryDiffEq.trivial_limiter!),
typeof(OrdinaryDiffEq.trivial_limiter!), Static.False}, OrdinaryDiffEq.InterpolationData{ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem},
Vector{Vector{Float64}}, Vector{Float64}, Vector{Vector{Vector{Float64}}}, OrdinaryDiffEq.Tsit5Cache{Vector{Float64}, Vector{Float64}, Vector{Float64}, OrdinaryDiffEq.Tsit5ConstantCache{Float64, Float64}, typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False}}, DiffEqBase.DEStats}, ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem}, OrdinaryDiffEq.Tsit5Cache{Vector{Float64}, Vector{Float64}, Vector{Float64}, OrdinaryDiffEq.Tsit5ConstantCache{Float64, Float64}, typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False}, OrdinaryDiffEq.DEOptions{Float64, Float64, Float64, Float64, PIController{Rational{Int64}}, typeof(DiffEqBase.ODE_DEFAULT_NORM), typeof(LinearAlgebra.opnorm), Nothing, CallbackSet{Tuple{}, Tuple{}}, typeof(DiffEqBase.ODE_DEFAULT_ISOUTOFDOMAIN), typeof(DiffEqBase.ODE_DEFAULT_PROG_MESSAGE), typeof(DiffEqBase.ODE_DEFAULT_UNSTABLE_CHECK), DataStructures.BinaryHeap{Float64, DataStructures.FasterForward}, DataStructures.BinaryHeap{Float64, DataStructures.FasterForward}, Nothing, Nothing, Int64, Tuple{}, Tuple{}, Tuple{}}, Vector{Float64}, Float64, Nothing, OrdinaryDiffEq.DefaultInit}, cache::OrdinaryDiffEq.Tsit5Cache{Vector{Float64}, Vector{Float64}, Vector{Float64}, OrdinaryDiffEq.Tsit5ConstantCache{Float64, Float64}, typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False})
@ OrdinaryDiffEq C:\Users\lucas\.julia\packages\OrdinaryDiffEq\gCvy4\src\perform_step\low_order_rk_perform_step.jl:627
[12] __init(prob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Vector{Num}, ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, SciMLBase.StandardODEProblem}, alg::Tsit5{typeof(OrdinaryDiffEq.trivial_limiter!),
typeof(OrdinaryDiffEq.trivial_limiter!), Static.False}, timeseries_init::Tuple{}, ts_init::Tuple{}, ks_init::Tuple{}, recompile::Type{Val{true}}; saveat::Tuple{}, tstops::Tuple{}, d_discontinuities::Tuple{}, save_idxs::Nothing, save_everystep::Bool, save_on::Bool, save_start::Bool, save_end::Nothing, callback::Nothing, dense::Bool, calck::Bool, dt::Float64, dtmin::Nothing, dtmax::Float64, force_dtmin::Bool, adaptive::Bool, gamma::Rational{Int64}, abstol::Nothing, reltol::Nothing, qmin::Rational{Int64}, qmax::Int64, qsteady_min::Int64, qsteady_max::Int64, beta1::Nothing, beta2::Nothing, qoldinit::Rational{Int64}, controller::Nothing, fullnormalize::Bool, failfactor::Int64, maxiters::Int64, internalnorm::typeof(DiffEqBase.ODE_DEFAULT_NORM), internalopnorm::typeof(LinearAlgebra.opnorm), isoutofdomain::typeof(DiffEqBase.ODE_DEFAULT_ISOUTOFDOMAIN), unstable_check::typeof(DiffEqBase.ODE_DEFAULT_UNSTABLE_CHECK), verbose::Bool, timeseries_errors::Bool, dense_errors::Bool, advance_to_tstop::Bool, stop_at_next_tstop::Bool, initialize_save::Bool, progress::Bool, progress_steps::Int64, progress_name::String, progress_message::typeof(DiffEqBase.ODE_DEFAULT_PROG_MESSAGE), userdata::Nothing, allow_extrapolation::Bool, initialize_integrator::Bool, alias_u0::Bool, alias_du0::Bool, initializealg::OrdinaryDiffEq.DefaultInit, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ OrdinaryDiffEq C:\Users\lucas\.julia\packages\OrdinaryDiffEq\gCvy4\src\solve.jl:454
[13] __init (repeats 5 times)
@ C:\Users\lucas\.julia\packages\OrdinaryDiffEq\gCvy4\src\solve.jl:9 [inlined]
[14] #__solve#562
@ C:\Users\lucas\.julia\packages\OrdinaryDiffEq\gCvy4\src\solve.jl:4 [inlined]
[15] __solve
@ C:\Users\lucas\.julia\packages\OrdinaryDiffEq\gCvy4\src\solve.jl:1 [inlined]
[16] #solve_call#24
@ C:\Users\lucas\.julia\packages\DiffEqBase\WDtlB\src\solve.jl:451 [inlined]
[17] solve_call(_prob::ODEProblem{Vector{Float64}, Tuple{Float64, Float64}, true, Vector{Num}, ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing,
Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, SciMLBase.StandardODEProblem}, args::Tsit5{typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False})
@ DiffEqBase C:\Users\lucas\.julia\packages\DiffEqBase\WDtlB\src\solve.jl:421
[18] solve_up(prob::ODEProblem{Vector{Float64}, Tuple{Int64, Int64}, true, Vector{Num}, ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d, 0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem},
Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, SciMLBase.StandardODEProblem}, sensealg::Nothing, u0::Vector{Float64}, p::Vector{Num}, args::Tsit5{typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
@ DiffEqBase C:\Users\lucas\.julia\packages\DiffEqBase\WDtlB\src\solve.jl:814
[19] solve_up
@ C:\Users\lucas\.julia\packages\DiffEqBase\WDtlB\src\solve.jl:787 [inlined]
[20] #solve#29
@ C:\Users\lucas\.julia\packages\DiffEqBase\WDtlB\src\solve.jl:784 [inlined]
[21] solve(prob::ODEProblem{Vector{Float64}, Tuple{Int64, Int64}, true, Vector{Num}, ODEFunction{true, ModelingToolkit.var"#f#462"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc8f06a07, 0xff73569b, 0x165df38c, 0xd1c8f94f, 0x48d5ca6e)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x1eb0efba, 0xf6ec394d,
0xa23bcd8c, 0xca8ff638, 0x06028518)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#472#generated_observed#469"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}, SciMLBase.StandardODEProblem}, args::Tsit5{typeof(OrdinaryDiffEq.trivial_limiter!), typeof(OrdinaryDiffEq.trivial_limiter!), Static.False})
@ DiffEqBase C:\Users\lucas\.julia\packages\DiffEqBase\WDtlB\src\solve.jl:767
[22] top-level scope
@ REPL[101]:1
In more realistic cases, some transformation/validation is going to choke first. It would be nice to have some guarantees about what's coming down the pipe to those things. Also, then the error message would point to the real problem. (I have unit validation in mind, but I'm sure structural_simplify
has expectations about the types of terms in equations as well.)
This could be handled via a type constraint on Equation
https://github.com/JuliaSymbolics/Symbolics.jl/blob/ab7e1aa725f5599e1fb9a9b6e76beb5e392f820c/src/equations.jl#L33-L37
Upstream issue. Tracking in Symbolics