Skip to content

Commit 2960221

Browse files
committed
improve approach a bit
1 parent 7547841 commit 2960221

File tree

2 files changed

+26
-28
lines changed

2 files changed

+26
-28
lines changed

docs/src/steady_state_functionality/bifurcation_diagrams.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Bifurcation diagrams describe how, for a dynamical system, the quantity and type
44

55
This tutorial briefly introduces how to use Catalyst with BifurcationKit through basic examples, with BifurcationKit.jl providing [a more extensive documentation](https://bifurcationkit.github.io/BifurcationKitDocs.jl/stable/). Especially for more complicated systems, where careful tuning of algorithm options might be required, reading the BifurcationKit documentation is recommended. Finally, BifurcationKit provides many additional features not described here, including [computation of periodic orbits](https://bifurcationkit.github.io/BifurcationKitDocs.jl/stable/periodicOrbit/), [tracking of bifurcation points along secondary parameters](https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/branchswitching/), and [bifurcation computations for PDEs](https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/tutorials/tutorials/#PDEs:-bifurcations-of-equilibria).
66

7-
## Basic example
7+
## [Basic example](@id bifurcation_diagrams_basics)
88
For this example, we will use a modified version of the model from Wilhelm (2009)[^2] (which
99
demonstrates a bistable switch as the parameter $k1$ is varied). We declare the model using Catalyst:
1010
```@example ex1
@@ -55,7 +55,7 @@ plot(bif_dia; xguide = "k1", yguide = "X")
5555
```
5656
Here, the steady state concentration of $X$ is shown as a function of $k1$'s value. Stable steady states are shown with thick lines, unstable ones with thin lines. The two [fold bifurcation points](https://en.wikipedia.org/wiki/Saddle-node_bifurcation) are marked with "bp".
5757

58-
## Additional `ContinuationPar` options
58+
## [Additional `ContinuationPar` options](@id bifurcation_diagrams_contpar_option)
5959
Most of the options required by the `bifurcationdiagram` function are provided through the `ContinuationPar` structure. For full details, please read the [BifurcationKit documentation](https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/library/#BifurcationKit.ContinuationPar). However, a few common options, and how they affect the continuation computation, are described here:
6060
- `p_min` and `p_max`: Set the interval over which the bifurcation diagram is computed (with the continuation stopping if it reaches these bounds).
6161
- `dsmin` and `dsmax`: The minimum and maximum length of the continuation steps (in the bifurcation parameter's value).
@@ -74,7 +74,7 @@ nothing # hide
7474
```
7575
(however, in this case these additional settings have no significant effect on the result)
7676

77-
## Bifurcation diagrams with disjoint branches
77+
## [Bifurcation diagrams with disjoint branches](@id bifurcation_diagrams_disjoint_branches)
7878
Let's consider the previous case, but instead compute the bifurcation diagram over the interval $(2.0,15.0)$:
7979
```@example ex1
8080
p_span = (2.0, 15.0)
@@ -85,7 +85,7 @@ plot(bif_dia; xguide = "k1", yguide = "X")
8585
Here, in the bistable region, we only see a single branch. The reason is that the continuation algorithm starts at our initial guess (here made at $k1 = 4.0$ for $(X,Y) = (5.0,2.0)$) and tracks the diagram from there. However, with the upper bound set at $k1=15.0$ the bifurcation diagram has a disjoint branch structure, preventing the full diagram from being computed by continuation alone. In this case it could be solved by increasing the bound from $k1=15.0$, however, this is not possible in all cases. In these cases, *deflation* can be used. This is described in the [BifurcationKit documentation](https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/tutorials/tutorials2/#Snaking-computed-with-deflation).
8686

8787

88-
## Systems with conservation laws
88+
## [Systems with conservation laws](@id bifurcation_diagrams_conservation_laws)
8989
Some systems are under-determined at steady state, so that for a given parameter set they have an infinite number of possible steady state solutions, preventing bifurcation diagrams from being computed. Similar to when we [compute steady states for fixed parameter values](@ref homotopy_continuation_conservation_laws), we can utilise Catalyst's ability to detect and eliminate conservation laws to resolve this issue. This requires us to provide information of the species concentrations at which we wish to compute the bifurcation diagram (to determine the values of conserved quantities). These are provided to the `BifurcationProblem` using the `u0` argument.
9090

9191
To illustrate this, we will create a simple model of a kinase that is produced and degraded (at rates $p$ and $d$). The kinase facilitates the phosphorylation of a protein ($X$), which is dephosphorylated at a constant rate. For this system, we will compute a bifurcation diagram, showing how the concentration of the phosphorylated protein ($Xp$) depends on the degradation rate of the kinase ($d$). We will set the total amount of protein ($X+Xp$) to $1.0$.

docs/src/steady_state_functionality/examples/nullcline_plotting.md

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,51 +45,44 @@ ps = [v => 1.0, K => 0.6, n => 4.0]
4545
sss = hc_steady_states(bs_switch, ps; show_progress = false)
4646
```
4747

48-
Finally, we will compute the nullclines. We will first extract our models steady state equations (which we do by creating a `NonlinearSystem`).
48+
Finally, we will compute the nullclines. We will first extract our model's steady state equations (which we do by creating a `NonlinearSystem`).
4949
```@example nullcline_plotting
5050
nlsys = convert(NonlinearSystem, bs_switch)
5151
eqs = equations(nlsys)
5252
```
53-
Here, each equation is an expression of two variables. To plot the corr
54-
55-
@parameters Xval Yval
56-
nc_eq_X = substitute(equations(nlsys)[1], Dict([X => Xval]))
57-
nc_eq_Y = substitute(equations(nlsys)[2], Dict([Y => Yval]))
58-
```
59-
60-
We will first extract the equations corresponding to these from our model. Next, we will compute them using [BifurcationKit.jl](https://github.com/bifurcationkit/BifurcationKit.jl). To generate our equations, we first convert our model to a `NonlinearSystem`. For each nullcline equation, we also have to replace the corresponding variable with a parameter (which can be varied to compute the full nullcline curve).
53+
Here, each equation is an expression of two variables ($X$ and $Y$). We wish to plot $Y$ as a function of $X$. To do this, we will substitute the species variable $X$ with the parameter $Xpar$. This will enable us to carry out bifurcation analysis of the equations' solutions as $Xpar$ is varied
6154
```@example nullcline_plotting
62-
@parameters Xval Yval
63-
nlsys = convert(NonlinearSystem, bs_switch)
64-
nc_eq_X = substitute(equations(nlsys)[1], Dict([X => Xval]))
65-
nc_eq_Y = substitute(equations(nlsys)[2], Dict([Y => Yval]))
55+
@parameters Xpar
56+
nc_eq_X = substitute(equations(nlsys)[1], Dict([X => Xpar]))
57+
nc_eq_Y = substitute(equations(nlsys)[2], Dict([X => Xpar]))
6658
```
67-
Next, we compute a `NonlinerSystem` corresponding to each nullcline.
59+
To input these into BifurcationKit we need to convert these into `NonlinearSystem`s.
6860
```@example nullcline_plotting
6961
@named nc_X_sys = NonlinearSystem([nc_eq_X])
7062
@named nc_Y_sys = NonlinearSystem([nc_eq_Y])
7163
nc_X_sys = complete(nc_X_sys)
7264
nc_Y_sys = complete(nc_Y_sys)
65+
nothing # hide
7366
```
74-
Finally, for each of these, we can use BifurcationKit's `continuation` function to track the solution of the nullclines as the corresponding variable (the workflow is similar to when we used `bifurcationdiagram` [here](@ref bifurcation_diagrams)).
67+
Finally, for out nullcline equations, we can use BifurcationKit's `continuation` function to track their solutions across all values of $Xpar$ (the workflow is similar to when we used `bifurcationdiagram` [here](@ref bifurcation_diagrams)).
7568
```@example nullcline_plotting
7669
using BifurcationKit
7770
span = (0.0, 1.2)
78-
function compute_nullcline(nc_sys, span, var_solve, pvar_bif)
79-
bprob = BifurcationProblem(nc_sys, [var_solve => 1.0], [ps; pvar_bif => 1.0], pvar_bif; plot_var = var_solve)
80-
opts_br = ContinuationPar(p_min = span[1], p_max = span[2], dsmax = 0.01) # `dsmax = 0.01` ensures a smooth plot.
71+
function compute_nullcline(nc_sys)
72+
bprob = BifurcationProblem(nc_sys, [Y => 1.0], [ps; Xval => 0.1], Xval)
73+
opts_br = ContinuationPar(p_min = span[1], p_max = span[2], dsmax = 0.01)
8174
return continuation(bprob, PALC(), opts_br; bothside = true)
8275
end
83-
nc_X = compute_nullcline(nc_X_sys, span, Y, Xval)
84-
nc_Y = compute_nullcline(nc_Y_sys, span, X, Yval)
76+
nc_X = compute_nullcline(nc_X_sys)
77+
nc_Y = compute_nullcline(nc_Y_sys)
8578
nothing # hide
8679
```
8780

88-
Finally, we are ready to create our plot. We will plot the steady states using `scatter`. We use the `steady_state_stability` function to [compute steady state stabilities](@ref steady_state_stability) (and use this to determine how to plot the steady state markers).
81+
We are ready to create our plot. We will plot the steady states using `scatter`. We use the `steady_state_stability` function to [compute steady state stabilities](@ref steady_state_stability) (and use this to determine how to plot the steady state markers).
8982
```@example nullcline_plotting
9083
using Plots
91-
plot(nc_X; vars = (:x, :param), label = "dX/dt = 0", lw = 7, la = 0.7)
92-
plot!(nc_Y; vars = (:param, :x), label = "dY/dt = 0", lw = 7, la = 0.7)
84+
plot(nc_X.x, nc_X.param; label = "dX/dt = 0", lw = 7, la = 0.7)
85+
plot!(nc_Y.x, nc_Y.param; label = "dY/dt = 0", lw = 7, la = 0.7)
9386
for ss in sss
9487
color, markershape = if steady_state_stability(ss, bs_switch, ps)
9588
:blue, :circle
@@ -104,7 +97,11 @@ plot!(xlimit = span, ylimit = span, xguide = "X", yguide = "Y", legendfontsize =
10497
```
10598
Here we can see how the steady states occur at the nullclines intersections.
10699

100+
!!! warn
101+
BifurcationKit's `continuation` function will not detect disjoint branches, and above we can only use it because we know that each nullcline consists of a single branch. To handle disjoint nullclines, consider using [deflated continuation](@ref bifurcation_diagrams_disjoint_branches) (or possibly a package like [Contour.jl](https://github.com/JuliaGeometry/Contour.jl)).
102+
107103
## [Plotting system directions in phase space](@id nullcline_plotting_directions)
104+
One useful property of nullclines is that the sign of $dX/dt$ will only switch whenever the solution crosses the $dX/dt=0$ nullcline. This mean that, within each region defined by the nullclines, the direction of the solution remains constant. Below we use this to, for each such region, plot arrows showing the solution's direction.
108105

109106
```@example nullcline_plotting
110107
nlprob = NonlinearProblem(complete(nlsys), [X => 0.0, Y => 0.0], ps)
@@ -122,4 +119,5 @@ end
122119
arrow_positions = [(0.25, 0.25), (0.75, 0.75), (0.35, 0.8), (0.8, 0.35), (0.02, 1.1), (1.1, 0.02)]
123120
foreach(pos -> plot_xy_arrow!(pos...), arrow_positions)
124121
plot!()
125-
```
122+
```
123+
This also works as a form of simple stability analysis, where we can see how the solution moves *away* from the unstable steady state, and *to* the stable ones.

0 commit comments

Comments
 (0)