diff --git a/docs/src/index.md b/docs/src/index.md index c9b048a..4120891 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -178,4 +178,5 @@ ProcessBasedModelling.lhs default_value has_variable new_derived_named_parameter +convert_to_parameters ``` diff --git a/src/processes_basic.jl b/src/processes_basic.jl index f3f7d23..3c9379f 100644 --- a/src/processes_basic.jl +++ b/src/processes_basic.jl @@ -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: diff --git a/src/utils.jl b/src/utils.jl index 169f39a..73b165f 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -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 \ No newline at end of file +export @convert_to_parameters diff --git a/test/runtests.jl b/test/runtests.jl index 3662263..d383ec0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -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