From 9584a4bdb13c559de3585fce90e632a690043f55 Mon Sep 17 00:00:00 2001 From: Torkel Loman Date: Fri, 20 Dec 2024 12:58:05 +0000 Subject: [PATCH] init --- src/chemistry_functionality.jl | 26 ++++---- test/miscellaneous_tests/compound_macro.jl | 70 ++++++++++++++-------- 2 files changed, 57 insertions(+), 39 deletions(-) diff --git a/src/chemistry_functionality.jl b/src/chemistry_functionality.jl index 7fbf43e43b..a2b5b7ed8b 100644 --- a/src/chemistry_functionality.jl +++ b/src/chemistry_functionality.jl @@ -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."))) @@ -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 diff --git a/test/miscellaneous_tests/compound_macro.jl b/test/miscellaneous_tests/compound_macro.jl index 485b6795e8..4440445827 100644 --- a/test/miscellaneous_tests/compound_macro.jl +++ b/test/miscellaneous_tests/compound_macro.jl @@ -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: @@ -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 @@ -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 @@ -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. @@ -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]) @@ -200,7 +218,7 @@ let end # Case 5. -let +let @species A(t) B = A @compound A2 ~ 2A @@ -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 @@ -239,7 +257,7 @@ let end # Interpolation in @compounds. -let +let @species s1(t) s2(t) s3(t) s2_alt = s2 s3_alt = s3 @@ -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. @@ -292,7 +310,7 @@ 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 @@ -300,17 +318,17 @@ let 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 @@ -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. @@ -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 \ No newline at end of file + @test isequal([SO2 => 2], component_coefficients(S2O4)) +end