Skip to content

Commit 847077b

Browse files
authored
Merge pull request #707 from SciML/BifurcationKitExtension
Bifurcation kit extension
2 parents 38ea201 + 80e94d6 commit 847077b

File tree

14 files changed

+388
-103
lines changed

14 files changed

+388
-103
lines changed

HISTORY.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,35 @@
2424
```
2525
X's value will be `1.0` in the first vertex, but `0.0` in the remaining one (the system have 25 vertexes in total). SInce th parameters `p` and `d` are part of the non-spatial reaction network, their values are tied to vertexes. However, if the `D` parameter (which governs diffusion between vertexes) is given several values, these will instead correspond to the specific edges (and transportation along those edges.)
2626

27+
- Add a CatalystBifurcationKitExtension, permitting BifurcationKit's `BifurcationProblem`s to be created from Catalyst reaction networks. Example usage:
28+
```julia
29+
using Catalyst
30+
wilhelm_2009_model = @reaction_network begin
31+
k1, Y --> 2X
32+
k2, 2X --> X + Y
33+
k3, X + Y --> Y
34+
k4, X --> 0
35+
k5, 0 --> X
36+
end
37+
38+
39+
using BifurcationKit
40+
bif_par = :k1
41+
u_guess = [:X => 5.0, :Y => 2.0]
42+
p_start = [:k1 => 4.0, :k2 => 1.0, :k3 => 1.0, :k4 => 1.5, :k5 => 1.25]
43+
plot_var = :X
44+
bprob = BifurcationProblem(wilhelm_2009_model, u_guess, p_start, bif_par; plot_var=plot_var)
45+
46+
p_span = (2.0, 20.0)
47+
opts_br = ContinuationPar(p_min = p_span[1], p_max = p_span[2], max_steps=1000)
48+
49+
bif_dia = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside=true)
50+
51+
using Plots
52+
plot(bif_dia; xguide="k1", yguide="X")
53+
```
54+
- Automatically handles elimination of conservation laws for computing bifurcation diagrams.
55+
- Updated Bifurcation documentation with respect to this new feature.
2756

2857
## Catalyst 13.5
2958
- Added a CatalystHomotopyContinuationExtension extension, which exports the `hc_steady_state` function if HomotopyContinuation is exported. `hc_steady_state` finds the steady states of a reaction system using the homotopy continuation method. This feature is only available for julia versions 1.9+. Example:

Project.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,25 @@ Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
2424
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
2525

2626
[weakdeps]
27+
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
2728
HomotopyContinuation = "f213a82b-91d6-5c5d-acf7-10f1c761b327"
2829

2930
[extensions]
31+
CatalystBifurcationKitExtension = "BifurcationKit"
3032
CatalystHomotopyContinuationExtension = "HomotopyContinuation"
3133

3234
[compat]
35+
BifurcationKit = "0.3"
3336
DataStructures = "0.18"
3437
DiffEqBase = "6.83.0"
3538
DocStringExtensions = "0.8, 0.9"
3639
Graphs = "1.4"
3740
JumpProcesses = "9.3.2"
41+
HomotopyContinuation = "2.9"
3842
LaTeXStrings = "1.3.0"
3943
Latexify = "0.14, 0.15, 0.16"
4044
MacroTools = "0.5.5"
41-
ModelingToolkit = "8.66"
45+
ModelingToolkit = "8.73"
4246
Parameters = "0.12"
4347
Reexport = "0.2, 1.0"
4448
Requires = "1.0"
@@ -50,6 +54,7 @@ Unitful = "1.12.4"
5054
julia = "1.9"
5155

5256
[extras]
57+
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
5358
DomainSets = "5b8099bc-c8ec-5219-889f-1d9e522a28bf"
5459
Graphviz_jll = "3c863552-8265-54e4-a6dc-903eb78fde85"
5560
HomotopyContinuation = "f213a82b-91d6-5c5d-acf7-10f1c761b327"
@@ -68,4 +73,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
6873
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
6974

7075
[targets]
71-
test = ["DomainSets", "Graphviz_jll", "HomotopyContinuation", "NonlinearSolve", "OrdinaryDiffEq", "Random", "SafeTestsets", "SciMLBase", "SciMLNLSolve", "StableRNGs", "Statistics", "SteadyStateDiffEq", "StochasticDiffEq", "Test", "Unitful"]
76+
test = ["BifurcationKit", "DomainSets", "Graphviz_jll", "HomotopyContinuation", "NonlinearSolve", "OrdinaryDiffEq", "Random", "SafeTestsets", "SciMLBase", "SciMLNLSolve", "StableRNGs", "Statistics", "SteadyStateDiffEq", "StochasticDiffEq", "Test", "Unitful"]

docs/src/api/catalyst_api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ netstoichmat
180180
reactionrates
181181
```
182182

