Thanks for your help. I finally understand your approach. I haven’t known that do
with nested integration can speed up functions until now and it reduce allocations drastically. In my practice, I found that defining two nested functions has the similar timing as your method:
using QuadGK,HCubature,BenchmarkTools,Richardson
function Sigma1(η)
hcubature((0.0,0.0),(2*pi,4*pi/sqrt(3))) do (kx, ky)
ϵ = spinonenergy(kx, ky)
quadgk(-Inf, Inf) do ω
-1/pi*sqrt(3)/2*1/(2*pi)^2 * imag(inv(ω - ϵ + im*η))
end[1]
end[1]
end
function Sigma2(η)
function intergrand1(kx,ky)
ϵ = spinonenergy(kx, ky);
-1/pi*sqrt(3)/2*1/(2*pi)^2 * quadgk(-Inf, Inf) do ω
imag(inv(ω - ϵ + im*η))
end[1]
end
int=hcubature((0.0,0.0),(2*pi,4*pi/sqrt(3))) do (kx, ky)
intergrand1(kx,ky)
end[1];
return(int)
end
@btime Sigma1(0.001)
219.100 μs (71 allocations: 29.78 KiB)
1.0000000000000029
@btime Sigma2(0.001)
213.100 μs (71 allocations: 29.78 KiB)
1.0000000000000027
However, I still cannot understand why integration order influencing radically. Since I have to integrate frequency first then integrate over (kx,ky) in further codes. I guess you already know that this order add huge allocations, do you have some idea to reduce this?
function Sigma4(η)
function intergrand1(ω)
-1/pi*sqrt(3)/2*1/(2*pi)^2 * hcubature((0.0,0.0),(2*pi,4*pi/sqrt(3)),rtol=1e-4,atol=1e-4) do (kx, ky)
imag(inv(ω - spinonenergy(kx, ky) + im*η))
end[1]
end
int=quadgk(-Inf, Inf,rtol=1e-4,atol=1e-4) do ω
intergrand1(ω)
end[1]
return(int)
end
@btime Sigma4(0.001)
9.222 s (157371111 allocations: 5.71 GiB)
0.999984450612222