SciML / ModelingToolkit.jl

An acausal modeling framework for automatically parallelized scientific machine learning (SciML) in Julia. A computer algebra system for integrated symbolics for physics-informed machine learning and automated transformations of differential equations
https://mtk.sciml.ai/dev/
Other
1.43k stars 209 forks source link

Creating variables that are vectors of symbolic variables is not documented #956

Open BenChung opened 3 years ago

BenChung commented 3 years ago

In order to create a symbolic vector, the notation

@variables x[1:2](t)

needs to be used (using @variables as an example). This doesn't appear in the documentation for ModelingToolkit (in an example, for instance), though it is described in the docstring from Symbolics.jl. It would be clearer if there was some example in the documentation that demonstrated a simple use case of @variables with a symbolic vector.

Additionally, the error message that's produced when a scalar variable is passed a vector argument is unclear, for example,

using ModelingToolkit
@variables t x(t) RHS(t) 
@parameters τ       
D = Differential(t) 
# your first ODE, consisting of a single equation, indicated by ~
@named @named fol_separate = ODESystem([ RHS  ~ (1 - x)/τ,
                                         D(x) ~ RHS ])
using DifferentialEquations: solve
prob = ODEProblem(structural_simplify(fol_separate), [x => [0.0, 0.0]], (0.0,10.0), [τ => 3.0])
solve(prob) 

produces

ERROR: MethodError: no method matching zero(::Type{Vector{Float64}})
Closest candidates are:
  zero(::Union{Type{P}, P}) where P<:Dates.Period at C:\buildbot\worker\package_win64\build\usr\share\julia\stdlib\v1.6\Dates\src\periods.jl:53
  zero(::AbstractAlgebra.MatrixElem{T} where T) at C:\Users\Ben Chung\.julia\packages\AbstractAlgebra\6JkeN\src\generic\Matrix.jl:232
  zero(::AbstractAlgebra.MatrixElem{T} where T, ::AbstractAlgebra.Ring) at C:\Users\Ben Chung\.julia\packages\AbstractAlgebra\6JkeN\src\generic\Matrix.jl:232
  ...
Stacktrace:
  [1] zero(x::Vector{Vector{Float64}})
    @ Base .\abstractarray.jl:1085
  [2] alg_cache(alg::OrdinaryDiffEq.Vern9, u::Vector{Vector{Float64}}, rate_prototype::Vector{Vector{Float64}}, uEltypeNoUnits::Type, uBottomEltypeNoUnits::Type, tTypeNoUnits::Type, uprev::Vector{Vector{Float64}}, uprev2::Vector{Vector{Float64}}, f::WARNING: both SymbolicUtils and LinearAlgebra export "cond"; uses of it in module Symbolics must be qualified
ODEFunction{true, ModelingToolkit.var"#f#140"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(Symbol("##arg#257"), Symbol("##arg#258"), :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x9d679005, 0xf9e93d3d, 0xde33153c, 0x87232e20, 0xd9de51d2)}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(Symbol("##out#259"), Symbol("##arg#257"), Symbol("##arg#258"), :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x3159e5b6, 0xdb5210ba, 0x212b43ea, 0x1f3d7d71, 0xb1165cc1)}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, ModelingToolkit.var"#generated_observed#145"{ODESystem, Dict{Any, Any}}, Nothing}, t::Float64, dt::Float64, reltol::Float64, p::Vector{Float64}, calck::Bool, #unused#::Val{true})
    @ OrdinaryDiffEq ~\.julia\packages\OrdinaryDiffEq\5egkj\src\caches\verner_caches.jl:153

(snipping the stack trace). This error suggests that the problem is initialization of the integrator cache, rather than in the definition of the problem; it would make it easier to understand and fix if the problem could be caught before attempting to initialize the integrator.

YingboMa commented 3 years ago
@named fol_separate = ODESystem([ RHS  ~ (1 - x)/τ,
                                                                 D(x) ~ RHS ])
prob = ODEProblem(structural_simplify(fol_separate), [x=>0.0, RHS=>0.0], (0.0,10.0), [τ => 3.0])
BenChung commented 3 years ago

This doesn't address the issue? Yes, there are a number of ways to solve this particular problem (I'd note, tangentially, that the shown isn't exactly one of them; the desired result is where x is a vector of size 2. I'm aware of these approaches, but the most elegant of them - the aforementioned @variables x[1:2](t) isn't mentioned in the documentation.

I'm not claiming a functional issue here. Instead, I'm pointing out that the documentation doesn't do a good job of describing how to have vectors of symbolic variables in the system, and that the error messages surrounding one obvious way to do so (where one assumes that vectors work implicitly) do not point the user in a direction where they may find this solution.

asprionj commented 3 years ago

There's other issues with vector symbolics, cf. for example #892. Documentation should be included for the new, clean way of handling vectors that's indicated in the referenced issue (?)

ChrisRackauckas commented 3 years ago

Yeah, I'd note that all of these cases need to get documented, but we also should be making all of it towards the coming array symbolics system and not what we have now.

ChrisRackauckas commented 9 months ago

It's now better documented https://symbolics.juliasymbolics.org/stable/manual/arrays/ but we should make a whole MTK level tutorial on this.