|
1 | 1 | # Bifurcation Diagrams
|
2 |
| -Bifurcation diagrams can be produced from Catalyst generated models through the use of the [BifurcationKit.jl](https://github.com/rveltz/BifurcationKit.jl/) package. This tutorial gives a simple example of how to create such a bifurcation diagram. |
| 2 | +Bifurcation diagrams can be produced from Catalyst generated models through the |
| 3 | +use of the [BifurcationKit.jl](https://github.com/rveltz/BifurcationKit.jl/) |
| 4 | +package. This tutorial gives a simple example of how to create such a |
| 5 | +bifurcation diagram. |
3 | 6 |
|
4 |
| -First, we declare our model. For this example we will use a bistable switch, but one which also contains a Hopf bifurcation. |
| 7 | +First, we declare our reaction model. For this example we will use a bistable |
| 8 | +switch, but one which also contains a Hopf bifurcation. |
5 | 9 | ```@example ex1
|
6 | 10 | using Catalyst
|
7 | 11 | rn = @reaction_network begin
|
8 |
| - (v0+v*(S*X)^n/((S*X)^n+(D*A)^n+K^n),d), ∅ ↔ X |
9 |
| - (X/τ,1/τ), ∅ ↔ A |
| 12 | + (v0 + v*(S * X)^n / ((S*X)^n + (D*A)^n + K^n), d), ∅ ↔ X |
| 13 | + (X/τ, 1/τ), ∅ ↔ A |
10 | 14 | end S D τ v0 v K n d
|
11 | 15 | ```
|
12 |
| -Next, we specify the system parameters for which we wish to plot the bifurcation diagram. We also set the parameter we wish to vary in our bifurcation diagram, as well as over which interval. Finally, we set which variable we wish to plot the steady state values of in the diagram. |
| 16 | +Next, we specify the system parameters for which we wish to plot the bifurcation |
| 17 | +diagram. We also set the parameter we wish to vary in our bifurcation diagram, |
| 18 | +as well as the interval to vary it over. Finally, we set which variable we wish |
| 19 | +to plot the steady state values of in the bifurcation plot. |
13 | 20 | ```@example ex1
|
14 |
| -p = [:S=>1., :D=>9., :τ=>1000., :v0=>0.01, :v=>2., :K=>20., :n=>3, :d=>0.05] |
15 |
| -bif_par = :S |
16 |
| -p_span = (0.1,20.) |
17 |
| -plot_var = :X |
| 21 | +p = Dict(:S => 1., :D => 9., :τ => 1000., :v0 => 0.01, |
| 22 | + :v => 2., :K => 20., :n => 3, :d => 0.05) |
| 23 | +bif_par = :S # bifurcation parameter |
| 24 | +p_span = (0.1, 20.) # interval to vary S over |
| 25 | +plot_var = :X # we will plot X vs S |
18 | 26 | ```
|
19 |
| -When creating a bifurcation diagram, we typically start in some point in parameter-phase space. For parameter space, we will simply select the beginning of the interval over which we wish to computer the bifurcation diagram. We thus create a modified parameter set where this is the case. For this parameter set, we make a guess of an initial fixed point. While a good estimate could be provided through e.g. a simulation, the guess do not need to be very exact. |
| 27 | +When creating a bifurcation diagram, we typically start at some point in |
| 28 | +parameter phase-space. We will simply select the beginning of the interval over |
| 29 | +which we wish to compute the bifurcation diagram, `p_span[1]`. We thus create a |
| 30 | +modified parameter set where `S = .1`. For this parameter set, we also make a |
| 31 | +guess for the steady-state of the system. While a good estimate could be |
| 32 | +provided through an ODE simulation, BifurcationKit does not require the guess to |
| 33 | +be very accurate. |
20 | 34 | ```@example ex1
|
21 |
| -p_bstart = setindex!(copy(p),bif_par => p_span[1],findfirst(first.(p).==bif_par)) |
22 |
| -u0 = [:X=>1.0, :A=>1.0] |
| 35 | +p_bstart = copy(p) |
| 36 | +p_bstart[bif_par] = p_span[1] |
| 37 | +u0 = [:X => 1.0, :A => 1.0] |
23 | 38 | ```
|
24 |
| -Finally, we extract the ode function and jacobian of our model in a form that BifurcationKit can read. |
| 39 | +Finally, we extract the ODE derivative function and its jacobian in a form that |
| 40 | +BifurcationKit can use: |
25 | 41 | ```@example ex1
|
26 |
| -oprob = ODEProblem(rn,u0,(0.0,0.0),p_bstart;jac=true) |
27 |
| -F = (u,p) -> oprob.f(u,p,0) |
28 |
| -J = (u,p) -> oprob.f.jac(u,p,0) |
| 42 | +oprob = ODEProblem(rn, u0, (0.0,0.0), p_bstart; jac = true) |
| 43 | +F = (u,p) -> oprob.f(u, p, 0) |
| 44 | +J = (u,p) -> oprob.f.jac(u, p, 0) |
29 | 45 | ```
|
30 | 46 |
|
31 |
| -Now, we fetch the required packages to create the bifurcation diagram. We also bundle the information we have compiled so far into a `BifurcationProblem`. |
| 47 | +In creating an `ODEProblem` an ordering is chosen for the initial condition and |
| 48 | +parameters, and regular `Float64` vectors of their numerical values are created |
| 49 | +as `oprob.u0` and `oprob.p` respectively. BifurcationKit needs to know the index |
| 50 | +in `oprob.p` of our bifurcation parameter, `:S`, and the index in `oprob.u0` of |
| 51 | +the variable we wish to plot, `:X`. We calculate these as |
| 52 | +```@example ex1 |
| 53 | +# get S and X as a symbolic variables |
| 54 | +@unpack S, X = rn |
| 55 | +
|
| 56 | +# find their indices in oprob.p and oprob.u0 respectively |
| 57 | +bif_idx = findfirst(isequal(S), parameters(rn)) |
| 58 | +plot_idx = findfirst(isequal(X), species(rn)) |
| 59 | +``` |
| 60 | + |
| 61 | +Now, we load the required packages to create and plot the bifurcation diagram. |
| 62 | +We also bundle the information we have compiled so far into a |
| 63 | +`BifurcationProblem`. |
32 | 64 | ```@example ex1
|
33 | 65 | using BifurcationKit, Plots, LinearAlgebra, Setfield
|
34 |
| -bprob = BifurcationProblem(F, oprob.u0, oprob.p, (@lens _[findfirst(first.(p).==bif_par)]); recordFromSolution = (x, p) -> x[findfirst(first.(u0).==plot_var)], J=J) |
| 66 | +
|
| 67 | +bprob = BifurcationProblem(F, oprob.u0, oprob.p, (@lens _[bif_idx]); |
| 68 | + recordFromSolution = (x, p) -> x[plot_idx], J = J) |
35 | 69 | ```
|
36 |
| -Next, we need to specify the input options for the pseudo-arclength continuation method which produces the diagram. |
| 70 | +Next, we need to specify the input options for the pseudo-arclength continuation method (PACM) which produces the diagram. |
37 | 71 | ```@example ex1
|
38 |
| -bopts = ContinuationPar(dsmax = 0.05, # Maximum arclength value of the pseudo-arc length continuation method. |
39 |
| - dsmin = 1e-4, # Minimum arclength value of the pseudo-arc length continuation method. |
40 |
| - ds=0.001, # Initial arclength value of the pseudo-arc length continuation method (should be positive). |
41 |
| - maxSteps = 100000, # The maximum number of steps. |
42 |
| - pMin = p_span[1], # Minimum p-vale (if hit, the method stops). |
43 |
| - pMax = p_span[2], # Maximum p-vale (if hit, the method stops). |
44 |
| - detectBifurcation=3) # Value in {0,1,2,3} determining to what extent bifurcation points are detected (0 means nothing is done, 3 both them and there localisation are detected). |
| 72 | +bopts = ContinuationPar(dsmax = 0.05, # Max arclength in PACM. |
| 73 | + dsmin = 1e-4, # Min arclength in PACM. |
| 74 | + ds=0.001, # Initial (positive) arclength in PACM. |
| 75 | + maxSteps = 100000, # Max number of steps. |
| 76 | + pMin = p_span[1], # Min p-val (if hit, the method stops). |
| 77 | + pMax = p_span[2], # Max p-val (if hit, the method stops). |
| 78 | + detectBifurcation = 3) # Value in {0,1,2,3} |
45 | 79 | ```
|
46 |
| -With all this done, we can compute the bifurcation diagram: |
| 80 | +Here `detectBifurcation` determines to what extent bifurcation points are |
| 81 | +detected and how accurately their values are determined. Three indicates to use the most |
| 82 | +accurate method for calculating their values. |
| 83 | + |
| 84 | +We are now ready to compute the bifurcation diagram: |
47 | 85 | ```@example ex1
|
48 |
| -bf = bifurcationdiagram(bprob, PALC(),2, (args...) -> bopts) |
| 86 | +bf = bifurcationdiagram(bprob, PALC(), 2, (args...) -> bopts) |
49 | 87 | ```
|
50 | 88 | Finally, we can plot it:
|
51 | 89 | ```@example ex1
|
52 |
| -plot(bf) |
| 90 | +plot(bf, xlabel = string(bif_par), ylabel = string(plot_var)) |
53 | 91 | ```
|
54 | 92 |
|
55 |
| -Here, Hopf bifurcation is marked with a red dot and fold bifurcation with blue dots. The region with a thinner linewidth corresponds to unstable steady states. |
56 |
| - |
57 |
| -This tutorial demonstrates how to make a simple bifurcation diagram where all branches are connected. However, BifurcationKit.jl is a very powerful package capable of a lot more. For more details, please see that package's documentation: [BifurcationKit.jl](https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/). |
| 93 | +Here, the Hopf bifurcation is marked with a red dot and the fold bifurcations |
| 94 | +with blue dots. The region with a thinner line width corresponds to unstable |
| 95 | +steady states. |
58 | 96 |
|
| 97 | +This tutorial demonstrated how to make a simple bifurcation diagram where all |
| 98 | +branches are connected. However, BifurcationKit.jl is a very powerful package |
| 99 | +capable of a lot more. For more details, please see that package's |
| 100 | +documentation: |
| 101 | +[BifurcationKit.jl](https://bifurcationkit.github.io/BifurcationKitDocs.jl/dev/). |
0 commit comments