Skip to content

Commit d6d767b

Browse files
committed
fix iv inference
1 parent ed705d4 commit d6d767b

File tree

3 files changed

+28
-35
lines changed

3 files changed

+28
-35
lines changed

src/chemistry_functionality.jl

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,28 +56,22 @@ function make_compound(expr)
5656

5757
# Extracts the composite species name, as well as the expression which creates it (with e.g. meta data and default values included).
5858
species_expr = expr.args[2] # E.g. :(CO2 = 1.0, [metadata=true])
59-
iv_expr = :(unique(reduce(vcat, arguments.(ModelingToolkit.unwrap.($(components)))))) # Expression which, when evaluated, becoems a list of all the independent variables the compound should depend on.
60-
species_expr = insert_independent_variable(species_expr, iv_expr) # Add independent variable (e.g. goes from `CO2` to `CO2(t)`).
59+
species_expr = insert_independent_variable(species_expr, :(..)) # Prepare iv addition, i.e. turns CO to CO(..).
6160
species_name = find_varname_in_declaration(expr.args[2]) # E.g. :CO2
61+
ivs_get_expr = :(unique(reduce(vcat,[arguments(ModelingToolkit.unwrap(iv)) for iv in $components]))) # Expression which when evaluated gives a vector with all the ivs of the components.
6262

63-
6463
# Creates the found expressions that will create the compound species.
65-
# The `Expr(:escape, :(...))` is required so that teh expressions are evaluated in the scope the users use the macro in (to e.g. detect already exiting species). # E.g. `@species CO2(t)`
66-
species_declaration_expr = Expr(:escape, :(@species $species_expr)) # E.g. `@species CO2(t)`
64+
# The `Expr(:escape, :(...))` is required so that the expressions are evaluated in the scope the users use the macro in (to e.g. detect already exiting species).
65+
species_declaration_expr = Expr(:escape, :(@species $species_expr)) # E.g. `@species CO2(..)`
66+
iv_designation_expression = Expr(:escape, :($species_name = $(species_name)($(ivs_get_expr)...))) # E.g. `CO2 = CO2([...]..)` where [...] is something which evaluates to a vector with all the ivs of the components.
6767
compound_designation_expr = Expr(:escape, :($species_name = ModelingToolkit.setmetadata($species_name, Catalyst.CompoundSpecies, true))) # E.g. `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, true)`
6868
components_designation_expr = Expr(:escape, :($species_name = ModelingToolkit.setmetadata($species_name, Catalyst.CompoundComponents, $components))) # E.g. `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, [C, O])`
6969
coefficients_designation_expr = Expr(:escape, :($species_name = ModelingToolkit.setmetadata($species_name, Catalyst.CompoundCoefficients, $coefficients))) # E.g. `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, [1, 2])`
7070

71-
println(quote
72-
$species_declaration_expr
73-
$compound_designation_expr
74-
$components_designation_expr
75-
$coefficients_designation_expr
76-
end)
77-
7871
# Returns the rephrased expression.
7972
return quote
8073
$species_declaration_expr
74+
$iv_designation_expression
8175
$compound_designation_expr
8276
$components_designation_expr
8377
$coefficients_designation_expr
@@ -128,6 +122,9 @@ function make_compounds(expr)
128122
end
129123
push!(compound_declarations.args, :($(Expr(:escape, :($(compound_syms))))))
130124

125+
# The output needs to be converted to Vector{Num} (from Vector{SymbolicUtils.BasicSymbolic{Real}}) to be consistent with e.g. @variables.
126+
compound_declarations.args[end] = :([ModelingToolkit.wrap(cmp) for cmp in $(compound_declarations.args[end])])
127+
131128
# Returns output that.
132129
return compound_declarations
133130
end

