Skip to content

Commit e1c9ebe

Browse files
committed
improved tests
1 parent f891e4c commit e1c9ebe

File tree

1 file changed

+95
-13
lines changed

1 file changed

+95
-13
lines changed

test/extensions/bifurcationkit.jl

Lines changed: 95 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,117 @@
11
using BifurcationKit, ModelingToolkit, Test
22

3-
# Checks pitchfork diagram and that there are the correct number of branches (a main one and two children)
4-
let
3+
# Simple pitchfork diagram, compares solution to native BifurcationKit, checks they are identical.
4+
# Checks using `jac=false` option.
5+
let
6+
# Creaets model.
57
@variables t x(t) y(t)
68
@parameters μ α
79
eqs = [0 ~ μ * x - x^3 + α * y,
810
0 ~ -y]
911
@named nsys = NonlinearSystem(eqs, [x, y], [μ, α])
1012

13+
# Creates BifurcationProblem
1114
bif_par = μ
1215
p_start ==> -1.0, α => 1.0]
1316
u0_guess = [x => 1.0, y => 1.0]
14-
plot_var = x
15-
16-
using BifurcationKit
17-
bprob = BifurcationProblem(nsys,
18-
u0_guess,
19-
p_start,
20-
bif_par;
21-
plot_var = plot_var,
22-
jac = false)
17+
plot_var = x;
18+
bprob = BifurcationProblem(nsys, u0_guess, p_start, bif_par; plot_var=plot_var, jac=false)
2319

20+
# Conputes bifurcation diagram.
2421
p_span = (-4.0, 6.0)
2522
opt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)
23+
opts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01,
24+
max_steps = 100, nev = 2, newton_options = opt_newton,
25+
p_min = p_span[1], p_max = p_span[2],
26+
detect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-8, dsmin_bisection = 1e-9)
27+
bif_dia = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside=true)
28+
29+
# Computes bifurcation diagram using BifurcationKit directly (without going through MTK).
30+
function f_BK(u, p)
31+
x, y = u
32+
μ, α =p
33+
return*x - x^3 + α*y, -y]
34+
end
35+
bprob_BK = BifurcationProblem(f_BK, [1.0, 1.0], [-1.0, 1.0], (@lens _[1]); record_from_solution = (x, p) -> x[1])
36+
bif_dia_BK = bifurcationdiagram(bprob_BK, PALC(), 2, (args...) -> opts_br; bothside=true)
37+
38+
# Compares results.
39+
@test getfield.(bif_dia.γ.branch, :x) getfield.(bif_dia_BK.γ.branch, :x)
40+
@test getfield.(bif_dia.γ.branch, :param) getfield.(bif_dia_BK.γ.branch, :param)
41+
@test bif_dia.γ.specialpoint[1].x == bif_dia_BK.γ.specialpoint[1].x
42+
@test bif_dia.γ.specialpoint[1].param == bif_dia_BK.γ.specialpoint[1].param
43+
@test bif_dia.γ.specialpoint[1].type == bif_dia_BK.γ.specialpoint[1].type
44+
end
45+
46+
# Lotka–Volterra model, checks exact position of bifurcation variable and bifurcation points.
47+
# Checks using ODESystem input.
48+
let
49+
# Ceates a Lotka–Volterra model.
50+
@parameters α a b
51+
@variables t x(t) y(t) z(t)
52+
D = Differential(t)
53+
eqs = [D(x) ~ -x + a*y + x^2*y,
54+
D(y) ~ b - a*y - x^2*y]
55+
@named sys = ODESystem(eqs)
56+
57+
# Creates BifurcationProblem
58+
bprob = BifurcationProblem(sys, [x => 1.5, y => 1.0], [a => 0.1, b => 0.5], b; plot_var = x)
59+
60+
# Computes bifurcation diagram.
61+
p_span = (0.0, 2.0)
62+
opt_newton = NewtonPar(tol = 1e-9, max_iterations = 2000)
2663
opts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01,
2764
max_steps = 100, nev = 2, newton_options = opt_newton,
2865
p_min = p_span[1], p_max = p_span[2],
2966
detect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-8,
3067
dsmin_bisection = 1e-9)
68+
bif_dia = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside = true)
3169

32-
bf = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside = true)
70+
# Tests that the diagram has the correct values (x = b)
71+
all([b.x b.param for b in bif_dia.γ.branch])
3372

34-
@test length(bf.child) == 2
73+
# Tests that we get two Hopf bifurcations at the correct positions.
74+
hopf_points = sort(getfield.(filter(sp -> sp.type == :hopf, bif_dia.γ.specialpoint), :x); by=x->x[1])
75+
@test length(hopf_points) == 2
76+
@test hopf_points[1] [0.41998733080424205, 1.5195495712453098]
77+
@test hopf_points[2] [0.7899715592573977, 1.0910379583813192]
3578
end
79+
80+
# Simple fold bifurcation model, checks exact position of bifurcation variable and bifurcation points.
81+
# Checks that default parameter values are accounted for.
82+
# Checks that observables (that depend on other observables, as in this case) are accounted for.
83+
let
84+
# Creates model, and uses `structural_simplify` to generate observables.
85+
@parameters μ p=2
86+
@variables t x(t) y(t) z(t)
87+
D = Differential(t)
88+
eqs = [0 ~ μ - x^3 + 2x^2,
89+
0 ~ p*μ - y,
90+
0 ~ y - z]
91+
@named nsys = NonlinearSystem(eqs, [x, y, z], [μ, p])
92+
nsys = structural_simplify(nsys)
93+
94+
# Creates BifurcationProblem.
95+
bif_par = μ
96+
p_start ==> 1.0]
97+
u0_guess = [x => 1.0, y => 0.1, z => 0.1]
98+
plot_var = x;
99+
bprob = BifurcationProblem(nsys, u0_guess, p_start, bif_par; plot_var=plot_var)
100+
101+
# Computes bifurcation diagram.
102+
p_span = (-4.3, 12.0)
103+
opt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)
104+
opts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01,
105+
max_steps = 100, nev = 2, newton_options = opt_newton,
106+
p_min = p_span[1], p_max = p_span[2],
107+
detect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-8, dsmin_bisection = 1e-9);
108+
bif_dia = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside=true)
109+
110+
# Tests that the diagram has the correct values (x = b)
111+
all([b.x 2*b.param for b in bif_dia.γ.branch])
112+
113+
# Tests that we get two fold bifurcations at the correct positions.
114+
fold_points = sort(getfield.(filter(sp -> sp.type == :bp, bif_dia.γ.specialpoint), :param))
115+
@test length(fold_points) == 2
116+
@test fold_points [-1.1851851706940317, -5.6734983580551894e-6] # test that they occur at the correct parameter values).
117+
end

0 commit comments

Comments
 (0)