I’m working on a physics project where (very roughly) I need to integrate some Hamiltonian equations of motion and differentiate functions of the resulting trajectories with respect to a parameter \alpha. More precisely, I want to solve the following system of equations for x(t; \alpha) and p(t; \alpha):
\frac{dx}{dt}(t; \alpha) = \frac{\partial H}{\partial p}(x, p, t; \alpha)\\ \frac{dp}{dt}(t; \alpha) = -\frac{\partial H}{\partial x}(x, p, t; \alpha),
and then optimize some functions x(t; \alpha) and p(t; \alpha) with respect to \alpha. Here’s my attempt at this using HamiltonianProblem
from DiffEqPhysics.jl
(modified version of the DiffEqFlux.jl
examples):
using DifferentialEquations
using DiffEqFlux
using Flux
using ForwardDiff
function H(p, x, params) # complicated Hamiltonian
return params[1] * (1 + x[1]^2)^(1/3) * (1 + p[1]^2)^(1/4) # randomly chosen function
end
# Solve the differential equation
function integrateeoms(params)
# Time interval to solve over
tspan = (0.0, 1.0)
# Initial state
p0, x0 = [0.05], [0.01]
# Construct ODE problem
prob = HamiltonianProblem(H, p0, x0, tspan, params)
# Integrate the ODE
Tracker.collect(diffeq_rd(params, prob, VelocityVerlet(), dt=0.1, saveat=0.1))
end
This runs fine if I pass in a plain array (eg, integrateeoms([1.0])
), but fails if I try to track the parameter array (eg, integrateeoms(param([1.0]))
). I get the following error followed by a huge stack trace:
ERROR: MethodError: *(::Tracker.TrackedReal{Float64}, ::ForwardDiff.Dual{ForwardDiff.Tag{DiffEqPhysics.PhysicsTag,Float64},Float64,1}) is ambiguous
Since H is too complicated to analytically differentiate, how can I go about using nested autodifferentiation here?
Internally, HamiltonianProblem
uses ForwardDiff.jl
to take partial derivatives of H. Is there a way to selectively turning off tracking for x and p after taking those derivatives to avoid the type problems?
Thanks!