Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bifurcation kit extension #2300

Closed
wants to merge 63 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
e56de20
split parameters linearize bug
Sep 25, 2023
cee69ed
added old MatrixGain definition for comparison
Sep 25, 2023
b4f821e
new promote_to_concrete
Sep 25, 2023
e62e3ee
improvements to protmote_to_concrete
Sep 26, 2023
ee4deb9
remake issue
Sep 26, 2023
a9c56b6
Suppose heterogeneous parameters for linearize and remake
YingboMa Sep 26, 2023
1a96915
Fix zero_dummy_der
YingboMa Sep 26, 2023
023e024
Relax tests
YingboMa Sep 26, 2023
119cb27
Don't use SciMLBase 2
YingboMa Sep 26, 2023
6bb0b2e
Merge branch 'master' into bgc/split_params_bug
YingboMa Oct 2, 2023
29aec7b
Fix eq ordering
YingboMa Oct 2, 2023
addf335
Change bounds back
YingboMa Oct 2, 2023
2e4c1bb
Format
YingboMa Oct 2, 2023
2a553a7
Be careful with string sorting
YingboMa Oct 2, 2023
f9ea3a6
Update LaTeXify ref tests
YingboMa Oct 2, 2023
c2f92f1
init
TorkelE Oct 4, 2023
b05bc5f
makefunction
TorkelE Oct 4, 2023
f2d80b0
1.6 has a different term ordering
YingboMa Oct 4, 2023
ae05041
Fix DiscreteProblem construction
YingboMa Oct 4, 2023
2309f9f
Merge pull request #2283 from SciML/bgc/split_params_bug
YingboMa Oct 4, 2023
fb7c3af
Update Project.toml
YingboMa Oct 4, 2023
6e795b8
Fix recursive structure and setup precompilation
ChrisRackauckas Oct 6, 2023
7949761
Merge pull request #2301 from SciML/precompile_workload
ChrisRackauckas Oct 6, 2023
c5bd821
docs(refactor): update acausal components tutorial with `@mtkmodel`
ven-k Sep 27, 2023
6ac545d
docs(refactor): update structural identifiability tutorial with `@mtk…
ven-k Sep 27, 2023
278698b
docs(fix): set a `u0` within the constraint for the optimization problem
ven-k Sep 28, 2023
94fb749
docs(refactor): refactor "Getting Started" section with `@mtkmodel`
ven-k Oct 3, 2023
438a225
docs(refactor): rename the `@mtkmodel` docs page as "Defining compone…
ven-k Oct 3, 2023
ff2a778
docs: reword Components and Connectors and elaborate Connectors and M…
ven-k Oct 3, 2023
2ef4752
docs: add `connect` section to Variable metadata
ven-k Oct 3, 2023
3034c9f
Merge pull request #2286 from ven-k/vkb/mtkmodel-examples
ChrisRackauckas Oct 8, 2023
c4868e3
Add `@mtkbuild` greatly simplify the tutorials
ChrisRackauckas Oct 8, 2023
ac75e77
Add `parent` to hierarchical systems and set it in `structural_simplify`
YingboMa Oct 8, 2023
b0c2938
Format
YingboMa Oct 8, 2023
c3c030e
Add "docs/src/assets/*.toml" to gitignore
YingboMa Oct 8, 2023
cd0f04a
Add tests
YingboMa Oct 8, 2023
0d5ab59
Fix CI
YingboMa Oct 8, 2023
7370a45
fix tutorial syntax
ChrisRackauckas Oct 8, 2023
137d3d1
Support implicit name unpack in `at extend`
YingboMa Oct 8, 2023
c679dd9
fix acausal tutorial
ChrisRackauckas Oct 8, 2023
17a3b6a
Merge pull request #2305 from SciML/mtkbuild
ChrisRackauckas Oct 8, 2023
3d83c4c
one more tutorial simplification
ChrisRackauckas Oct 8, 2023
0a9dca1
Merge branch 'master' into myb/extend
YingboMa Oct 8, 2023
73f9e0a
Stop using `at testset` macro
YingboMa Oct 8, 2023
718ae81
Remove ODAEProblem from acausal tutorial
ChrisRackauckas Oct 8, 2023
0bcdee8
Merge pull request #2308 from SciML/odaeproblem
YingboMa Oct 8, 2023
379161f
Merge pull request #2307 from SciML/tuts
YingboMa Oct 8, 2023
314bb1d
Merge pull request #2306 from SciML/myb/extend
YingboMa Oct 9, 2023
298a9a5
patch system names
ChrisRackauckas Oct 9, 2023
bdc45d1
Simplify `at extend`
YingboMa Oct 9, 2023
1152f30
update docs for new extension syntax
ChrisRackauckas Oct 9, 2023
9e45fee
fix for simplified extend
ChrisRackauckas Oct 9, 2023
563f04f
Merge pull request #2310 from SciML/myb/extend
ChrisRackauckas Oct 9, 2023
2c17d63
Merge pull request #2309 from SciML/extend
ChrisRackauckas Oct 9, 2023
d4239a7
Update Project.toml
ChrisRackauckas Oct 9, 2023
bc93796
non canonical docstrings
ArnoStrouwen Oct 14, 2023
b54b05b
update contributing docs
ArnoStrouwen Oct 14, 2023
0ef0bb4
Merge pull request #2315 from ArnoStrouwen/docs
ChrisRackauckas Oct 14, 2023
2c86306
updates
TorkelE Oct 14, 2023
3249aeb
init
TorkelE Oct 4, 2023
7f5d8be
makefunction
TorkelE Oct 4, 2023
c4a1a20
updates
TorkelE Oct 14, 2023
918f5e6
Merge remote-tracking branch 'TorkelE/BifurcationKitExtension' into B…
TorkelE Oct 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[weakdeps]
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"

[extensions]
MTKBifurcationKitExt = "BifurcationKit"
MTKDeepDiffsExt = "DeepDiffs"

[compat]
Expand Down Expand Up @@ -100,6 +102,7 @@ julia = "1.6"

[extras]
AmplNLWriter = "7c4d4715-977e-5154-bfe0-e096adeac482"
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
ControlSystemsMTK = "687d7614-c7e5-45fc-bfc3-9ee385575c88"
DeepDiffs = "ab62b9b5-e342-54a8-a765-a90f495de1a6"
Expand All @@ -123,4 +126,4 @@ Sundials = "c3572dad-4567-51f8-b174-8c6c989267f4"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["AmplNLWriter", "BenchmarkTools", "ControlSystemsMTK", "NonlinearSolve", "ForwardDiff", "Ipopt", "Ipopt_jll", "ModelingToolkitStandardLibrary", "Optimization", "OptimizationOptimJL", "OptimizationMOI", "Random", "ReferenceTests", "SafeTestsets", "StableRNGs", "Statistics", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials", "StochasticDelayDiffEq"]
test = ["AmplNLWriter", "BifurcationKit", "BenchmarkTools", "ControlSystemsMTK", "NonlinearSolve", "ForwardDiff", "Ipopt", "Ipopt_jll", "ModelingToolkitStandardLibrary", "Optimization", "OptimizationOptimJL", "OptimizationMOI", "Random", "ReferenceTests", "SafeTestsets", "StableRNGs", "Statistics", "SteadyStateDiffEq", "Test", "StochasticDiffEq", "Sundials", "StochasticDelayDiffEq"]
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
BifurcationKit = "0f109fa4-8a5d-4b75-95aa-f515264e7665"
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Expand Down
1 change: 1 addition & 0 deletions docs/pages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pages = [
"tutorials/modelingtoolkitize.md",
"tutorials/stochastic_diffeq.md",
"tutorials/parameter_identifiability.md",
"tutorials/bifurcation_diagram_computation.md",
"tutorials/domain_connections.md"],
"Examples" => Any["Basic Examples" => Any["examples/higher_order.md",
"examples/spring_mass.md",
Expand Down
93 changes: 93 additions & 0 deletions docs/src/tutorials/bifurcation_diagram_computation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# [Bifurcation Diagrams](@id bifurcation_diagrams)
Bifurcation diagrams describes how, for a dynamic system, the quantity and quality of its steady states changes with a parameter's value. These can be computed through the [BifurcationKit.jl](https://github.com/bifurcationkit/BifurcationKit.jl) package. ModelingToolkit provides a simple interface for creating BifurcationKit compatible `BifurcationProblem`s from `NonlinearSystem`s and `ODESystem`s. All teh features provided by BifurcationKit can then be applied to these systems. This tutorial provides a brief introduction for these features, with BifurcationKit.jl providing [a more extensive documentation](https://bifurcationkit.github.io/BifurcationKitDocs.jl/stable/).

### Creating a `BifurcationProblem`
Let us first consider a simple `NonlinearSystem`:
```@example Bif1
using ModelingToolkit
@variables t x(t) y(t)
@parameters μ α
eqs = [0 ~ μ*x - x^3 + α*y,
0 ~ -y]
@named nsys = NonlinearSystem(eqs, [x, y], [μ, α])
```
we wish to compute a bifurcation diagram for this system as we vary the parameter `μ`. For this, we need to provide the following information:
1. The system for which we wish to compute the bifurcation diagram (`nsys`).
2. The parameter which we wish to vary (`μ`).
3. The parameter set for which we want to compute the bifurcation diagram.
4. An initial guess of the state of the system for which there is a steady state at our provided parameter value.
5. The variable which value we wish to plot in the bifurcation diagram (this argument is optional, if not provided, BifurcationKit default plot functions are used).

We declare this additional information:
```@example Bif1
bif_par = μ
p_start = [μ => -1.0, α => 1.0]
u0_guess = [x => 1.0, y => 1.0]
plot_var = x;
```
For the initial state guess (`u0_guess`), typically any value can be provided, however, read BifurcatioKit's documentation for more details.

We can now create our `BifurcationProblem`, which can be provided as input to BifurcationKit's various functions.
```@example Bif1
using BifurcationKit
bprob = BifurcationProblem(nsys, u0_guess, p_start, bif_par; plot_var=plot_var, jac=false)
```
Here, the `jac` argument (by default set to `true`) sets whenever to provide BifurcationKit with a Jacobian or not.


### Computing a bifurcation diagram

Let us consider the `BifurcationProblem` from the last section. If we wish to compute the corresponding bifurcation diagram we must first declare various settings used by BifurcationKit to compute the diagram. These are stored in a `ContinuationPar` structure (which also contain a `NewtonPar` structure).
```@example Bif1
p_span = (-4.0, 6.0)
opt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)
opts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01,
max_steps = 100, nev = 2, newton_options = opt_newton,
p_min = p_span[1], p_max = p_span[2],
detect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-8, dsmin_bisection = 1e-9);
```
Here, `p_span` sets the interval over which we wish to compute the diagram.

Next, we can use this as input to our bifurcation diagram, and then plot it.
```@example Bif1
bf = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside=true)
```
Here, the value `2` sets how sub-branches of the diagram that BifurcationKit should compute. Generally, for bifurcation diagrams, it is recommended to use the `bothside=true` argument.
```@example Bif1
using Plots
plot(bf; putspecialptlegend=false, markersize=2, plotfold=false, xguide="μ", yguide = "x")
```
Here, the system exhibits a pitchfork bifurcation at *μ=0.0*.

### Using `ODESystem` inputs
It is also possible to use `ODESystem`s (rather than `NonlinearSystem`s) as input to `BifurcationProblem`. Here follows a brief such example.

```@example Bif2
using BifurcationKit, ModelingToolkit, Plots