src/expression_utils.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,21 @@ end
4949
# X(t) = 1.0
5050
# X(t), [metadata=true]
5151
# X(t) = 1.0, [metadata=true]
52-
# (In this example the independent variable t was inserted).
53-
# Extra dispatch is to ensure so that iv is a vector (so that we can handle both single or multiple iv insertion in one function).
54-
# - This way we don't have to make a check for how to create the final expression (which is different for symbol or vector of symbols).
55-
function insert_independent_variable(expr_in, ivs)
52+
# (In this example the independent variable :t was inserted).
53+
# Here, the iv is a iv_expr, which can be anything, which is inserted
54+
function insert_independent_variable(expr_in, iv_expr)
5655
# If expr is a symbol, just attach the iv. If not we have to create a new expr and mutate it.
5756
# Because Symbols (a possible input) cannot be mutated, this function cannot mutate the input (would have been easier if Expr input was guaranteed).
58-
(expr_in isa Symbol) && (return Expr(:call, expr_in, :($ivs...)))
57+
(expr_in isa Symbol) && (return Expr(:call, expr_in, iv_expr))
5958
expr = deepcopy(expr_in)
6059

6160
if expr.head == :(=) # Case: :(X = 1.0)
62-
expr.args[1] = Expr(:call, expr.args[1], :($ivs...))
61+
expr.args[1] = Expr(:call, expr.args[1], iv_expr)
6362
elseif expr.head == :tuple
6463
if expr.args[1] isa Symbol # Case: :(X, [metadata=true])
65-
expr.args[1] = Expr(:call, expr.args[1], :($ivs...))
64+
expr.args[1] = Expr(:call, expr.args[1], iv_expr)
6665
elseif (expr.args[1].head == :(=)) && (expr.args[1].args[1] isa Symbol) # Case: :(X = 1.0, [metadata=true])
67-
expr.args[1].args[1] = Expr(:call, expr.args[1].args[1], :($ivs...))
66+
expr.args[1].args[1] = Expr(:call, expr.args[1].args[1], iv_expr)
6867
end
6968
end
7069
(expr == expr_in) && error("Failed to add independent variable $(iv) to expression: $expr_in")

test/miscellaneous_tests/compound_macro.jl

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,23 +71,20 @@ end
7171
let
7272
@variables t x y z
7373
@species C(t) H(x) N(x) O(t) P(t,x) S(x,y)
74-
74+
75+
# Creates compounds.
7576
@compound CO2 ~ C + 2O
76-
@test issetequal(arguments(ModelingToolkit.unwrap(CO2)), [t])
77+
@compound NH4, [output=true] ~ N + 4H
78+
@compound (H2O = 2.0) ~ 2H + O
79+
@compound PH4 ~ P + 4H
80+
@compound SO2 ~ S + 2O
7781

78-
# These 4 tests checks currently non-supported feature.
79-
@test_broken false
80-
@test_broken false
81-
@test_broken false
82-
@test_broken false
83-
# @compound NH4, [output=true] ~ N + 4H
84-
# @compound (H2O = 2.0) ~ 2H + N
85-
# @compound PH4 ~ P + 4H
86-
# @compound SO2 ~ S + 2O
87-
# @test issetequal(arguments(ModelingToolkit.unwrap(NH4)), [x])
88-
# @test issetequal(arguments(ModelingToolkit.unwrap(H2O)), [t, x])
89-
# @test issetequal(arguments(ModelingToolkit.unwrap(PH4)), [t, x])
90-
# @test issetequal(arguments(ModelingToolkit.unwrap(SO2)), [t, x, y])
82+
# Checks they have the correct independent variables.
83+
@test issetequal(arguments(ModelingToolkit.unwrap(CO2)), [t])
84+
@test issetequal(arguments(ModelingToolkit.unwrap(NH4)), [x])
85+
@test issetequal(arguments(ModelingToolkit.unwrap(H2O)), [t, x])
86+
@test issetequal(arguments(ModelingToolkit.unwrap(PH4)), [t, x])
87+
@test issetequal(arguments(ModelingToolkit.unwrap(SO2)), [t, x, y])
9188
end
9289

9390
### Other Minor Tests ###

0 commit comments

Comments
 (0)