Fixed V algorithm to pick closest pairs
This commit is contained in:
parent
84c41e0646
commit
abcf18fec2
50
common.jl
50
common.jl
|
|
@ -1,5 +1,7 @@
|
|||
Float = Union{Float32,Float64}
|
||||
|
||||
norm_square(x::Array{Int})::Int = sum(x .* x)
|
||||
|
||||
"Eq (46): Partial derivative matrix element for 1 degree of freedom"
|
||||
function ∂_1DOF(L::T, N::Int, k::Int, l::Int)::Complex{T} where {T<:Float}
|
||||
if k == l
|
||||
|
|
@ -9,35 +11,43 @@ function ∂_1DOF(L::T, N::Int, k::Int, l::Int)::Complex{T} where {T<:Float}
|
|||
end
|
||||
end
|
||||
|
||||
"Which index (dimension of the multidimensional array) corresponds to this dimension and coordinate?"
|
||||
which_index(n::Int, dim::Int, coord::Int)::Int = (dim - 1) * (n - 1) + coord
|
||||
"Which index (dimension of the multidimensional array) corresponds to spatial dimension 'dim' and particle 'p'?"
|
||||
which_index(n::Int, dim::Int, p::Int)::Int = (dim - 1) * (n - 1) + p
|
||||
|
||||
"k value of the given degree of freedom at the corresponding index, with coord=0 always returning 0"
|
||||
get_k(n::Int, N::Int, i::CartesianIndex, dim::Int, coord::Int)::Int =
|
||||
coord == 0 ? 0 : i[which_index(n, dim, coord)] - N ÷ 2 - 1
|
||||
|
||||
"k value of the DOF at the specified cubic image"
|
||||
get_shifted_k(n::Int, N::Int, i::CartesianIndex, dim::Int, coord::Int, image::Vector{Int})::Int =
|
||||
get_k(n, N, i, dim, coord) + N * image[dim]
|
||||
|
||||
"Difference of k values between two particles"
|
||||
get_Δk(n::Int, N::Int, i::CartesianIndex, dim::Int, coord1::Int, coord2::Int, image::Vector{Int})::Int =
|
||||
get_k(n, N, i, dim, coord1) - get_shifted_k(n, N, i, dim, coord2, image)
|
||||
"Δk (distance in terms of lattice paramter) between two particles along the given dimension"
|
||||
function get_Δk(n::Int, N::Int, i::CartesianIndex, dim::Int, p1::Int, p2::Int)::Int
|
||||
if p1 == p2
|
||||
return 0
|
||||
elseif p1 == n
|
||||
return -(i[which_index(n, dim, p2)] - N ÷ 2 - 1)
|
||||
elseif p2 == n
|
||||
return i[which_index(n, dim, p1)] - N ÷ 2 - 1
|
||||
else
|
||||
return i[which_index(n, dim, p1)] - i[which_index(n, dim, p2)]
|
||||
end
|
||||
end
|
||||
|
||||
"Calculate diagonal elements of the V matrix"
|
||||
function calculate_Vs(V_twobody::Function, d::Int, n::Int, N::Int, L::T, n_image::Int)::Array{T} where {T<:Float}
|
||||
L²_over_N² = (L / N)^2
|
||||
coords = n - 1
|
||||
images = collect.(Iterators.product(fill(-n_image:n_image, d)...)) # TODO: Learn how to use tuples instead of vectors
|
||||
Vs = zeros(T, fill(N, d * coords)...)
|
||||
for image in images
|
||||
Vs = zeros(T, fill(N, d * (n - 1))...)
|
||||
Threads.@threads for i in CartesianIndices(Vs)
|
||||
for coord1 in 1:coords
|
||||
for coord2 in 0:coord1-1
|
||||
Δk² = 0
|
||||
for p1 in 1:n
|
||||
for p2 in (p1 + 1):n
|
||||
min_Δk = Array{Int}(undef, d)
|
||||
for dim in 1:d
|
||||
Δk² += get_Δk(n, N, i, dim, coord1, coord2, image)^2
|
||||
Δk = get_Δk(n, N, i, dim, p1, p2)
|
||||
if Δk > N ÷ 2
|
||||
min_Δk[dim] = Δk - N
|
||||
elseif Δk < -N ÷ 2
|
||||
min_Δk[dim] = Δk + N
|
||||
else
|
||||
min_Δk[dim] = Δk
|
||||
end
|
||||
end
|
||||
for image in images
|
||||
Δk² = norm_square(min_Δk .- (N .* image))
|
||||
Vs[i] += V_twobody(Δk² * L²_over_N²)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue