Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
TorkelE committed Dec 20, 2024
1 parent 6e33f5b commit 9584a4b
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 39 deletions.
26 changes: 13 additions & 13 deletions src/chemistry_functionality.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,31 +101,29 @@ function make_compound(expr)
species_expr = expr.args[2]
species_name, ivs, _, _ = find_varinfo_in_declaration(expr.args[2])

# If no ivs were given, inserts `(..)` (e.g. turning `CO` to `CO(..)`).
isempty(ivs) && (species_expr = insert_independent_variable(species_expr, :(..)))

# Expression which when evaluated gives a vector with all the ivs of the components.
ivs_get_expr = :(unique(reduce(
vcat, [sorted_arguments(ModelingToolkit.unwrap(comp))
for comp in $components])))
# If no ivs were given, inserts and expression which evaluates to the union of the ivs
# for the species the compound depends on.
ivs_get_expr = :(unique(reduce( vcat, [sorted_arguments(ModelingToolkit.unwrap(comp))
for comp in $components])))
if isempty(ivs)
species_expr = Catalyst.insert_independent_variable(species_expr, :($ivs_get_expr...))
end

# Creates the found expressions that will create the compound species.
# 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).
# Creates something like (where `compound_ivs` and `component_ivs` evaluates to all the compound's and components' ivs):
# `@species CO2(..)`
# `isempty([])` && length(component_ivs) && error("When ...)
# `CO2 = CO2(component_ivs..)`
# `@species CO2(iv)`
# `isempty([])` && (length(component_ivs) > 1) && error("When ...)
# `issetequal(compound_ivs, component_ivs) || error("The ...)`
# `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, true)`
# `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, [C, O])`
# `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, [1, 2])`
# `CO2 = ModelingToolkit.wrap(CO2)`
species_declaration_expr = Expr(:escape, :(@species $species_expr))
multiple_ivs_error_check_expr = Expr(:escape,
:($(isempty(ivs)) && (length($ivs_get_expr) > 1) &&
error($COMPOUND_CREATION_ERROR_DEPENDENT_VAR_REQUIRED)))
iv_designation_expr = Expr(:escape,
:($(isempty(ivs)) && ($species_name = $(species_name)($(ivs_get_expr)...))))
iv_check_expr = Expr(:escape,
:(issetequal(arguments(ModelingToolkit.unwrap($species_name)), $ivs_get_expr) ||
error("The independent variable(S) provided to the compound ($(arguments(ModelingToolkit.unwrap($species_name)))), and those of its components ($($ivs_get_expr)))), are not identical.")))
Expand All @@ -138,16 +136,18 @@ function make_compound(expr)
coefficients_designation_expr = Expr(:escape,
:($species_name = ModelingToolkit.setmetadata(
$species_name, Catalyst.CompoundCoefficients, $coefficients)))
compound_wrap_expr = Expr(:escape,
:($species_name = ModelingToolkit.wrap($species_name)))

# Returns the rephrased expression.
return quote
$species_declaration_expr
$multiple_ivs_error_check_expr
$iv_designation_expr
$iv_check_expr
$compound_designation_expr
$components_designation_expr
$coefficients_designation_expr
$compound_wrap_expr
end
end

Expand Down
70 changes: 44 additions & 26 deletions test/miscellaneous_tests/compound_macro.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ using Catalyst, Test
# Sets the default `t` to use.
t = default_t()

### Test Macro Basic Functionality ###
### Test Macro Basic Functionality ###

# Miscellaneous basic usage.
let
@species C(t) H(t) O(t)
@species C(t) H(t) O(t)
@parameters p1 p2

# Basic cases that should pass:
Expand Down Expand Up @@ -50,7 +50,7 @@ let

# Declares stuff in the DSL.
rn = @reaction_network begin
@species N(t) H(t)
@species N(t) H(t)
@parameters p1 p2
@compounds begin
NH3_1 ~ N + 3H
Expand Down Expand Up @@ -80,7 +80,7 @@ let

@test isequal([C, H, O], components(C6H12O2))
@test isequal([6, 12, 2], coefficients(C6H12O2))
@test isequal([C => 6, H => 12, O => 2], Catalyst.component_coefficients(C6H12O2))
@test isequal([C => 6, H => 12, O => 2], Catalyst.component_coefficients(C6H12O2))
@test all(!iscompound(i) for i in components(C6H12O2))
end

Expand All @@ -95,10 +95,28 @@ let

@test isequal([O], components(O2))
@test isequal([2], coefficients(O2))
@test isequal([O => 2], Catalyst.component_coefficients(O2))
@test isequal([O => 2], Catalyst.component_coefficients(O2))
@test all(!iscompound(i) for i in components(O2))
end

# Tests https://github.com/SciML/Catalyst.jl/issues/1151.
# Checks that compounds are `Num` (and not BasicSymbolics).
# Check that ModelingToolkit.get_variables! works on compounds.
let
@species C(t) H(t) O(t)
@compounds begin
O₂ ~ 2O
CH₄ ~ C + 4H
end

