Skip to content

Commit d856db7

Browse files
authored
Merge branch 'master' into continuation_of_bifurcation_point_tutorial
2 parents 9fa23b0 + cf6a8e6 commit d856db7

File tree

25 files changed

+916
-158
lines changed

25 files changed

+916
-158
lines changed

HISTORY.md

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,47 @@
77
(at the time the release is made). If you need a dependency version increased,
88
please open an issue and we can update it and make a new Catalyst release once
99
testing against the newer dependency version is complete.
10-
- It is no longer recommended to install and use the full OrdinaryDiffEq library to access specific ODE solvers.
11-
Instead, only install the specific OrdinaryDiffEq sub-libraries that contain the desired
12-
solver. This significantly reduces installation and package loading times. I.e. to use the default
13-
solver that auto-switches between explicit and implicit methods, install `OrdinaryDiffEqDefault`. To
14-
use `Tsit5` install `OrdinaryDiffEqTsit5`, etc. The possible sub-libraries, each containing different solvers,
15-
can be viewed [here](https://github.com/SciML/OrdinaryDiffEq.jl/tree/master/lib).
16-
- It should now be safe to use `remake` on problems which have had conservation laws removed.
17-
The warning regarding this when eliminating conservation laws have been removed (in conjunction
18-
with the `remove_conserved_warn` argument for disabling this warning).
19-
- New formula for inferring variables from equations (declared using the `@equations` options) in the DSL. The order of inference of species/variables/parameters is now:
20-
(1) Every symbol explicitly declared using `@species`, `@variables`, and `@parameters` are assigned to the correct category.
21-
(2) Every symbol used as a reaction reactant is inferred as a species.
22-
(3) Every symbol not declared in (1) or (2) that occurs in an expression provided after `@equations` is inferred as a variable.
23-
(4) Every symbol not declared in (1), (2), or (3) that occurs either as a reaction rate or stoichiometric coefficient is inferred to be a parameter.
24-
E.g. in
25-
```julia
26-
@reaction_network begin
27-
@equations V1 + S ~ V2^2
28-
(p + S + V1), S --> 0
29-
end
30-
```
31-
`S` is inferred as a species, `V1` and `V2` as variables, and `p` as a parameter. The previous special cases for the `@observables`, `@compounds`, and `@differentials` options still hold. Finally, the `@require_declaration` options (described in more detail below) can now be used to require everything to be explicitly declared.
32-
- New formula for determining whether the default differentials have been used within an `@equations` option. Now, if any expression `D(...)` is encountered (where `...` can be anything), this is inferred as usage of the default differential D. E.g. in the following equations `D` is inferred as a differential with respect to the default independent variable:
10+
- It is no longer recommended to install and use the full OrdinaryDiffEq library
11+
to access specific ODE solvers. Instead, only install the specific
12+
OrdinaryDiffEq sub-libraries that contain the desired solver. This
13+
significantly reduces installation and package loading times. I.e. to use the
14+
default solver that auto-switches between explicit and implicit methods,
15+
install `OrdinaryDiffEqDefault`. To use `Tsit5` install `OrdinaryDiffEqTsit5`,
16+
etc. The possible sub-libraries, each containing different solvers, can be
17+
viewed [here](https://github.com/SciML/OrdinaryDiffEq.jl/tree/master/lib).
18+
- It should now be safe to use `remake` on problems which have had conservation
19+
laws removed with the exception of `NonlinearProblem`s or `NonlinearSystem`s.
20+
For NonlinearProblems it is safe to use `remake` if only updating `u0` values,
21+
but it is not safe to update the value of the conserved constant, `Γ`. See
22+
[the FAQ](https://docs.sciml.ai/Catalyst/stable/faqs/#faq_remake_nonlinprob)
23+
for details.
24+
- New formula for inferring variables from equations (declared using the
25+
`@equations` options) in the DSL. The order of inference of
26+
species/variables/parameters is now:
27+
1. Every symbol explicitly declared using `@species`, `@variables`, and
28+
`@parameters` are assigned to the correct category.
29+
2. Every symbol used as a reaction reactant is inferred as a species.
30+
3. Every symbol not declared in (1) or (2) that occurs in an expression
31+
provided after `@equations` is inferred as a variable.
32+
4. Every symbol not declared in (1), (2), or (3) that occurs either as a
33+
reaction rate or stoichiometric coefficient is inferred to be a
34+
parameter. E.g. in
35+
```julia
36+
@reaction_network begin
37+
@equations V1 + S ~ V2^2
38+
(p + S + V1), S --> 0
39+
end
40+
```
41+
`S` is inferred as a species, `V1` and `V2` as variables, and `p` as a
42+
parameter. The previous special cases for the `@observables`, `@compounds`,
43+
and `@differentials` options still hold. Finally, the `@require_declaration`
44+
options (described in more detail below) can now be used to require everything
45+
to be explicitly declared.
46+
- New formula for determining whether the default differentials have been used
47+
within an `@equations` option. Now, if any expression `D(...)` is encountered
48+
(where `...` can be anything), this is inferred as usage of the default
49+
differential D. E.g. in the following equations `D` is inferred as a
50+
differential with respect to the default independent variable:
3351
```julia
3452
@reaction_network begin
3553
@equations D(V) + V ~ 1
@@ -38,7 +56,9 @@
3856
@equations D(D(V)) ~ 1
3957
end
4058
```
41-
Please note that this cannot be used at the same time as `D` is used to represent a species, variable, or parameter (including if these are implicitly designated as such by e.g. appearing as a reaction reactant).
59+
Please note that this cannot be used at the same time as `D` is used to
60+
represent a species, variable, or parameter (including if these are implicitly
61+
designated as such by e.g. appearing as a reaction reactant).
4262
- Array symbolics support is more consistent with ModelingToolkit v9. Parameter
4363
arrays are no longer scalarized by Catalyst, while species and variables
4464
arrays still are (as in ModelingToolkit). As such, parameter arrays should now
@@ -51,7 +71,11 @@
5171
*not* to do this as it has signifcant performance costs with ModelingToolkit
5272
v9. Note, scalarized parameter arrays passed to the two-argument
5373
`ReactionSystem` constructor may become unscalarized.
54-
- Functional (e.g. time-dependent) parameters can now be used in Catalyst models. These can e.g. be used to incorporate arbitrary time-dependent functions (as a parameter) in a model. For more details on how to use these, please read: https://docs.sciml.ai/Catalyst/stable/model_creation/functional_parameters/.
74+
- Functional (e.g. time-dependent) parameters can now be used in Catalyst
75+
models. These can e.g. be used to incorporate arbitrary time-dependent
76+
functions (as a parameter) in a model. For more details on how to use these,
77+
please read:
78+
https://docs.sciml.ai/Catalyst/stable/model_creation/functional_parameters/.
5579
- Scoped species/variables/parameters are now treated similar to the latest MTK
5680
releases ( 9.49).
5781
- A tutorial on making interactive plot displays using Makie has been added.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ be found in its corresponding research paper, [Catalyst: Fast and flexible model
9090
- [Optimization.jl](https://github.com/SciML/Optimization.jl), [DiffEqParamEstim.jl](https://github.com/SciML/DiffEqParamEstim.jl), and [PEtab.jl](https://github.com/sebapersson/PEtab.jl) can all be used to [fit model parameters to data](https://sebapersson.github.io/PEtab.jl/stable/Define_in_julia/).
9191
- [GlobalSensitivity.jl](https://github.com/SciML/GlobalSensitivity.jl) can be used to perform [global sensitivity analysis](https://docs.sciml.ai/Catalyst/stable/inverse_problems/global_sensitivity_analysis/) of model behaviors.
9292
- [SciMLSensitivity.jl](https://github.com/SciML/SciMLSensitivity.jl) can be used to compute local sensitivities of functions containing forward model simulations.
93-
<!-- - [StructuralIdentifiability.jl](https://github.com/SciML/StructuralIdentifiability.jl) can be used to [perform structural identifiability analysis](https://docs.sciml.ai/Catalyst/stable/inverse_problems/structural_identifiability/). -->
93+
- [StructuralIdentifiability.jl](https://github.com/SciML/StructuralIdentifiability.jl) can be used to [perform structural identifiability analysis](https://docs.sciml.ai/Catalyst/stable/inverse_problems/structural_identifiability/).
9494

9595
#### Features of packages built upon Catalyst
9696
- Catalyst [`ReactionSystem`](@ref)s can be [imported from SBML files](https://docs.sciml.ai/Catalyst/stable/model_creation/model_file_loading_and_export/#Loading-SBML-files-using-SBMLImporter.jl-and-SBMLToolkit.jl) via [SBMLImporter.jl](https://github.com/sebapersson/SBMLImporter.jl) and [SBMLToolkit.jl](https://github.com/SciML/SBMLToolkit.jl), and [from BioNetGen .net files](https://docs.sciml.ai/Catalyst/stable/model_creation/model_file_loading_and_export/#file_loading_rni_net) and various stoichiometric matrix network representations using [ReactionNetworkImporters.jl](https://github.com/SciML/ReactionNetworkImporters.jl).

docs/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ BifurcationKit = "0.4.4"
5252
CairoMakie = "0.12, 0.13"
5353
Catalyst = "14.4"
5454
DataFrames = "1.6"
55+
DataInterpolations = "7.2, 8"
5556
DiffEqBase = "6.159.0"
5657
Distributions = "0.25"
57-
DataInterpolations = "7.2"
5858
Documenter = "1.4.1"
5959
DynamicalSystems = "3.3"
6060
GlobalSensitivity = "2.6"

docs/pages.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ pages = Any[
2323
"model_creation/examples/basic_CRN_library.md",
2424
"model_creation/examples/programmatic_generative_linear_pathway.md",
2525
"model_creation/examples/hodgkin_huxley_equation.md",
26-
"model_creation/examples/smoluchowski_coagulation_equation.md"
26+
"model_creation/examples/smoluchowski_coagulation_equation.md",
27+
"model_creation/examples/noise_modelling_approaches.md",
2728
]
2829
],
2930
"Model simulation and visualization" => Any[
@@ -45,6 +46,7 @@ pages = Any[
4546
"steady_state_functionality/bifurcation_diagrams.md",
4647
"steady_state_functionality/dynamical_systems.md",
4748
"Examples" => Any[
49+
"steady_state_functionality/examples/bifurcationkit_periodic_orbits.md"
4850
"steady_state_functionality/examples/bifurcationkit_codim2.md"
4951
]
5052
],

docs/src/faqs.md

Lines changed: 138 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ so the reaction
271271
```@example faq7
272272
using Catalyst
273273
rn = @reaction_network begin
274-
k, X --> ∅
274+
k, X --> ∅
275275
end
276276
convert(ODESystem, rn)
277277
```
@@ -280,7 +280,7 @@ using any of the following non-filled arrows when declaring the reaction: `<=`,
280280
``, ``, `=>`, ``, ``, ``, ``. This means that the reaction
281281
```@example faq7
282282
rn = @reaction_network begin
283-
k, X => ∅
283+
k, X => ∅
284284
end
285285
convert(ODESystem, rn)
286286
```
@@ -290,7 +290,7 @@ will be degraded at a constant rate even when very small or equal to 0).
290290
Note, stoichiometric coefficients are still included, i.e. the reaction
291291
```@example faq7
292292
rn = @reaction_network begin
293-
k, 2*X ⇒ ∅
293+
k, 2*X ⇒ ∅
294294
end
295295
convert(ODESystem, rn)
296296
```
@@ -303,7 +303,7 @@ ModelingToolkit. e.g., this is should work
303303
using Catalyst
304304
myHill(x) = 2*x^3/(x^3+1.5^3)
305305
rn = @reaction_network begin
306-
myHill(X), ∅ --> X
306+
myHill(X), ∅ --> X
307307
end
308308
```
309309
In some cases, it may be necessary or desirable to register functions with
@@ -322,3 +322,137 @@ rn = @reaction_network begin
322322
(k1, k2), A <--> B
323323
end
324324
```
325+
326+
## [What to be aware of when using `remake` with conservation law elimination and NonlinearProblems?](@id faq_remake_nonlinprob)
327+
328+
When constructing `NonlinearSystem`s or `NonlinearProblem`s with `remove_conserved = true`, i.e.
329+
```julia
330+
# for rn a ReactionSystem
331+
nsys = convert(NonlinearSystem, rn; remove_conserved = true)
332+
333+
# or
334+
nprob = NonlinearProblem(rn, u0, p; remove_conserved = true)
335+
```
336+
`remake` is currently unable to correctly update all `u0` values when the
337+
conserved constant(s), `Γ`, are updated. As an example consider the following
338+
```@example faq_remake
339+
using Catalyst, NonlinearSolve
340+
rn = @reaction_network begin
341+
(k₁,k₂), X₁ <--> X₂
342+
(k₃,k₄), X₁ + X₂ --> 2X₃
343+
end
344+
u0 = [:X₁ => 1.0, :X₂ => 2.0, :X₃ => 3.0]
345+
ps = [:k₁ => 0.1, :k₂ => 0.2, :k₃ => 0.3, :k₄ => 0.4]
346+
nlsys = convert(NonlinearSystem, rn; remove_conserved = true, conseqs_remake_warn = false)
347+
nlsys = complete(nlsys)
348+
equations(nlsys)
349+
```
350+
If we generate a `NonlinearProblem` from this system the conservation constant,
351+
`Γ[1]`, is automatically set to `X₁ + X₂ + X₃ = 6` and the initial values are
352+
those in `u0`. i.e if
353+
```@example faq_remake
354+
nlprob1 = NonlinearProblem(nlsys, u0, ps)
355+
```
356+
then
357+
```@example faq_remake
358+
nlprob1[(:X₁, :X₂, :X₃)] == (1.0, 2.0, 3.0)
359+
```
360+
and
361+
```@example faq_remake
362+
nlprob1.ps[:Γ][1] == 6.0
363+
```
364+
If we now try to change a value of `X₁`, `X₂`, or `X₃` using `remake`, the
365+
conserved constant will be recalculated. i.e. if
366+
```@example faq_remake
367+
nlprob2 = remake(nlprob1; u0 = [:X₂ => 3.0])
368+
```
369+
compare
370+
```@example faq_remake
371+
println("Correct u0 is: ", (1.0, 3.0, 3.0), "\n", "remade value is: ", nlprob2[(:X₁, :X₂, :X₃)])
372+
```
373+
and
374+
```@example faq_remake
375+
println("Correct Γ is: ", 7.0, "\n", "remade value is: ", nlprob2.ps[:Γ][1])
376+
```
377+
However, if we try to directly change the value of `Γ` it is not always the case
378+
that a `u0` value will correctly update so that the conservation law is
379+
conserved. Consider
380+
```@example faq_remake
381+
nlprob3 = remake(nlprob1; u0 = [:X₂ => nothing], p = [:Γ => [4.0]])
382+
```
383+
Setting `[:X₂ => nothing]` for other problem types communicates that the
384+
`u0` value for `X₂` should be solved for. However, if we examine the values we
385+
find
386+
```@example faq_remake
387+
println("Correct u0 is: ", (1.0, 0.0, 3.0), "\n", "remade value is: ", nlprob3[(:X₁, :X₂, :X₃)])
388+
```
389+
and
390+
```@example faq_remake
391+
println("Correct Γ is: ", 4.0, "\n", "remade value is: ", nlprob3.ps[:Γ][1])
392+
```
393+
As such, the `u0` value for `X₂` has not updated, and the conservation law is
394+
now violated by the `u0` values, i.e,
395+
```@example faq_remake
396+
(nlprob3[:X₁] + nlprob3[:X₂] + nlprob3[:X₃]) == nlprob3.ps[:Γ][1]
397+
```
398+
Currently, the only way to avoid this issue is to manually specify updated
399+
values for the `u0` components, which will ensure that `Γ` updates appropriately
400+
as in the first example. i.e. we manually set `X₂` to the value it should be and
401+
`Γ` will be updated accordingly:
402+
```@example faq_remake
403+
nlprob4 = remake(nlprob1; u0 = [:X₂ => 0.0])
404+
```
405+
so that
406+
```@example faq_remake
407+
println("Correct u0 is: ", (1.0, 0.0, 3.0), "\n", "remade value is: ", nlprob4[(:X₁, :X₂, :X₃)])
408+
```
409+
and
410+
```@example faq_remake
411+
println("Correct Γ is: ", 4.0, "\n", "remade value is: ", nlprob4.ps[:Γ][1])
412+
```
413+
414+
Finally, we note there is one extra consideration to take into account if using
415+
`structural_simplify`. In this case one of `X₁`, `X₂`, or `X₃` will be moved to
416+
being an observed. It will then always correspond to the updated value if one
417+
tries to manually change `Γ`. Let's see what happens here directly
418+
```@example faq_remake
419+
nlsys = convert(NonlinearSystem, rn; remove_conserved = true, conseqs_remake_warn = false)
420+
nlsys = structural_simplify(nlsys)
421+
nlprob1 = NonlinearProblem(nlsys, u0, ps)
422+
```
423+
We can now try to change just `Γ` and implicitly the observed variable that was
424+
removed will be assumed to have changed its initial value to compensate for it.
425+
Let's confirm this. First we find the observed variable that was elminated.
426+
```@example faq_remake
427+
obs_unknown = only(observed(nlsys)).lhs
428+
```
429+
We can figure out its index in `u0` via
430+
```@example faq_remake
431+
obs_symbol = ModelingToolkit.getname(obs_unknown)
432+
obsidx = findfirst(p -> p[1] == obs_symbol, u0)
433+
```
434+
Let's now remake
435+
```@example faq_remake
436+
nlprob2 = remake(nlprob1; u0 = [obs_unknown => nothing], p = [:Γ => [8.0]])
437+
```
438+
Here we indicate that the observed variable should be treated as unspecified
439+
during initialization. Since the observed variable is not considered an unknown,
440+
everything now works, with the observed variable's assumed initial value
441+
adjusted to allow `Γ = 8`:
442+
```@example faq_remake
443+
correct_u0 = last.(u0)
444+
correct_u0[obsidx] = 8 - sum(correct_u0) + correct_u0[obsidx]
445+
println("Correct u0 is: ", (1.0, 2.0, 5.0), "\n", "remade value is: ", nlprob2[(:X₁, :X₂, :X₃)])
446+
```
447+
and `Γ` becomes
448+
```@example faq_remake
449+
println("Correct Γ is: ", 8.0, "\n", "remade value is: ", nlprob2.ps[:Γ][1])
450+
```
451+
Unfortunately, as with our first example, trying to enforce that a
452+
non-eliminated species should have its initial value updated instead of the
453+
observed species will not work.
454+
455+
*Summary:* it is not recommended to directly update `Γ` via `remake`, but to
456+
instead update values of the initial guesses in `u0` to obtain a desired `Γ`. At
457+
this time the behavior when updating `Γ` can result in `u0` values that do not
458+
satisfy the conservation law defined by `Γ` as illustrated above.

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ etc).
4444
- [Optimization.jl](https://github.com/SciML/Optimization.jl), [DiffEqParamEstim.jl](https://github.com/SciML/DiffEqParamEstim.jl), and [PEtab.jl](https://github.com/sebapersson/PEtab.jl) can all be used to [fit model parameters to data](https://sebapersson.github.io/PEtab.jl/stable/Define_in_julia/).
4545
- [GlobalSensitivity.jl](https://github.com/SciML/GlobalSensitivity.jl) can be used to perform [global sensitivity analysis](@ref global_sensitivity_analysis) of model behaviors.
4646
- [SciMLSensitivity.jl](https://github.com/SciML/SciMLSensitivity.jl) can be used to compute local sensitivities of functions containing forward model simulations.
47-
<!--- [StructuralIdentifiability.jl](https://github.com/SciML/StructuralIdentifiability.jl) can be used to perform structural identifiability analysis.-->
47+
- [StructuralIdentifiability.jl](https://github.com/SciML/StructuralIdentifiability.jl) can be used to perform structural identifiability analysis.
4848

4949
#### [Features of packages built upon Catalyst](@id doc_index_features_other_packages)
5050
- Catalyst [`ReactionSystem`](@ref)s can be [imported from SBML files](@ref model_file_import_export_sbml) via [SBMLImporter.jl](https://github.com/sebapersson/SBMLImporter.jl) and [SBMLToolkit.jl](https://github.com/SciML/SBMLToolkit.jl), and [from BioNetGen .net files](@ref model_file_import_export_sbml_rni_net) and various stoichiometric matrix network representations using [ReactionNetworkImporters.jl](https://github.com/SciML/ReactionNetworkImporters.jl).

docs/src/model_creation/conservation_laws.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ Generally, for a conservation law where we have:
133133
If the value of the conservation law parameter $Γ$'s value *has never been specified*, its value will be updated to accommodate changes in species values. If the conservation law parameter ($Γ$)'s value *has been specified* (either when the `ODEProblem` was created, or using `remake`), then the eliminated species's value will be updated to accommodate changes in the conservation law parameter or non-eliminated species's values. Furthermore, in this case, the value of the eliminated species *cannot be updated*.
134134

135135
!!! warn
136-
When updating the values of problems with conservation laws it is additionally important to use `remake` (as opposed to direct indexing, e.g. setting `oprob[:X₁] = 16.0`).
136+
When updating the values of problems with conservation laws it is additionally important to use `remake` (as opposed to direct indexing, e.g. setting `oprob[:X₁] = 16.0`). Moreover, care is needed when using `remake` with `NonlinearProblem`s for which conserved equations have been removed. See [the FAQ](https://docs.sciml.ai/Catalyst/stable/faqs/#faq_remake_nonlinprob) for details on what is supported and what may lead to `u0` values that do not satisfy the conservation law in the special case of `NonlinearProblem`s.
137137

138138
### [Extracting the conservation law parameter's symbolic variable](@id conservation_laws_prob_updating_symvar)
139139
Catalyst represents its models using the [Symbolics.jl](https://github.com/JuliaSymbolics/Symbolics.jl) computer algebraic system, something which allows the user to [form symbolic expressions of model components](@ref simulation_structure_interfacing_symbolic_representation). If you wish to extract and use the symbolic variable corresponding to a model's conserved quantities, you can use the following syntax:

0 commit comments

Comments
 (0)