Skip to content

Commit 687dc7f

Browse files
committed
feat(mtkmodel): handle unit conversion for array inputs
1 parent 98471b6 commit 687dc7f

File tree

1 file changed

+39
-15
lines changed

1 file changed

+39
-15
lines changed

src/systems/model_parsing.jl

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,16 @@ function update_kwargs_and_metadata!(dict, kwargs, a, def, indices, type, var,
180180
end
181181
end
182182

183+
function unit_handled_variable_value(mod, y, varname)
184+
meta = parse_metadata(mod, y)
185+
varval = if meta isa Nothing || get(meta, VariableUnit, nothing) isa Nothing
186+
varname
187+
else
188+
:($convert_units($(meta[VariableUnit]), $varname))
189+
end
190+
return varval
191+
end
192+
183193
function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
184194
def = nothing, indices::Union{Vector{UnitRange{Int}}, Nothing} = nothing,
185195
type::Type = Real, meta = Dict{DataType, Expr}())
@@ -225,27 +235,29 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
225235
Expr(:tuple, Expr(:ref, a, b...), y) => begin
226236
varname = Meta.isexpr(a, :call) ? a.args[1] : a
227237
push!(kwargs, Expr(:kw, varname, nothing))
238+
varval = unit_handled_variable_value(mod, y, varname)
228239
if varclass == :parameters
229-
var = :($varname = $first(@parameters $a[$(b...)] = ($varname, $y)))
240+
var = :($varname = $first(@parameters $a[$(b...)] = ($varval, $y)))
230241
else
231-
var = :($varname = $first(@variables $a[$(b...)] = ($varname, $y)))
242+
var = :($varname = $first(@variables $a[$(b...)] = ($varval, $y)))
232243
end
233244
#TODO: update `dict` aka `Model.structure` with the metadata
234245
(:($varname...), var), nothing, Dict()
235246
end
236247
Expr(:(=), Expr(:ref, a, b...), y) => begin
237248
varname = Meta.isexpr(a, :call) ? a.args[1] : a
238249
if Meta.isexpr(y, :tuple)
250+
varval = unit_handled_variable_value(mod, y, varname)
239251
val, y = (y.args[1], y.args[2:end])
240252
push!(kwargs, Expr(:kw, varname, nothing))
241253
if varclass == :parameters
242254
var = :($varname = $varname === nothing ? $val : $varname;
243255
$varname = $first(@parameters $a[$(b...)] = (
244-
$varname, $(y...))))
256+
$varval, $(y...))))
245257
else
246258
var = :($varname = $varname === nothing ? $val : $varname;
247259
$varname = $first(@variables $a[$(b...)] = (
248-
$varname, $(y...))))
260+
$varval, $(y...))))
249261
end
250262
else
251263
push!(kwargs, Expr(:kw, varname, nothing))
@@ -260,37 +272,37 @@ function parse_variable_def!(dict, mod, arg, varclass, kwargs, where_types;
260272
end
261273
Expr(:(=), Expr(:(::), Expr(:ref, a, b...), n), y) => begin
262274
varname = Meta.isexpr(a, :call) ? a.args[1] : a
275+
varval = unit_handled_variable_value(mod, y, varname)
263276
if Meta.isexpr(y, :tuple)
264277
val, y = (y.args[1], y.args[2:end])
265278
push!(kwargs, Expr(:kw, varname, nothing))
266279
if varclass == :parameters
267-
var = :(
268-
$varname = $varname = $varname === nothing ? $val : $varname;
269-
$varname = $first(@parameters $a[$(b...)]::$n = ($varname, $(y...)))
270-
)
280+
var = :($varname = $varname = $varname === nothing ? $val : $varname;
281+
$varname = $first(@parameters $a[$(b...)]::$n = ($varval, $(y...))))
271282
else
272283
var = :($varname = $varname === nothing ? $val : $varname;
273284
$varname = $first(@variables $a[$(b...)]::$n = (
274-
$varname, $(y...))))
285+
$varval, $(y...))))
275286
end
276287
else
277288
push!(kwargs, Expr(:kw, varname, y))
278289
if varclass == :parameters
279-
var = :($varname = $first(@parameters $a[$(b...)]::$n = $varname))
290+
var = :($varname = $first(@parameters $a[$(b...)]::$n = $varval))
280291
else
281-
var = :($varname = $first(@variables $a[$(b...)]::$n = $varname))
292+
var = :($varname = $first(@variables $a[$(b...)]::$n = $varval))
282293
end
283294
end
284295
#TODO: update `dict`` aka `Model.structure` with the metadata
285296
(:($varname...), var), nothing, Dict()
286297
end
287298
Expr(:tuple, Expr(:(::), Expr(:ref, a, b...), n), y) => begin
288299
varname = Meta.isexpr(a, :call) ? a.args[1] : a
300+
varval = unit_handled_variable_value(mod, y, varname)
289301
push!(kwargs, Expr(:kw, varname, nothing))
290302
if varclass == :parameters
291-
var = :($varname = $first(@parameters $a[$(b...)]::$n = ($varname, $y)))
303+
var = :($varname = $first(@parameters $a[$(b...)]::$n = ($varval, $y)))
292304
else
293-
var = :($varname = $first(@variables $a[$(b...)]::$n = ($varname, $y)))
305+
var = :($varname = $first(@variables $a[$(b...)]::$n = ($varval, $y)))
294306
end
295307
#TODO: update `dict` aka `Model.structure` with the metadata
296308
(:($varname...), var), nothing, Dict()
@@ -465,14 +477,24 @@ function parse_default(mod, a)
465477
end
466478
end
467479

468-
function parse_metadata(mod, a)
480+
function parse_metadata(mod, a::Expr)
481+
@info a typeof(a)
469482
MLStyle.@match a begin
470-
Expr(:vect, eles...) => Dict(parse_metadata(mod, e) for e in eles)
483+
Expr(:vect, b...) => Dict(parse_metadata(mod, m) for m in b)
484+
Expr(:tuple, a, b...) => parse_metadata(mod, b)
471485
Expr(:(=), a, b) => Symbolics.option_to_metadata_type(Val(a)) => get_var(mod, b)
472486
_ => error("Cannot parse metadata $a")
473487
end
474488
end
475489

490+
function parse_metadata(mod, metadata::AbstractArray)
491+
ret = Dict()
492+
for m in metadata
493+
merge!(ret, parse_metadata(mod, m))
494+
end
495+
ret
496+
end
497+
476498
function _set_var_metadata!(metadata_with_exprs, a, m, v::Expr)
477499
push!(metadata_with_exprs, m => v)
478500
a
@@ -730,6 +752,7 @@ function parse_variable_arg!(exprs, vs, dict, mod, arg, varclass, kwargs, where_
730752
end
731753

732754
function convert_units(varunits::DynamicQuantities.Quantity, value)
755+
value isa Nothing && return nothing
733756
DynamicQuantities.ustrip(DynamicQuantities.uconvert(
734757
DynamicQuantities.SymbolicUnits.as_quantity(varunits), value))
735758
end
@@ -741,6 +764,7 @@ function convert_units(
741764
end
742765

743766
function convert_units(varunits::Unitful.FreeUnits, value)
767+
value isa Nothing && return nothing
744768
Unitful.ustrip(varunits, value)
745769
end
746770

0 commit comments

Comments
 (0)