Skip to content

Commit

Permalink
Merge 4529be4 into 8fbdc46
Browse files Browse the repository at this point in the history
  • Loading branch information
TorkelE committed Jun 9, 2024
2 parents 8fbdc46 + 4529be4 commit d39c7bc
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ etc).
**NOTE:** version 14 is a breaking release, prompted by the release of ModelingToolkit.jl version 9. This caused several breaking changes in how Catalyst models are represented and interfaced with.

Breaking changes and new functionality are summarized in the
[HISTORY.md](HISTORY.md) file.
[HISTORY.md](HISTORY.md) file. Furthermore, a migration guide on how to adapt your workflows to the
the new v14 update can be found [here](https://docs.sciml.ai/Catalyst/stable/v14_migration_guide/).

## Tutorials and documentation

Expand Down
1 change: 0 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ makedocs(sitename = "Catalyst.jl",
doctest = false,
clean = true,
pages = pages,
pagesonly = true,
warnonly = [:missing_docs])

deploydocs(repo = "github.com/SciML/Catalyst.jl.git";
Expand Down
188 changes: 188 additions & 0 deletions docs/src/v14_migration_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Version 14 Migration Guide

Catalyst is built on the [ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl) modelling language. A recent update of ModelingToolkit from version 8 to version 9 have required a corresponding update to Catalyst (from version 13 to 14). This update have introduced a couple of breaking changes, all of which will be detailed below.

!!! note
Catalyst version 14 also introduces a large number of new features. These will not be discussed here, however, they are described in Catalyst's [history file]([@ref ](https://github.com/SciML/Catalyst.jl/blob/master/HISTORY.md)).

## System completeness
In ModelingToolkit v19 (and thus also Catalyst v14) all systems (e.g. `ReactionSystem`s and `ODESystem`s) are either *complete* or *incomplete* (completeness was a thing previously, however, recent updates mean that the user now have to be aware of this). Complete and incomplete systems differ in that
- Only complete models can be used as inputs to simulations or certain tools for model analysis.
- Only incomplete models can be [composed with other models to form hierarchical models](@ref compositional_modeling).

A model's completeness depends on how it was created:
- Models created programmatically (using the `ReactionSystem` constructor) are *incomplete*.
- Models created using the `@reaction_network` DSL are *complete*.
- To create *incomplete models using the DSL*, use the `@network_component` macro.
- Models generated through the `compose` and `extend` functions are *incomplete*.

Furthermore, any systems generated through e.g. `convert(ODESystem, rs)` are also complete.

Complete models can be generated from incomplete models through the `complete` function. Here is a workflow where we take completeness into account in the simulation of a simple birth-death process.
```@example v14_migration_1
using Catalyst
t = default_t()
@species X(t)
@parameters p d
rxs = [
Reaction(p, [], [X]),
Reaction(d, [X], [])
]
@named rs = ReactionSystem(rxs, t)
```
Here we have created an incomplete model. If we think our model is ready (i.e. we do not wish to compose it with additional models) we mark it as complete:
```@example v14_migration_1
rs = complete(rs)
```
Here, `complete` does not change the input model, but simply creates a new complete model. We hence overwrite our model variable (`rs`) with `complete`'s output. We can confirm that our model is complete using the `iscomplete` function
```@example v14_migration_1
Catalyst.iscomplete(rs)
```
We can now go on and use our model for e.g. simulations:
```@example v14_migration_1
using OrdinaryDiffEq, Plots
u0 = [X => 0.1]
tspan = (0.0, 10.0)
ps = [d => 1.0, d => 0.2]
oprob = ODEProblem(rs, u0, tspan, ps)
sol = solve(oprob)
plot(sol)
```

if we wish to first create a `ODESystem` from our `ReactionSystem`, the created `ODESystem` will be incomplete:
```@example v14_migration_1
osys = convert(ODESystem, rs)
Catalyst.iscomplete(osys)
```
(note that `rs` must be complete before it can be converted to a `ODESystem`)

If we now wish to create an `ODEProblem` from our `ODESystem`, we must first mark it as complete (using similar syntax as for our `ReactionSystem`):
```@example v14_migration_1
osys = complete(osys)
oprob = ODEProblem(osys, u0, tspan, ps)
sol = solve(oprob)
plot(sol)
```

## Unknowns instead of states
Previously, "states" was used as a term for a systems variables (both species and non-species variables). Now, the term "unknowns" is preferred instead. This means that there have been a number of changes to function names (e.g. `states` => `unknowns`, `get_states` => `get_unknowns`).

E.g. here we declare a `ReactionSystem` model containing both species and non-species unknowns:
```@example v14_migration_2
using Catalyst
t = default_t()
D = default_time_deriv()
@species X(t)
@variables V(t)
@parameters p d Vmax
eqs = [
Reaction(p, [], [X]),
Reaction(d, [X], []),
D(V) ~ Vmax - V*X*d/p
]
@named rs = ReactionSystem(eqs, t)
```
We can now use `unknowns` to retrieve all unknowns
```@example v14_migration_2
unknowns(rs)
```
Meanwhile, `species` and `nonspecies` (like previously) returns all species or non-species unknowns, respectively:
```@example v14_migration_2
species(rs)
```
```@example v14_migration_2
nonspecies(rs)
```

## Lost support for most units
As part of its v9 update, ModelingToolkit changed how units was handled. This includes using the package [DynamicQuantities.jl](https://github.com/SymbolicML/DynamicQuantities.jl) to manage units (instead of [Uniful.jl](https://github.com/PainterQubits/Unitful.jl), like previously).

While this should lead to long-term improvements, unfortunately, as part of the process support for most units where removed. Currently, only the main SI units are supported (`s`, `m`, `kg`, `A`, `K`, `mol`, and `cd`). Composite units (e.g. `N = kg/(m^2)`) are no longer supported. Furthermore, prefix units (e.g. `mm = m/1000`) are not supported either. This means that most units relevant to Catalyst (such as `µM`) cannot be used directly. While composite units can still be written out in full and used (e.f. `mol/(m^3)`) this is hardly user friendly.

The maintainers of ModelingTOolkit have been notified of this issue. We are unsure when this will be fixed, however, we do not think it will be a permanent change.

## Removed support for system-mutating functions
According to ModelingToolkit policy, created systems should not be modified. In accordance with this, the following functions have been deprecated: `addparam!`, `addreaction!`, `addspecies!`, `@add_reactions`, and `merge!`. Please use `ModelingToolkit.extend` and `ModelingToolkit.compose` to generate new merged and/or composed `ReactionSystems` from multiple component systems.

It is still possible to add default values to a created `ReactionSystem`, i.e. the `setdefaults!` function is still supported.

## New interface for creating time variable (`t`) and its differential (`D`)

Previously, the time independent variable (typically called `t`) was declared using
```@example v14_migration_3
using Catalyst
@variables t
nothing # hide
```
A new, preferred, interface have now been introduced:
```@example v14_migration_3
t = default_t()
nothing # hide
```

Similarly, the time differential (primarily relevant when creating combined reaction-equation models) used to be declared through
```@example v14_migration_3
D = Differential(t)
nothing # hide
```
where the preferred method now being
```@example v14_migration_3
Dt = default_time_deriv()
nothing # hide
```

## New interface for accessing problem/integrator/solution parameter (and species) value

Previously, it was possible to index problems to query them for their parameter values. e.g.
```@example v14_migration_4
using Catalyst
rn = @reaction_network begin
(p,d), 0 <--> X
end
oprob = ODEProblem(rn, [:X => 1.0], (0.0, 1.0), [:p => 1.0, :d => 0.2])
nothing # hide
```julia
oprob[:p]
```
This *is no longer supported*. When you wish to query a problem (or integrator or solution) for a parameter value (or to update a parameter value), you must append `.ps` to the problem:
```@example v14_migration_4
oprob.ps[:p]
```

Furthermore, a few new functions (`getp`, `getu`, `setp`, `setu`) have been introduced. These can improve performance when querying a structure for a value multiple times (especially for very large models). These are describe in more detail [here](@ref simulation_structure_interfacing_functions).

For more details on how to query various structures for parameter and species values, please read [this documentation page](@ref simulation_structure_interfacing).

## Other notes
Finally, here are some additional, minor, notes regarding the new update.

### Modification of problems with conservation laws broken
While it is possible to update e.g. `ODEProblem`s using the [`remake`](@ref simulation_structure_interfacing_problems_remake) function, this is not possible if the `remove_conserved = true` option was used. E.g. while
```@example v14_migration_5
using Catalyst, OrdinaryDiffEq
rn = @reaction_network begin
(k1,k2), X1 <--> X2
end
u0 = [:X1 => 1.0, :X2 => 2.0]
ps = [:k1 => 0.5, :k2 => 3.0]
oprob = ODEProblem(rn, u0, (0.0, 10.0), ps; remove_conserved = true)
sol(oprob)
# hide
```
is perfectly fine, attempting to then modify `oprob` (in any manner!) is not possible (without introducing a bug):
```@example v14_migration_5
oprob_remade = remake(oprob; u0 = [:X1 => 5.0]) # NEVER do this.
sol(oprob)
# hide
```

This bug was likely present on earlier versions as well, but was only recently discovered. While we hope it will be fixed soon, the bug is in ModelingToolkit, and will not be fixed until its maintainers find the time to do so.

### Depending on parameter order even more dangerous than before
In early versions of Catalyst, parameters and species were provided as vectors (e.g. `[1.0, 2.0]`) rather than maps (e.g. `[p => 1.0, d => 2.0]`). While it has been *strongly* recommended to use the map form for a while, the vector form is still (technically) possible (however, we would not guarantee that this would produce expected behaviours). However, due to recent internal ModelingToolkit updates, the risk of unexpected behaviour when providing parameter values as vector is even larger than before.

*Users should never use vector-forms to represent parameter and species values*

### Additional deprecated functions
The `reactionparams`, `numreactionparams`, and `reactionparamsmap` functions have been deprecated.
File renamed without changes.

0 comments on commit d39c7bc

Please sign in to comment.