Skip to content

Commit

Permalink
add convert_to_parameters macro
Browse files Browse the repository at this point in the history
  • Loading branch information
Datseris committed Feb 20, 2024
1 parent 4f47f48 commit 1c9c85c
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 20 deletions.
1 change: 1 addition & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,5 @@ ProcessBasedModelling.lhs
default_value
has_variable
new_derived_named_parameter
convert_to_parameters
```
2 changes: 1 addition & 1 deletion src/processes_basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
The simplest process which equates a given `variable` to a constant value
that is encapsulated in a parameter. If `value isa Real`, then
hence, a named parameter with the name of `variable` and `_0` appended is created.
a named parameter with the name of `variable` and `_0` appended is created.
Else, if `valua isa Num` then it is taken as the paremeter directly.
Example:
Expand Down
50 changes: 31 additions & 19 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,28 +68,40 @@ function new_derived_named_parameter(newstring::String, value::Real)
return first(dummy)
end

# Macro thanks to Jonas Isensee,
# https://discourse.julialang.org/t/metaprogramming-macro-calling-another-macro-making-named-variables/109621/6
"""
@named_parameters vars...
@convert_to_parameters vars...
Convert all Julia variables `vars` into `@parameters` with name the same as `vars`
and default value the same as the value of `vars`.
Convert all variables `vars` into `@parameters` with name the same as `vars`
and default value the same as the value of `vars`. Example:
```
julia> A, B = 0.5, 0.5
(0.5, 0.5)
julia> @convert_to_parameters A B
2-element Vector{Num}:
A
B
julia> typeof(A) # `A` is not a number anymore!
Num
julia> default_value(A)
0.5
"""
macro named_parameters(vars...)
return quote
out = []
for v in vars
res = (ModelingToolkit.toparam)((Symbolics.wrap)((Symbolics.SymbolicUtils.setmetadata)((Symbolics.setdefaultval)((Sym){Real}($(QuoteNode(v))), $(esc(v))), Symbolics.VariableSource, (:parameters, $(QuoteNode(v))))))
push!(out, res)
end
$(out...)
macro convert_to_parameters(vars...)
expr = Expr(:block)
for var in vars
binding = esc(var)
varname = QuoteNode(var)
push!(expr.args,
:($binding = (ModelingToolkit.toparam)((Symbolics.wrap)((SymbolicUtils.setmetadata)((Symbolics.setdefaultval)((Sym){Real}($varname), $binding), Symbolics.VariableSource, (:parameters, $varname)))))
)
end
push!(expr.args, Expr(:vect, esc.(vars)...))
return expr
end

# This may help:

# julia> @macroexpand @parameters A=0.1 B=0.1
# quote
# A = (ModelingToolkit.toparam)((Symbolics.wrap)((SymbolicUtils.setmetadata)((Symbolics.setdefaultval)((Sym){Real}(:A), 0.1), Symbolics.VariableSource, (:parameters, :A))))
# B = (ModelingToolkit.toparam)((Symbolics.wrap)((SymbolicUtils.setmetadata)((Symbolics.setdefaultval)((Sym){Real}(:B), 0.1), Symbolics.VariableSource, (:parameters, :B))))
# [A, B]
# end
export @convert_to_parameters
14 changes: 14 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,17 @@ end
@testset "extending default processes" begin
# API not yet finished on this one
end

@testset "utility functions" begin
@variables x(t) = 0.5
p = new_derived_named_parameter(x, 0.2, "t")
@test ModelingToolkit.getname(p) == :x_t
@test default_value(p) == 0.2
p = new_derived_named_parameter(x, p, "lala")
@test ModelingToolkit.getname(p) == :x_t

A, B = 0.5, 0.5
@convert_to_parameters A B
@test A isa Num
@test default_value(A) == 0.5
end

0 comments on commit 1c9c85c

Please sign in to comment.