@test O₂ isa Symbolics.Num
@test CH₄ isa Symbolics.Num
vars = []
ModelingToolkit.get_variables!(vars, O₂)
ModelingToolkit.get_variables!(vars, CH₄)
@test issetequal(vars, [O₂, CH₄])
end

### Independent Variables ###

# Test using different independent variable combinations.
Expand All @@ -112,14 +130,14 @@ let
@test_throws Exception @eval @compound (H2O = 2.0) ~ 2H + O
@test_throws Exception @eval @compound PH4(x) ~ P + 4H
@test_throws Exception @eval @compound SO2(t,y) ~ S + 2O

# Creates compounds.
@compound CO2 ~ C + 2O
@compound (NH4, [output=true]) ~ N + 4H
@compound (H2O(t,x) = 2.0) ~ 2H + O
@compound PH4(t,x) ~ P + 4H
@compound SO2(t,x,y) ~ S + 2O

# Checks they have the correct independent variables.
@test issetequal(Symbolics.sorted_arguments(ModelingToolkit.unwrap(CO2)), [t])
@test issetequal(Symbolics.sorted_arguments(ModelingToolkit.unwrap(NH4)), [x])
Expand Down Expand Up @@ -200,7 +218,7 @@ let
end

# Case 5.
let
let
@species A(t)
B = A
@compound A2 ~ 2A
Expand All @@ -217,7 +235,7 @@ end
### Test @compounds Macro ###

# Basic @compounds syntax.
let
let
@species C(t) H(t) O(t)
@compound OH ~ 1O + 1H
@compound C3H5OH3 ~ 3C + 5H + 3OH
Expand All @@ -239,7 +257,7 @@ let
end

# Interpolation in @compounds.
let
let
@species s1(t) s2(t) s3(t)
s2_alt = s2
s3_alt = s3
Expand All @@ -262,8 +280,8 @@ end
# Checks that compounds cannot be created from non-existing species.
let
@species C(t) H(t)
@test_throws Exception @compound C6H12O2 ~ 6C + 12H + 2O
@test_throws Exception @compound O2 ~ 2O
@test_throws Exception @compound C6H12O2 ~ 6C + 12H + 2O
@test_throws Exception @compound O2 ~ 2O
end

# Checks that nested components works as expected.
Expand Down Expand Up @@ -292,25 +310,25 @@ end
# Checks with a single compound.
# Checks using @unpack.
# Check where compounds and components does not occur in reactions.
let
let
rn = @reaction_network begin
@species C(t) O(t)
@compounds begin
CO2 ~ C + 2O
end
end
@unpack C, O, CO2 = rn

@test length(species(rn)) == 3
@test iscompound(CO2)
@test isequal([C, O], components(CO2))
@test isequal([1, 2], coefficients(CO2))
@test isequal([C => 1, O => 2], component_coefficients(CO2))
@test isequal([C => 1, O => 2], component_coefficients(CO2))
end

# Test using multiple compounds.
# Test using rn. notation to fetch species.
let
let
rn = @reaction_network begin
@species C(t) O(t) H(t)
@compounds begin
Expand All @@ -322,20 +340,20 @@ let
k, CH4 + O2 --> CO2 + H2O
end
species(rn)

@test length(species(rn)) == 7
@test isequal([rn.C, rn.H], components(rn.CH4))
@test isequal([1, 4], coefficients(rn.CH4))
@test isequal([rn.C => 1, rn.H => 4], component_coefficients(rn.CH4))
@test isequal([rn.C => 1, rn.H => 4], component_coefficients(rn.CH4))
@test isequal([rn.O], components(rn.O2))
@test isequal([2], coefficients(rn.O2))
@test isequal([rn.O => 2], component_coefficients(rn.O2))
@test isequal([rn.O => 2], component_coefficients(rn.O2))
@test isequal([rn.C, rn.O], components(rn.CO2))
@test isequal([1, 2], coefficients(rn.CO2))
@test isequal([rn.C => 1, rn.O => 2], component_coefficients(rn.CO2))
@test isequal([rn.C => 1, rn.O => 2], component_coefficients(rn.CO2))
@test isequal([rn.H, rn.O], components(rn.H2O))
@test isequal([2, 1], coefficients(rn.H2O))
@test isequal([rn.H => 2, rn.O => 1], component_coefficients(rn.H2O))
@test isequal([rn.H => 2, rn.O => 1], component_coefficients(rn.H2O))
end

# Tests using compounds of compounds.
Expand All @@ -351,13 +369,13 @@ let
end
species(rn)
@unpack S, O, SO2, S2O4 = rn

@test length(species(rn)) == 4

@test isequal([S, O], components(SO2))
@test isequal([1, 2], coefficients(SO2))
@test isequal([S => 1, O => 2], component_coefficients(SO2))
@test isequal([S => 1, O => 2], component_coefficients(SO2))
@test isequal([SO2], components(S2O4))
@test isequal([2], coefficients(S2O4))
@test isequal([SO2 => 2], component_coefficients(S2O4))
end
@test isequal([SO2 => 2], component_coefficients(S2O4))
end

0 comments on commit 9584a4b

Please sign in to comment.