Here is a working example. There are two functions, the Coulomb_matrix() function just takes in a vector of Float numbers, and gives out a matrix of float numbers. The test() is having strange behaviour. Here is the full script:
function Coulomb_matrix(kvec::Vector{Float64})::Matrix{Float64}
s1=[9047.5636*exp(-norm(kvec)) for ja in 1:10, jb in 1:10]
cmatrix=kron(ones(Float64,4,4),s1)
return cmatrix
end
function test()
radius=1.4
num_points=20
dimension=40
kx_grid=collect(range(-radius/2, stop=+radius/2, length=num_points))
ky_grid=collect(range(-radius/2, stop=+radius/2, length=num_points))
k_set=Vector{Float64}[]
for ja in eachindex(kx_grid),jb in eachindex(ky_grid)
push!(k_set,[kx_grid[ja],ky_grid[jb]])
end
l1=zeros(ComplexF64,dimension,dimension,length(k_set))
l2=zeros(ComplexF64,dimension,dimension,length(k_set))
density_matrix=ones(ComplexF64,dimension,dimension,length(k_set))
Threads.@threads for ja in eachindex(k_set)
for jb in eachindex(k_set)
cmatrix=Coulomb_matrix(k_set[ja]-k_set[jb])
l2[:,:,ja]+=(cmatrix.*density_matrix[:,:,jb])
end
end
println("maxl2",sort(vec(abs.(l2)))[end])
Threads.@threads for ja in eachindex(k_set)
for jb in eachindex(k_set)
fcmatrix=Coulomb_matrix(k_set[ja]-k_set[jb])
l1[:,:,ja]+=(fcmatrix.*density_matrix[:,:,jb])
end
end
println("maxl1",sort(abs.(vec(l1)))[end])
println("l1,l2",l1==l2)
println(sum(abs.(l1-l2)))
cmatrix=Coulomb_matrix([0.0,0.0])
l3=diagm(cmatrix*diag(dropdims(sum(density_matrix,dims=3),dims=3)))
end
I am seeing strange behaviour in the function test(). Supposedly l1 and l2 should be equal to each other. They are both three-dimensional ComplexF64 arrays. The only difference is that when I compute l1 and l2, they need to use some intermediate arrays from the Coulomb_matrix() function. In one case, I call the intermediate array cmatrix, the other case, I call it fcmatrix (below)
Threads.@threads for ja in eachindex(k_set)
for jb in eachindex(k_set)
cmatrix=Coulomb_matrix(k_set[ja]-k_set[jb])
l2[:,:,ja]+=(cmatrix.*density_matrix[:,:,jb])
end
end
Threads.@threads for ja in eachindex(k_set)
for jb in eachindex(k_set)
fcmatrix=Coulomb_matrix(k_set[ja]-k_set[jb])
l1[:,:,ja]+=(fcmatrix.*density_matrix[:,:,jb])
end
end
The strange thing is that the test(), as it is written, will report l1 is not equal to l2. I was guessing that this is because the threading syntax I wrote was not appropriate, i.e. I probably should not thread over l2[:,:,index], and perform in-place addition (actually why? I had the impression that this should be safe). Since in the code below, I only access one slice of l2 every time.
Threads.@threads for ja in eachindex(k_set)
for jb in eachindex(k_set)
cmatrix=Coulomb_matrix(k_set[ja]-k_set[jb])
l2[:,:,ja]+=(cmatrix.*density_matrix[:,:,jb])
end
end
But the strangest thing is that if you just delete the last two lines, the test() will just report l1 is indeed equal to l2, which confuses a lot. Why would this happen?
cmatrix=Coulomb_matrix([0.0,0.0])
l3=diagm(cmatrix*diag(dropdims(sum(density_matrix,dims=3),dims=3)))