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

Disable AD for Continuation #196

Open
fh9g12 opened this issue Dec 18, 2024 · 3 comments
Open

Disable AD for Continuation #196

fh9g12 opened this issue Dec 18, 2024 · 3 comments

Comments

@fh9g12
Copy link

fh9g12 commented Dec 18, 2024

Is it possible to disable automatic differentiation and use finite difference for the calculation of period orbits and normal forms?

I am just starting with Julia and BifurcationKit and as a first step I was trying to replicate results I have generated using AUTO in another programming language. To do this, I wrapped an external call to a function in a different langauge

function derivfunc(X::Vector{Float64},params::Vector{Float64})
    # call to deriv function in other software 
end

derivfunc is not suitable for Automatic differentiation and as such the inputs of the function can only be vectors of real numbers. ( I know this is a slightly contrived example, but the generalised case where automatic differentiation cannot be used in the call to the derivative function seems generic enough)

In terms of the continuation of equilibria, my question is related to #68 . By setting the J = (x,p)->BifurcationKit.finite_differences(z->derivfunc(z,p), x)) in the BifurcationProblem I was able to solve for equilibrium positions. (I have a quick side note here: both #68 and the documentation for BifurcationProblem suggest using BifurcationKit.finiteDifferences. I guess the naming was changed at some point, but the doc string wasn't updated?)

However, I cannot solve for periodic orbits (the continuation of a simple Hopf). Regardless of which method I pick the code will always error on line 243 of Problems.jl

if isnothing(d2F)
    d2F = (x, p, dx1, dx2) -> ForwardDiff.derivative(t -> d1Fad(x .+ t .* dx2, p, dx1), zero(eltype(dx1)))
    d2Fc = (x, p, dx1, dx2) -> BilinearMap((_dx1, _dx2) -> d2F(x, p, _dx1, _dx2))(dx1, dx2)
else
    d2Fc = d2F
end

e.g. it still attempts to calculate the second (and third) derivatives using automatic differentiation. I first tried to 'cheat' this by making d2F not nothing, e.g. (d2F = (x,p,dx1,dx2)->throw(DomainError("Second derivatives not implemented"))) but alas, all the periodic methods I tried require the calculation of d2F. Additionally, I would like to estimate the normal form, which also requires the derivatives.

So my questions:

  1. do any periodic methods not require the calculation of higher-order derivatives?
  2. can you suggest a function to use to calculate d2F and d3F numerically? (I know AUTO / COCO have internal functions for this, but I'll be honest, I've always found it hard to grasp the proper implementation of the higher order derivatives)

Thank you for any help you can provide.

Cheers,
Fintan

@rveltz
Copy link
Member

rveltz commented Dec 18, 2024

Hi,

(I have a quick side note here: both #68 and the documentation for BifurcationProblem suggest using BifurcationKit.finiteDifferences. I guess the naming was changed at some point, but the doc string wasn't updated?)

Thank you for pointing this. The issue is based on an older version of BK so that's why the name difference. Where do you see this in the docs?

@rveltz
Copy link
Member

rveltz commented Dec 18, 2024

However, I cannot solve for periodic orbits (the continuation of a simple Hopf). Regardless of which method I pick the code will always error on line 243 of Problems.jl

Yes, contrary to Auto and Matcont, BK uses the Hopf normal form to have a robust branch switching from a simple Hopf point. That answers your point 1. I could try to add a Basic branch switching ala Auto but that will take some time.

@rveltz
Copy link
Member

rveltz commented Dec 18, 2024

For the other derivatives, you can perhaps use https://github.com/JuliaDiff/FiniteDifferences.jl

Otherwise, this could work (not tested)

δ = 1e-8
d1Fad(x,p,dx1) = (F(x .+ δ .* dx1, p) .- F(x .- δ .* dx1, p)) /(2δ)
d2F(x, p, dx1, dx2) = (d1Fad(x .+ δ .* dx2, p, dx1) - d1Fad(x .- δ .* dx2, p, dx1) )/(2δ)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants