# Failure of Zygote.jl on function with integration by HCubature.jl

I need to perform automatic differentiation on a function constructed by numerical integration. I choose `HCubature.jl` on integral and `Zygote.jl` on AD. However, there is an error as following:

``````using HCubature,Zygote

const kb::Float64=1;

const tem::Float64=1/9600;

nf(e,tem)=inv(expm1(e/(kb*tem))+2.0)

spinonenergy(kx,ky,h,mu)=(-2*(cos(kx)+cos(ky)))-h-mu

SD_spinon(omega,kx,ky,h,mu)=
-1/pi*imag(inv(omega+1e-2*im-spinonenergy(kx,ky,h,mu)))

function GSE(mu,h)
integrand_spinon(omega,kx,ky)=
omega*SD_spinon(omega,kx,ky,h,mu)*nf(omega,tem)

int_spinon=hcubature(x->integrand_spinon(x,x,x), (-5,-pi,-pi), (5,pi,pi),maxevals=Int(2e+7),rtol=1e-4, atol=1e-4)

return 1/(2*pi)^2*(int_spinon)
end

let
energy(x) = GSE(-0.5,x)

end

ArgumentError: new: too few arguments (expected 1)
``````

What cause this error and how could I fix it?

If I turn to use `Cubature`, the error would become to

``````using Cubature, Zygote
#Everything is the same as above mentioned
let
energy(x) = GSE(-0.5,x)

end
Compiling Tuple{typeof(Cubature.integrands), Cubature.IntegrandData{var"#3#5"{var"#integrand_spinon#4"{Float64, Float64}}}, Bool, Bool, Bool}: UndefVarError: `spvals` not defined
``````

For this sort of thing, I would recommend using HCubature via Integrals.jl, which provides a wrapper that has AD chain rules written for it, so that Zygote does not try to differentiate through it “manually”.

I rewrite the function with integration into `Integrals.jl`, however there is still a problem in `Zygote.jl`

``````using Integrals,Zygote
function GSE(mu,h)
integrand_spinon(u,p)=
u*SD_spinon(u,u,u,h,mu)*nf(u,tem)

int_spinon = IntegralProblem(integrand_spinon, (-5.0,-pi*1,-pi*1), (5.0,pi*1,pi*1))

sol_spinon = solve(int_spinon, HCubatureJL(); reltol = 1e-3, abstol = 1e-3)

return 1/(2*pi)^2*(sol_spinon.u)
end

let
energy(x) = GSE(-0.5,x)

end
MethodError: no method matching length(::SciMLBase.NullParameters)
An arithmetic operation was performed on a NullParameters object. This means no parameters were passed
into the AbstractSciMLProblem (e.x.: ODEProblem) but the parameters object `p` was used in an arithmetic
expression. Two common reasons for this issue are:

1. Forgetting to pass parameters into the problem constructor. For example, `ODEProblem(f,u0,tspan)` should
be `ODEProblem(f,u0,tspan,p)` in order to use parameters.

2. Using the wrong function signature. For example, with `ODEProblem`s the function signature is always
`f(du,u,p,t)` for the in-place form or `f(u,p,t)` for the out-of-place form. Note that the `p` argument
will always be in the function signature reguardless of if the problem is defined with parameters!
``````

BTW, functions by `Integrals.jl` support `ForwardDiff.jl` and the results are correct. Actually, my final goal is minimize the function `GSE` through `Optim.jl` with some derivative dependent algorithms, but only errors I received.

I think you might have some errors in the way parameters are handled (see this tutorial). The following should work but I’m missing some functions so I can’t test:

``````using Integrals, Zygote

function integrand_spinon(u, p)
mu, h = p, p
return u*SD_spinon(u,u,u,h,mu)*nf(u,tem)
end

function GSE(mu, h)
lb = (-5.0,-pi*1,-pi*1)
ub = (5.0,pi*1,pi*1)
p = [mu, h]
int_spinon = IntegralProblem(integrand_spinon, lb, ub, p)
sol_spinon = solve(int_spinon, HCubatureJL(); reltol = 1e-3, abstol = 1e-3)
return 1/(2*pi)^2*(sol_spinon.u)
end

energy(x) = GSE(-0.5, x)