tkf / Bifurcations.jl

Bifurcation analysis in pure Julia. Totally work-in-progress.
https://tkf.github.io/Bifurcations.jl/dev/
Other
14 stars 4 forks source link

Use diffeq callback instead of manual root finding #10

Open tkf opened 6 years ago

tkf commented 6 years ago

https://github.com/tkf/Bifurcations.jl/blob/4e89cef3d10a0803fb761d35de21aaed5b84003a/docs/src/examples/van_der_pol.md#L33-L42

Datseris commented 6 years ago

I was using callbacks for poincare section intersections in ChaosTools. However, I decided to use manualfinding through step! and Roots. It was not only much faster but also more robust, because if anything went wrong I knew exactly where it went wrong.

You can look the code here:

https://github.com/JuliaDynamics/ChaosTools.jl/blob/master/src/orbitdiagrams/poincare.jl#L64

https://github.com/JuliaDynamics/ChaosTools.jl/blob/master/src/orbitdiagrams/poincare.jl#L97-L104

https://github.com/JuliaDynamics/ChaosTools.jl/blob/master/src/orbitdiagrams/poincare.jl#L126-L130

Of course I can't know your exact case, but my choice of using Roots directly gave me a full order of magnitude speedup.

tkf commented 6 years ago

Thanks for the advice! It's good to know that it isn't worth it before try :)

FYI this is just a demo/tutorial purpose: https://tkf.github.io/Bifurcations.jl/latest/examples/van_der_pol/ so actually the speed is not super important. Probably I should just link DiffEqCallbacks and ChaosTool's poincare map.

ChrisRackauckas commented 5 years ago

The DiffEqBase one is trying to solve somewhat of a different problem from the one George is solving. The DiffEqBase one cannot assume that checking the ends of an interval is sufficient to know whether there's a root, and that's where a lot of the extra cost comes in. Under the hood, the DiffEq one is just using Roots.jl, but it does a lot more checking to understand if there is a crossing first to be robust to cross-backs.

I would say the poincare can't be more robust because I can point out exact cases where it will fail given the above part. Also, the poincare one is not robust to stiffness which will lead to floating point error. The poincare one is just detecting crossings so it doesn't need to do manifold pullbacks, so generally that's not an issue there, but this method would fail for example on the bouncing ball. That said, George's test cases don't cover that because it's not common in that domain. Then again, the manifold pullbacks can go wrong, and so poincare ends up being "more robust" for George's exact case while not being generally robust.

So robustness really depends on what you're looking to achieve.

ChrisRackauckas commented 5 years ago

(Actually, for @Datseris 's case, we can check whether u_modified! and if not, don't prevfloat, but there's a lot of details going on there.)

tkf commented 5 years ago

Under the hood, the DiffEq one is just using Roots.jl, but it does a lot more checking to understand if there is a crossing first to be robust to cross-backs.

I think this could be handy here. Although usually I find starting from a Hopf bifurcation is easier (if possible). Also, in this particular case, it can be started from the known weak nonlinearity limit.

This issue is just a (low-priority) TODO for me to demonstrate how to bridge Julia libraries (and give some pointers to other useful tools like Poincare section in ChaosTools.jl).