183-
## Functions to extend or modify a network
183+
## (Functions to extend or modify a network)(@id api_network_extension_and_modification)
184184
`ReactionSystem`s can be programmatically extended using
185185
[`@add_reactions`](@ref), [`addspecies!`](@ref), [`addparam!`](@ref) and
186186
[`addreaction!`](@ref), or using [`ModelingToolkit.extend`](@ref) and

docs/src/catalyst_applications/bifurcation_diagrams.md

Lines changed: 90 additions & 87 deletions
Large diffs are not rendered by default.

docs/src/catalyst_applications/homotopy_continuation.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ The order of the species in the output vectors are the same as in `species(wilhe
3838

3939
It should be noted that the steady state multivariate polynomials produced by reaction systems may have both imaginary and negative roots, which are filtered away by `hc_steady_states`. If you want the negative roots, you can use the `hc_steady_states(wilhelm_2009_model, ps; filter_negative=false)` argument.
4040

41-
4241
## [Systems with conservation laws](@id homotopy_continuation_conservation_laws)
4342
Some systems are under-determined, and have an infinite number of possible steady states. These are typically systems containing a conservation
4443
law, e.g.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module CatalystBifurcationKitExtension
2+
3+
# Fetch packages.
4+
using Catalyst
5+
import BifurcationKit as BK
6+
7+
# Creates and exports hc_steady_states function.
8+
include("CatalystBifurcationKitExtension/bifurcation_kit_extension.jl")
9+
10+
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
### Dispatch for BifurcationKit BifurcationProblems ###
2+
3+
# Creates a BifurcationProblem, using a ReactionSystem as an input.
4+
function BK.BifurcationProblem(rs::ReactionSystem, u0_bif, ps, bif_par, args...;
5+
plot_var=nothing, record_from_solution=BK.record_sol_default, jac=true, u0=[], kwargs...)
6+
7+
# Converts symbols to symbolics.
8+
(bif_par isa Symbol) && (bif_par = rs.var_to_name[bif_par])
9+
(plot_var isa Symbol) && (plot_var = rs.var_to_name[plot_var])
10+
((u0_bif isa Vector{<:Pair{Symbol,<:Any}}) || (u0_bif isa Dict{Symbol, <:Any})) && (u0_bif = symmap_to_varmap(rs, u0_bif))
11+
((ps isa Vector{<:Pair{Symbol,<:Any}}) || (ps isa Dict{Symbol, <:Any})) && (ps = symmap_to_varmap(rs, ps))
12+
((u0 isa Vector{<:Pair{Symbol,<:Any}}) || (u0 isa Dict{Symbol, <:Any})) && (u0 = symmap_to_varmap(rs, u0))
13+
14+
# Creates NonlinearSystem.
15+
Catalyst.conservationlaw_errorcheck(rs, vcat(ps, u0))
16+
nsys = convert(NonlinearSystem, rs; remove_conserved=true, defaults=Dict(u0))
17+
18+
# Makes BifurcationProblem (this call goes through the ModelingToolkit-based BifurcationKit extension).
19+
return BK.BifurcationProblem(nsys, u0_bif, ps, bif_par, args...; plot_var=plot_var,
20+
record_from_solution=record_from_solution, jac=jac, kwargs...)
21+
end

ext/CatalystHomotopyContinuationExtension/homotopy_continuation_extension.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ function steady_state_polynomial(rs::ReactionSystem, ps, u0)
4747
rs = Catalyst.expand_registered_functions(rs)
4848
ns = convert(NonlinearSystem, rs; remove_conserved = true)
4949
pre_varmap = [symmap_to_varmap(rs,u0)..., symmap_to_varmap(rs,ps)...]
50-
conservationlaw_errorcheck(rs, pre_varmap)
50+
Catalyst.conservationlaw_errorcheck(rs, pre_varmap)
5151
p_vals = ModelingToolkit.varmap_to_vars(pre_varmap, parameters(ns); defaults = ModelingToolkit.defaults(ns))
5252
p_dict = Dict(parameters(ns) .=> p_vals)
5353
eqs_pars_funcs = vcat(equations(ns), conservedequations(rs))

src/networkapi.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,18 @@ Compute conserved quantities for a system with the given conservation laws.
12771277
"""
12781278
conservedquantities(state, cons_laws) = cons_laws * state
12791279

1280+
1281+
# If u0s are not given while conservation laws are present, throws an error.
1282+
# Used in HomotopyContinuation and BifurcationKit extensions.
1283+
# Currently only checks if any u0s are given
1284+
# (not whether these are enough for computing conserved quantitites, this will yield a less informative error).
1285+
function conservationlaw_errorcheck(rs, pre_varmap)
1286+
vars_with_vals = Set(p[1] for p in pre_varmap)
1287+
any(s -> s in vars_with_vals, species(rs)) && return
1288+
isempty(conservedequations(Catalyst.flatten(rs))) ||
1289+
error("The system has conservation laws but initial conditions were not provided for some species.")
1290+
end
1291+
12801292
######################## reaction network operators #######################
12811293

12821294
"""

src/reactionsystem.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,7 @@ Keyword args and default values:
12871287
function Base.convert(::Type{<:ODESystem}, rs::ReactionSystem; name = nameof(rs),
12881288
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
12891289
include_zero_odes = true, remove_conserved = false, checks = false,
1290+
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
12901291
kwargs...)
12911292
spatial_convert_err(rs::ReactionSystem, ODESystem)
12921293
fullrs = Catalyst.flatten(rs)
@@ -1299,7 +1300,7 @@ function Base.convert(::Type{<:ODESystem}, rs::ReactionSystem; name = nameof(rs)
12991300
ODESystem(eqs, get_iv(fullrs), sts, ps;
13001301
observed = obs,
13011302
name,
1302-
defaults = defs,
1303+
defaults = _merge(defaults,defs),
13031304
checks,
13041305
continuous_events = MT.get_continuous_events(fullrs),
13051306
discrete_events = MT.get_discrete_events(fullrs),
@@ -1326,6 +1327,7 @@ Keyword args and default values:
13261327
function Base.convert(::Type{<:NonlinearSystem}, rs::ReactionSystem; name = nameof(rs),
13271328
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
13281329
include_zero_odes = true, remove_conserved = false, checks = false,
1330+
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
13291331
kwargs...)
13301332
spatial_convert_err(rs::ReactionSystem, NonlinearSystem)
13311333
fullrs = Catalyst.flatten(rs)
@@ -1339,7 +1341,7 @@ function Base.convert(::Type{<:NonlinearSystem}, rs::ReactionSystem; name = name
13391341
NonlinearSystem(eqs, sts, ps;
13401342
name,
13411343
observed = obs,
1342-
defaults = defs,
1344+
defaults = _merge(defaults,defs),
13431345
checks,
13441346
kwargs...)
13451347
end
@@ -1375,6 +1377,7 @@ function Base.convert(::Type{<:SDESystem}, rs::ReactionSystem;
13751377
noise_scaling = nothing, name = nameof(rs),
13761378
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
13771379
include_zero_odes = true, checks = false, remove_conserved = false,
1380+
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
13781381
kwargs...)
13791382
spatial_convert_err(rs::ReactionSystem, SDESystem)
13801383

@@ -1435,7 +1438,9 @@ Notes:
14351438
"""
14361439
function Base.convert(::Type{<:JumpSystem}, rs::ReactionSystem; name = nameof(rs),
14371440
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
1438-
remove_conserved = nothing, checks = false, kwargs...)
1441+
remove_conserved = nothing, checks = false,
1442+
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
1443+
kwargs...)
14391444
spatial_convert_err(rs::ReactionSystem, JumpSystem)
14401445

14411446
(remove_conserved !== nothing) &&
@@ -1457,7 +1462,7 @@ function Base.convert(::Type{<:JumpSystem}, rs::ReactionSystem; name = nameof(rs
14571462
JumpSystem(eqs, get_iv(flatrs), sts, ps;
14581463
observed = MT.observed(flatrs),
14591464
name,
1460-
defaults = MT.defaults(flatrs),
1465+
defaults = _merge(defaults,MT.defaults(flatrs)),
14611466
checks,
14621467
discrete_events = MT.discrete_events(flatrs),
14631468
kwargs...)

0 commit comments

Comments
 (0)