Skip to content

Commit 3041ab0

Browse files
committed
Merge remote-tracking branch 'origin/master' into isaacsas-uncap-bases
2 parents 14f78af + 8a9b4e4 commit 3041ab0

31 files changed

+193
-94
lines changed

HISTORY.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@
2525
StructuralIdentifiability has with Julia 1.10.5 and 1.11.
2626
- A tutorial on making interactive plot displays using Makie has been added.
2727
- The BifurcationKit extension has been updated to v.4.
28+
- There is a new DSL option `@require_declaration` that will turn off automatic inferring for species, parameters, and variables in the DSL. For example, the following will now error:
29+
```julia
30+
rn = @reaction_network begin
31+
@require_declaration
32+
(k1, k2), A <--> B
33+
end
34+
```
35+
When this flag is set, all symbolics must be explicitly declared.
36+
```julia
37+
rn = @reaction_network begin
38+
@species A(t) B(t)
39+
@parameters k1 k2
40+
@require_declaration
41+
(k1, k2), A <--> B
42+
end
43+
```
2844

2945
## Catalyst 14.4.1
3046
- Support for user-defined functions on the RHS when providing coupled equations

Project.toml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ SciMLBase = "2.57.2"
6666
Setfield = "1"
6767
# StructuralIdentifiability = "0.5.8"
6868
SymbolicUtils = "2.1.2, 3.3.0"
69-
Symbolics = "5.30.1, 6"
69+
Symbolics = "6.22"
7070
Unitful = "1.12.4"
7171
julia = "1.10"
7272

@@ -77,7 +77,11 @@ Graphviz_jll = "3c863552-8265-54e4-a6dc-903eb78fde85"
7777
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
7878
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
7979
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
80-
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
80+
OrdinaryDiffEqBDF = "6ad6398a-0878-4a85-9266-38940aa047c8"
81+
OrdinaryDiffEqDefault = "50262376-6c5a-4cf5-baba-aaf4f84d72d7"
82+
OrdinaryDiffEqRosenbrock = "43230ef6-c299-4910-a778-202eb28ce4ce"
83+
OrdinaryDiffEqTsit5 = "b1df2697-797e-41e3-8120-5422d3b24e4a"
84+
OrdinaryDiffEqVerner = "79d7bb75-1356-48c1-b8c0-6832512096c2"
8185
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
8286
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
8387
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
@@ -93,7 +97,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
9397
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
9498

9599
[targets]
96-
test = ["DiffEqCallbacks", "DomainSets", "Graphviz_jll", "Logging", "NonlinearSolve",
97-
"OrdinaryDiffEq", "Pkg", "Plots", "Random", "SafeTestsets", "SciMLBase", "SciMLNLSolve",
98-
"StableRNGs", "StaticArrays", "Statistics", "SteadyStateDiffEq", "StochasticDiffEq",
99-
"Test", "Unitful"]
100+
test = ["DiffEqCallbacks", "DomainSets", "Graphviz_jll", "Logging", "NonlinearSolve", "OrdinaryDiffEqBDF", "OrdinaryDiffEqDefault", "OrdinaryDiffEqRosenbrock", "OrdinaryDiffEqTsit5", "OrdinaryDiffEqVerner", "Pkg", "Plots", "Random", "SafeTestsets", "SciMLBase", "SciMLNLSolve", "StableRNGs", "StaticArrays", "Statistics", "SteadyStateDiffEq", "StochasticDiffEq", "Test", "Unitful"]

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,4 @@ SpecialFunctions = "2.4"
8787
StaticArrays = "1.9"
8888
SteadyStateDiffEq = "2.2"
8989
StochasticDiffEq = "6.65"
90-
Symbolics = "5.30.1, 6"
90+
Symbolics = "6.22"

