Symbols and variables

The following code fails:

using ModelingToolkit

@variables t
@syms ω(t) Pgc(t)
@variables R a b ρ U J A s

struct Equilibrium
    a_bar
    b_bar
    pg_bar    # generator power
    ω_bar     # rotor speed
end

mutable struct Settings
    ρ0::Float64
    U0::Float64
    A0::Float64
    R0::Float64
    J0::Float64
end

se::Settings = Settings(1.225, 7.0, 12469.0, 63.0, 4.047e7)
eq = Equilibrium(-0.012273163568697454, 0.5344744027433362, 1132254, 0.88612)
op_ = Dict([R => se.R0, ρ => se.ρ0,  A => se.A0, J => se.J0, U => se.U0, 
            Pgc(t) => eq.pg_bar, ω(t) => eq.ω_bar, a => eq.a_bar, b => eq.b_bar])

function model_turbine_symbolic()
    @variables t ω(t) Pr(t) λ(t) Pgc(t)
    @parameters J R ρ A U a b
    D = Differential(t)
    eqs = [D(ω)  ~ (Pr - Pgc) / (J * ω),
            0     ~ ω * R/U - λ,
            0     ~ 0.5 * ρ * A * U^3 * (a*λ + b) - Pr]
    @named sys = ODESystem(eqs, t)
    sys, Pgc, ω
end

function calc_lin_numeric()
    sys, Pgc, ω = model_turbine_symbolic()
    matrices, simplified_sys = ModelingToolkit.linearize(sys, [Pgc], [ω], op=op_)
    A_, B, C, D = matrices
    A_[2]
end

println("Numeric linearization:  ", calc_lin_numeric())

Error message:

