TinyModia.jl
TinyModia.jl copied to clipboard
support for parameter vectors in Model
I created a Model that starts like this:
SingleTrackModel = Model(
inputs = :[delta,T_F,T_R],
m = 1450,
I_z = 1.0,
l_F = 1.1,
l_R = 1.59,
h = 0.4,
I_w = [1.8, 1.8],
...
Now in the equations
section, I cannot access elements of parameters I_w
using I_w[ind...]
. A tested workaround I found is to use getindex(I_w, ind...)
instead. However, neither does I_w
show up in field parametersAndConstantVariables
of the instantiated model, nor can I spot its contents in the field p
.
However I would like to alter p
after model instantiation (machine learning purposes).
Is there any supported and intended way to use and alter parameters in arrays?
It would have been better if you would have provided a complete example illustrating the problem. I successfully tested the following model in my development version:
using TinyModia
using ModiaPlot
SingleTrackModel = Model(
# inputs = :[delta,T_F,T_R],
m = 1450,
I_z = 1.0,
l_F = 1.1,
l_R = 1.59,
h = 0.4,
I_w = [1.8, 2.8],
equations = :[
I_w_2 = I_w[2...]
]
)
model = @instantiateModel(SingleTrackModel, log=true, logCode=true)
simulate!(model)
plot(model, "I_w_2")
So I might have misunderstood you. BTW, why do you want to use: I_w[ind...]
It should be possible to use parameter arrays and also change them in the simulate! call without redoing the symbolic transformation (under development, coming to main soon).
So I created a minimal but complete demonstration:
using TinyModia
function simandprint!(model)
simulate!(model)
println("
m = $(model.p[1])
x starts at $(get_result(model, "x")[1]) and ends at $(get_result(model, "x")[end])
")
end
MinimalModel = Model(
m = 2.0,
pv = [3.0, 5.0],
init = Map(x=2.0),
equations = :[
#der(x) = m*p[1]*p[2] # THIS LINE does not work
der(x) = m*getindex(pv, 1)*getindex(pv, 2) # I have to use getindex() instead
]
)
model = @instantiateModel(MinimalModel)
println("model.p: $(model.p)")
println("model.paramatersAndConstantVariables: $(model.parametersAndConstantVariables)")
simandprint!(model)
# manual altering of a scalar parameter works BUT there is no way to change pv from here!
model.p[1] = 4.0
simandprint!(model)
I marked the relevant bits I was talking about using comments.
If I execute this, I cannot see pv
in the model parameters (which I am printing).
(I should mention that I am on [0169e107] TinyModia v0.7.1-dev `dev/TinyModia` )
I suppose yo meant:
der(x) = m*pv[1]*pv[2]
instead of
der(x) = m*p[1]*p[2]
and
model.p[1].pv[1] = 4.0
instead of
model.p[1] = 4.0
model.p is the root of the parameters. We are supporting changing (merging) parameters in the simulate! call .
You are right about your first remark (where I mixed up p
and pv
), this was a remainder of an earlier refactoring.
However, if I try to uncomment
#der(x) = m*pv[1]*pv[2] # THIS LINE does not work
,
I am getting the error:
AssertionError: Equation not solved for der(x): der(x) = m * pv[1] * pv[2] (::TinyModia.var"#getSolvedEquationAST#65"{Bool,Array{Any,1},Array{Any,1}})(::Int64, ::Int64) at TinyModia.jl:460 addSolvedEquations!(::ModiaBase.EquationGraph, ::Array{Int64,1}, ::Array{Int64,1}) at StateSelection.jl:858 getSortedAndSolvedAST(::Array{Array{Int64,1},1}, ::Array{Array{Int64,1},1}, ::Array{Int64,1}, ::Array{Int64,1}, ::Array{Int64,1}, ::ModiaBase.StateSelectionFunctions; log::Bool, logDetails::Bool, logStates::Bool, modelName::String, unitless::Bool, defaultParameterAndStartValues::Nothing) at StateSelection.jl:1247 getSortedAndSolvedAST at StateSelection.jl:1197 [inlined] stateSelectionAndCodeGeneration(::Tuple{Array{Any,1},Array{Any,1},Array{Array{Int64,1},1},Array{Int64,1},Array{Int64,1},Array{Int64,1},Array{Array{Int64,1},1},OrderedCollections.OrderedDict{Any,Any}}, ::String, ::Module, ::Type{T} where T, ::OrderedCollections.OrderedDict{Any,Any}, ::OrderedCollections.OrderedDict{Any,Any}, ::Array{Int64,1}, ::Array{Int64,1}, ::Array{Union{Expr, Symbol},1}; unitless::Bool, logStateSelection::Bool, logCode::Bool, logExecution::Bool, logTiming::Bool) at TinyModia.jl:588 (::TinyModia.var"#stateSelectionAndCodeGeneration##kw")(::NamedTuple{(:unitless, :logStateSelection, :logCode, :logExecution, :logTiming),NTuple{5,Bool}}, ::typeof(TinyModia.stateSelectionAndCodeGeneration), ::Tuple{Array{Any,1},Array{Any,1},Array{Array{Int64,1},1},Array{Int64,1},Array{Int64,1},Array{Int64,1},Array{Array{Int64,1},1},OrderedCollections.OrderedDict{Any,Any}}, ::String, ::Module, ::Type{T} where T, ::OrderedCollections.OrderedDict{Any,Any}, ::OrderedCollections.OrderedDict{Any,Any}, ::Array{Int64,1}, ::Array{Int64,1}, ::Array{Union{Expr, Symbol},1}) at TinyModia.jl:455 instantiateModel(::NamedTuple{(:m, :pv, :init, :equations),Tuple{Float64,Array{Float64,1},NamedTuple{(:x,),Tuple{Float64}},Expr}}; modelName::String, modelModule::Module, FloatType::Type{T} where T, aliasReduction::Bool, unitless::Bool, log::Bool, logModel::Bool, logDetails::Bool, logStateSelection::Bool, logCode::Bool, logExecution::Bool, logTiming::Bool) at TinyModia.jl:791 (::TinyModia.var"#instantiateModel##kw")(::NamedTuple{(:modelName, :modelModule),Tuple{String,Module}}, ::typeof(instantiateModel), ::NamedTuple{(:m, :pv, :init, :equations),Tuple{Float64,Array{Float64,1},NamedTuple{(:x,),Tuple{Float64}},Expr}}) at TinyModia.jl:711 top-level scope at demo.jl:33
Furthermore, model.p
is reported to be an Array{Float64,1}
which does not have a field named pv
so I do not understand that second remark of yours.
Also, line model.p[1] = 4.0
does exactly what I want: alter the behaviour of model.getDerivatives!
.
I am interested in getting model.getDerivatives!
to behave differently so that I can
- instantiate a model
- set a model parameter (possibly located in an array) to a desired value
- solve the model using an arbitrary code (in my case
solve
fromDifferentialEquations.jl
) - repeat 2. and 3. until the model does what I want it to
I'm appending a more relevant demonstration below:
using TinyModia
function simandprint!(model)
simulate!(model)
println("
m = $(model.p[1])
x starts at $(get_result(model, "x")[1]) and ends at $(get_result(model, "x")[end])
")
end
function print_derivatives!(derx, x0, model)
model.getDerivatives!(derx, x0, model, t0)
println("m = $(model.p[1]) => dx = $(derx)")
end
MinimalModel = Model(
m = 2.0,
pv = [3.0, 5.0],
init = Map(x=2.0),
equations = :[
#der(x) = m*pv[1]*pv[2] # THIS LINE does not work
der(x) = m*getindex(pv, 1)*getindex(pv, 2) # I have to use getindex() instead
]
)
model = @instantiateModel(MinimalModel)
println("model.p: $(model.p)")
println("model.paramatersAndConstantVariables: $(model.parametersAndConstantVariables)")
derx = zeros(1)
x0 = similar(derx)
t0 = 0.0
print_derivatives!(derx, x0, model)
#simandprint!(model)
# manual altering of a scalar parameter works BUT there is no way to change pv from here!
model.p[1] = 4.0
print_derivatives!(derx, x0, model)
#simandprint!(model)
You are right. I recently changed how parameters are passed. I tested in the branch "development". We want to make some more updates before merging to main. You might want to use development branch in the mean time.
Support for indexing was added in ModiaBase 11 days ago, so you might want to update.
Note that all TinyModia models can not be simulated directly with DifferentialEquations. The simulate! function of TinyModia is needed. Note that the workflow you indicated is now supported by an additional parameter merge
in simulate!. It takes a nested Map
modification for changing parameters.