docs/src/faqs.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,16 @@ end
309309
In some cases, it may be necessary or desirable to register functions with
310310
Symbolics.jl before their use in Catalyst, see the discussion
311311
[here](https://symbolics.juliasymbolics.org/stable/manual/functions/).
312+
313+
## How can I turn off automatic inferring of species and parameters when using the DSL?
314+
This option can be set using the `@require_declaration` option inside `@reaction_network`. In this case all the species, parameters, and variables in the system must be pre-declared using one of the `@species`, `@parameters`, or `@variables` macros. For more information about what is inferred automatically and not, please see the section on [`@require_declaration`](@ref dsl_advanced_options_require_dec).
315+
316+
```@example faq9
317+
using Catalyst
318+
rn = @reaction_network begin
319+
@require_declaration
320+
@species A(t) B(t)
321+
@parameters k1 k2
322+
(k1, k2), A <--> B
323+
end
324+
```

docs/src/model_creation/dsl_advanced.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ ModelingToolkit.getdescription(two_state_system.kA)
205205

206206
### [Designating constant-valued/fixed species parameters](@id dsl_advanced_options_constant_species)
207207

208-
Catalyst enables the designation of parameters as `constantspecies`. These parameters can be used as species in reactions, however, their values are not changed by the reaction and remain constant throughout the simulation (unless changed by e.g. the [occurrence of an event]@ref constraint_equations_events). Practically, this is done by setting the parameter's `isconstantspecies` metadata to `true`. Here, we create a simple reaction where the species `X` is converted to `Xᴾ` at rate `k`. By designating `X` as a constant species parameter, we ensure that its quantity is unchanged by the occurrence of the reaction.
208+
Catalyst enables the designation of parameters as `constantspecies`. These parameters can be used as species in reactions, however, their values are not changed by the reaction and remain constant throughout the simulation (unless changed by e.g. the [occurrence of an event](@ref constraint_equations_events). Practically, this is done by setting the parameter's `isconstantspecies` metadata to `true`. Here, we create a simple reaction where the species `X` is converted to `Xᴾ` at rate `k`. By designating `X` as a constant species parameter, we ensure that its quantity is unchanged by the occurrence of the reaction.
209209
```@example dsl_advanced_constant_species
210210
using Catalyst # hide
211211
rn = @reaction_network begin
@@ -272,6 +272,40 @@ sol = solve(oprob)
272272
plot(sol)
273273
```
274274

275+
### [Turning off species, parameter, and variable inference](@id dsl_advanced_options_require_dec)
276+
In some cases it may be desirable for Catalyst to not infer species and parameters from the DSL, as in the case of reaction networks with very many variables, or as a sanity check that variable names are written correctly. To turn off inference, simply use the `@require_declaration` option when using the `@reaction_network` DSL. This will require every single variable, species, or parameter used within the DSL to be explicitly declared using the `@variable`, `@species`, or `@parameter` options. In the case that the DSL parser encounters an undeclared symbolic, it will error with an `UndeclaredSymbolicError` and print the reaction or equation that the undeclared symbolic was found in.
277+
278+
```julia
279+
using Catalyst
280+
rn = @reaction_network begin
281+
@require_declaration
282+
(k1, k2), A <--> B
283+
end
284+
```
285+
Running the code above will yield the following error:
286+
```
287+
LoadError: UndeclaredSymbolicError: Unrecognized variables A detected in reaction expression: "((k1, k2), A <--> B)". Since the flag @require_declaration is declared, all species must be explicitly declared with the @species macro.
288+
```
289+
In order to avoid the error in this case all the relevant species and parameters will have to be declared.
290+
```@example dsl_advanced_require_dec
291+
# The following case will not error.
292+
using Catalyst
293+
t = default_t()
294+
rn = @reaction_network begin
295+
@require_declaration
296+
@species A(t) B(t)
297+
@parameters k1 k2
298+
(k1, k2), A <--> B
299+
end
300+
```
301+
302+
The following cases in which the DSL would normally infer variables will all throw errors if `@require_declaration` is set and the variables are not explicitly declared.
303+
- Occurrence of an undeclared species in a reaction, as in the example above.
304+
- Occurrence of an undeclared parameter in a reaction rate expression, as in the reaction line `k*n, A --> B`.
305+
- Occurrence of an undeclared parameter in the stoichiometry of a species, as in the reaction line `k, n*A --> B`.
306+
- Occurrence of an undeclared differential variable on the LHS of a coupled differential equation, as in `A` in `@equations D(A) ~ A^2`.
307+
- Occurrence of an undeclared [observable](@ref dsl_advanced_options_observables) in an `@observables` expression, such as `@observables X1 ~ A + B`.
308+
275309
## [Naming reaction networks](@id dsl_advanced_options_naming)
276310
Each reaction network model has a name. It can be accessed using the `nameof` function. By default, some generic name is used:
277311
```@example dsl_advanced_names

src/Catalyst.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import ModelingToolkit: check_variables,
4141

4242
import Base: (==), hash, size, getindex, setindex, isless, Sort.defalg, length, show
4343
import MacroTools, Graphs
44+
using MacroTools: striplines
4445
import Graphs: DiGraph, SimpleGraph, SimpleDiGraph, vertices, edges, add_vertices!, nv, ne
4546
import DataStructures: OrderedDict, OrderedSet
4647
import Parameters: @with_kw_noshow

src/chemistry_functionality.jl

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,11 @@ t = default_t()
6363
@compound CO2(t) ~ C + 2O
6464
```
6565
66-
Notes:
66+
Notes:
6767
- The component species must be defined before using the `@compound` macro.
6868
"""
6969
macro compound(expr)
70-
make_compound(MacroTools.striplines(expr))
70+
make_compound(striplines(expr))
7171
end
7272

7373
# Declares compound error messages:
@@ -83,12 +83,12 @@ function make_compound(expr)
8383
error(COMPOUND_CREATION_ERROR_BAD_SEPARATOR)
8484

8585
# Loops through all components, add the component and the coefficients to the corresponding vectors
86-
# Cannot extract directly using e.g. "getfield.(composition, :reactant)" because then
86+
# Cannot extract directly using e.g. "getfield.(composition, :reactant)" because then
8787
# we get something like :([:C, :O]), rather than :([C, O]).
8888
composition = Catalyst.recursive_find_reactants!(expr.args[3], 1,
8989
Vector{ReactantStruct}(undef, 0))
90-
components = :([]) # Becomes something like :([C, O]).
91-
coefficients = :([]) # Becomes something like :([1, 2]).
90+
components = :([]) # Becomes something like :([C, O]).
91+
coefficients = :([]) # Becomes something like :([1, 2]).
9292
for comp in composition
9393
push!(components.args, comp.reactant)
9494
push!(coefficients.args, comp.stoichiometry)
@@ -110,13 +110,13 @@ function make_compound(expr)
110110
for comp in $components])))
111111

112112
# Creates the found expressions that will create the compound species.
113-
# The `Expr(:escape, :(...))` is required so that the expressions are evaluated in
114-
# the scope the users use the macro in (to e.g. detect already exiting species).
113+
# The `Expr(:escape, :(...))` is required so that the expressions are evaluated in
114+
# the scope the users use the macro in (to e.g. detect already exiting species).
115115
# Creates something like (where `compound_ivs` and `component_ivs` evaluates to all the compound's and components' ivs):
116116
# `@species CO2(..)`
117117
# `isempty([])` && length(component_ivs) && error("When ...)
118-
# `CO2 = CO2(component_ivs..)`
119-
# `issetequal(compound_ivs, component_ivs) || error("The ...)`
118+
# `CO2 = CO2(component_ivs..)`
119+
# `issetequal(compound_ivs, component_ivs) || error("The ...)`
120120
# `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, true)`
121121
# `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, [C, O])`
122122
# `CO2 = ModelingToolkit.setmetadata(CO2, Catalyst.CompoundSpecies, [1, 2])`
@@ -159,7 +159,7 @@ Macro that creates several compound species, which each is composed of smaller c
159159
Example:
160160
```julia
161161
t = default_t()
162-
@species C(t) H(t) O(t)
162+
@species C(t) H(t) O(t)
163163
@compounds
164164
CH4(t) = C + 4H
165165
O2(t) = 2O
@@ -168,11 +168,11 @@ t = default_t()
168168
end
169169
```
170170
171-
Notes:
171+
Notes:
172172
- The component species must be defined before using the `@compound` macro.
173173
"""
174174
macro compounds(expr)
175-
make_compounds(MacroTools.striplines(expr))
175+
make_compounds(striplines(expr))
176176
end
177177

178178
# Function managing the @compound macro.
@@ -183,7 +183,7 @@ function make_compounds(expr)
183183
# For each compound in `expr`, creates the set of 7 compound creation lines (using `make_compound`).
184184
# Next, loops through all 7*[Number of compounds] lines and add them to compound_declarations.
185185
compound_calls = [Catalyst.make_compound(line) for line in expr.args]
186-
for compound_call in compound_calls, line in MacroTools.striplines(compound_call).args
186+
for compound_call in compound_calls, line in striplines(compound_call).args
187187
push!(compound_declarations.args, line)
188188
end
189189

@@ -249,7 +249,7 @@ brxs = balance_reaction(rx) # No solution.
249249
250250
Notes:
251251
- Balancing reactions that contain compounds of compounds is currently not supported.
252-
- A reaction may not always yield a single solution; it could have an infinite number of solutions or none at all. When there are multiple solutions, a vector of all possible `Reaction` objects is returned. However, substrates and products may be interchanged as we currently do not solve for a linear combination that maintains the set of substrates and products.
252+
- A reaction may not always yield a single solution; it could have an infinite number of solutions or none at all. When there are multiple solutions, a vector of all possible `Reaction` objects is returned. However, substrates and products may be interchanged as we currently do not solve for a linear combination that maintains the set of substrates and products.
253253
- If the reaction cannot be balanced, an empty `Reaction` vector is returned.
254254
"""
255255
function balance_reaction(reaction::Reaction)
@@ -369,16 +369,16 @@ From a system, creates a new system where each reaction is a balanced version of
369369
reaction of the original system. For more information, consider the `balance_reaction` function
370370
(which is internally applied to each system reaction).
371371
372-
Arguments
372+
Arguments
373373
- `rs`: The reaction system that should be balanced.
374374
375375
Notes:
376376
- If any reaction in the system cannot be balanced, throws an error.
377-
- If any reaction in the system have an infinite number of potential reactions, throws an error.
377+
- If any reaction in the system have an infinite number of potential reactions, throws an error.
378378
Here, it would be possible to generate a valid reaction, however, no such routine is currently
379379
implemented in `balance_system`.
380380
- `balance_system` will not modify reactions of subsystems to the input system. It is recommended
381-
not to apply `balance_system` to non-flattened systems.
381+
not to apply `balance_system` to non-flattened systems.
382382
"""
383383
function balance_system(rs::ReactionSystem)
384384
@set! rs.eqs = CatalystEqType[get_balanced_reaction(eq) for eq in get_eqs(rs)]
@@ -391,7 +391,7 @@ end
391391
function get_balanced_reaction(rx::Reaction)
392392
brxs = balance_reaction(rx)
393393

394-
# In case there are no, or multiple, solutions to the balancing problem.
394+
# In case there are no, or multiple, solutions to the balancing problem.
395395
if isempty(brxs)
396396
error("Could not balance reaction `$rx`, unable to create a balanced `ReactionSystem`.")
397397
end

0 commit comments

Comments
 (0)