julia> include("mwes\\mwe16.jl")
ERROR: LoadError: ArgumentError: SymbolicUtils.BasicSymbolic[ω(t)] are missing from the variable map.
Stacktrace:
  [1] throw_missingvars(vars::Vector{SymbolicUtils.BasicSymbolic})
    @ ModelingToolkit C:\Users\uwefechner\.julia\packages\ModelingToolkit\rrbUl\src\variables.jl:121
  [2] _varmap_to_vars(varmap::Dict{Any, Any}, varlist::Vector{SymbolicUtils.BasicSymbolic{Real}}; defaults::Dict{Any, Any}, check::Bool, toterm::typeof(ModelingToolkit.default_toterm))
    @ ModelingToolkit C:\Users\uwefechner\.julia\packages\ModelingToolkit\rrbUl\src\variables.jl:115
  [3] varmap_to_vars(varmap::Dict{Any, Any}, varlist::Vector{Any}; defaults::Dict{Any, Any}, check::Bool, toterm::Function, promotetoconcrete::Nothing, tofloat::Bool, use_union::Bool)
    @ ModelingToolkit C:\Users\uwefechner\.julia\packages\ModelingToolkit\rrbUl\src\variables.jl:84
  [4] get_u0_p(sys::ODESystem, u0map::Dict{Any, Any}, parammap::SciMLBase.NullParameters; use_union::Bool, tofloat::Bool)
    @ ModelingToolkit C:\Users\uwefechner\.julia\packages\ModelingToolkit\rrbUl\src\systems\diffeqs\abstractodesystem.jl:591
  [5] linearize(sys::ODESystem, lin_fun::ModelingToolkit.var"#132#135"{Vector{Num}, UnitRange{Int64}, UnitRange{Int64}, UnitRange{Int64}, Vector{Any}, ODEFunction{true, SciMLBase.FullSpecialize, ModelingToolkit.var"#f#533"{RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xd4d85126, 0x18aadede, 0x17a09b22, 0x02577da8, 0x2c5f5169), Nothing}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(:ˍ₋out, :ˍ₋arg1, :ˍ₋arg2, :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0x30918c58, 0xe8de3e77, 0xb7bd31f3, 0x4caf8f90, 0x996d4b0b), Nothing}}, LinearAlgebra.UniformScaling{Bool}, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Nothing, Vector{Symbol}, Symbol, Vector{Symbol}, ModelingToolkit.var"#583#generated_observed#541"{Bool, ODESystem, Dict{Any, Any}}, Nothing, ODESystem}, RuntimeGeneratedFunctions.RuntimeGeneratedFunction{(Symbol("##arg#5403431765531858355"), Symbol("##arg#3669817888844577317"), :t), ModelingToolkit.var"#_RGF_ModTag", ModelingToolkit.var"#_RGF_ModTag", (0xc4eb96ba, 0x09fdb654, 0x41bf9ba7, 0xc49409ef, 0x508b1e9f), Nothing}, ForwardDiff.Chunk{1}}; t::Float64, op::Dict{Num, Float64}, allow_input_derivatives::Bool, p::SciMLBase.NullParameters)
    @ ModelingToolkit C:\Users\uwefechner\.julia\packages\ModelingToolkit\rrbUl\src\systems\abstractsystem.jl:1518
  [6] linearize(sys::ODESystem, inputs::Vector{Num}, outputs::Vector{Num}; op::Dict{Num, Float64}, t::Float64, allow_input_derivatives::Bool, zero_dummy_der::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ ModelingToolkit C:\Users\uwefechner\.julia\packages\ModelingToolkit\rrbUl\src\systems\abstractsystem.jl:1570
  [7] calc_lin_numeric()
    @ Main C:\Users\uwefechner\repos\WindTurbines\mwes\mwe16.jl:40
  [8] top-level scope
    @ C:\Users\uwefechner\repos\WindTurbines\mwes\mwe16.jl:45
  [9] include(fname::String)
    @ Base.MainInclude .\client.jl:478
 [10] top-level scope
    @ REPL[1]:1
in expression starting at C:\Users\uwefechner\repos\WindTurbines\mwes\mwe16.jl:45

Any idea why?

I assume that I do not make the correct use of variables and symbols, but how can I use them correctly?

Is there a difference between the symbol ω(t) and the variable ω(t), and if yes what is the difference?

I was able to fix the example by not using @syms to define ω(t). I used it in the first place because an error message suggested it when I used ω(t) => eq.ω_bar in the dictionary. I have to use just ω here. Still not fully clear to me when I have to use ω(t) and when ω

using ModelingToolkit, ControlSystemsBase

@variables t ω(t) Pgc(t)
@variables R a b ρ U J A s

struct Equilibrium
    a_bar
    b_bar
    pg_bar    # generator power
    ω_bar     # rotor speed
end

mutable struct Settings
    ρ0::Float64
    U0::Float64
    A0::Float64
    R0::Float64
    J0::Float64
end

se::Settings = Settings(1.225, 7.0, 12469.0, 63.0, 4.047e7)
eq = Equilibrium(-0.012273163568697454, 0.5344744027433362, 1132254, 0.88612)
op_ = Dict([R => se.R0, ρ => se.ρ0,  A => se.A0, J => se.J0, U => se.U0, 
            Pgc => eq.pg_bar, ω => eq.ω_bar, a => eq.a_bar, b => eq.b_bar])

function model_turbine_symbolic()
    @variables t ω(t) Pr(t) λ(t) Pgc(t)
    @parameters J R ρ A U a b
    D = Differential(t)
    eqs = [D(ω)  ~ (Pr - Pgc) / (J * ω),
            0     ~ ω * R/U - λ,
            0     ~ 0.5 * ρ * A * U^3 * (a*λ + b) - Pr]
    @named sys = ODESystem(eqs, t)
    sys, Pgc, ω
end

function calc_lin_numeric()
    sys, Pgc, ω = model_turbine_symbolic()
    matrices, simplified_sys = ModelingToolkit.linearize(sys, [Pgc], [ω], op=op_)
    A_, B, C, D = matrices
    A_[1]
end

function calc_lin_symbolic(num=true)
    sys, Pgc, ω = model_turbine_symbolic()
    matrices, simplified_sys = ModelingToolkit.linearize_symbolic(sys, [Pgc], [ω])
    A_, B, C, D = matrices
    if num; return substitute(A_[1], op_); else return A_[1] end
end

println("Symbolic linearization: ", calc_lin_symbolic(false))
println("Symbolic linearization, numeric result: ", calc_lin_symbolic())
println("Numeric linearization:  ", calc_lin_numeric())

which has the output:

julia> include("mwes\\mwe16.jl")
Symbolic linearization: (0.5A*R*(U^2)*a*ρ) / (J*ω(t)) - J*((-Pgc(t) + 0.5A*(U^3)*(b + (R*a*ω(t)) / U)*ρ) / ((J^2)*(ω(t)^2)))
Symbolic linearization, numeric result: -0.008428790869465188
Numeric linearization:  -0.008428790869465188
1 Like

If you declare a variable like

@variables t ω(t)

then you should generally use it in equations and mappings as just ω. It will implicitly know it is ω(t).

The one time you might need to specify the arguments is if you declared it with unbounded arguments like

@variables ω(...)

then you will always need to say ω(t) when using it to make clear the arguments. This representation is only used by the PDE packages like MethodOfLines as far as I am aware (and is an unfortunate inconsistency).

1 Like

And when should I use @syms instead of @variables ?

Never as far as I am aware. That is a much lower-level macro from SymbolicUtils that ModelingToolkit users should not ever need to use. Just use @variables and @parameters.

1 Like

But then the error message that suggests to use @syms if you accidentally write ω(t) instead of ω is misleading…

1 Like

Sounds like that is worth opening an issue on ModelingToolkit about then. Seems like a lower-level error from SymbolicUtils is being propagated up in this case instead of a more helpful message being generated in ModelingToolkit.

4 Likes