@variables t x(t) y(t)
@parameters μ
D = Differential(t)
eqs = [D(x) ~ μ*x - y - x*(x^2+y^2),
D(y) ~ x + μ*y - y*(x^2+y^2)]
@named osys = ODESystem(eqs, t)

bif_par = μ
plot_var = x
p_start = [μ => 1.0]
u0_guess = [x => 0.0, y=> 0.0]

bprob = BifurcationProblem(osys, u0_guess, p_start, bif_par; plot_var=plot_var, jac=false)

p_span = (-3.0, 3.0)
opt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)
opts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01,
max_steps = 100, nev = 2, newton_options = opt_newton,
p_max = p_span[2], p_min = p_span[1],
detect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-8, dsmin_bisection = 1e-9)

bf = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside=true)
using Plots
plot(bf; putspecialptlegend=false, markersize=2, plotfold=false, xguide="μ", yguide = "x")
```
Here, the value of `x` in the steady state does not change, however, at `μ=0` a Hopf bifurcation occur and the steady state turn unstable.
40 changes: 40 additions & 0 deletions ext/MTKBifurcationKitExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module MTKBifurcationKitExt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix the naming.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what should I name it?


println("BifurcationKit extension loaded")

### Preparations ###

# Imports
using ModelingToolkit, Setfield
import BifurcationKit

### Creates BifurcationProblem Overloads ###

# When input is a NonlinearSystem.
function BifurcationKit.BifurcationProblem(nsys::NonlinearSystem, u0_bif, ps, bif_par, args...; plot_var=nothing, record_from_solution=BifurcationKit.record_sol_default, jac=true, kwargs...)

Check warning on line 14 in ext/MTKBifurcationKitExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/MTKBifurcationKitExt.jl#L14

Added line #L14 was not covered by tests
# Creates F and J functions.
ofun = NonlinearFunction(nsys; jac=jac)
F = ofun.f
J = jac ? ofun.jac : nothing

Check warning on line 18 in ext/MTKBifurcationKitExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/MTKBifurcationKitExt.jl#L16-L18

Added lines #L16 - L18 were not covered by tests

# Computes bifurcation parameter and plot var indexes.
bif_idx = findfirst(isequal(bif_par), parameters(nsys))
if !isnothing(plot_var)
plot_idx = findfirst(isequal(plot_var), states(nsys))
record_from_solution = (x, p) -> x[plot_idx]

Check warning on line 24 in ext/MTKBifurcationKitExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/MTKBifurcationKitExt.jl#L21-L24

Added lines #L21 - L24 were not covered by tests
end

# Converts the input state guess.
u0_bif = ModelingToolkit.varmap_to_vars(u0_bif, states(nsys))
ps = ModelingToolkit.varmap_to_vars(ps, parameters(nsys))

Check warning on line 29 in ext/MTKBifurcationKitExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/MTKBifurcationKitExt.jl#L28-L29

Added lines #L28 - L29 were not covered by tests

return BifurcationKit.BifurcationProblem(F, u0_bif, ps, (@lens _[bif_idx]), args...; record_from_solution = record_from_solution, J = J, kwargs...)

Check warning on line 31 in ext/MTKBifurcationKitExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/MTKBifurcationKitExt.jl#L31

Added line #L31 was not covered by tests
end

# When input is a ODESystem.
function BifurcationKit.BifurcationProblem(osys::ODESystem, args...; kwargs...)
nsys = NonlinearSystem([0 ~ eq.rhs for eq in equations(osys)], states(osys), parameters(osys); name=osys.name)
return BifurcationKit.BifurcationProblem(nsys, args...; kwargs...)

Check warning on line 37 in ext/MTKBifurcationKitExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/MTKBifurcationKitExt.jl#L35-L37

Added lines #L35 - L37 were not covered by tests
end

end # module
29 changes: 29 additions & 0 deletions test/extensions/bifurcationkit.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using BifurcationKit, ModelingToolkit, Test

# Checks pitchfork diagram and that there are the correct number of branches (a main one and two children)
let
@variables t x(t) y(t)
@parameters μ α
eqs = [0 ~ μ*x - x^3 + α*y,
0 ~ -y]
@named nsys = NonlinearSystem(eqs, [x, y], [μ, α])

bif_par = μ
p_start = [μ => -1.0, α => 1.0]
u0_guess = [x => 1.0, y => 1.0]
plot_var = x;

using BifurcationKit
bprob = BifurcationProblem(nsys, u0_guess, p_start, bif_par; plot_var=plot_var, jac=false)

p_span = (-4.0, 6.0)
opt_newton = NewtonPar(tol = 1e-9, max_iterations = 20)
opts_br = ContinuationPar(dsmin = 0.001, dsmax = 0.05, ds = 0.01,
max_steps = 100, nev = 2, newton_options = opt_newton,
p_min = p_span[1], p_max = p_span[2],
detect_bifurcation = 3, n_inversion = 4, tol_bisection_eigenvalue = 1e-8, dsmin_bisection = 1e-9);

bf = bifurcationdiagram(bprob, PALC(), 2, (args...) -> opts_br; bothside=true)

@test length(bf.child) == 2
end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ end
@safetestset "OptimizationSystem Test" include("optimizationsystem.jl")
@safetestset "FuncAffect Test" include("funcaffect.jl")
@safetestset "Constants Test" include("constants.jl")
@safetestset "BifurcationKit Extension Test" include("extensions/bifurcationkit.jl")
# Reference tests go Last
@safetestset "Latexify recipes Test" include("latexify.jl")
Loading