Hello, so, I have been trying accelerating this function called overlap
by using broadcasting and dot notation instead of unpacking matrices elements using for loops. However, I am getting different results when I do that. I would appreciate help if someone has an alternative for this acceleration or has any clue where my math is going wrong:
1. Auxiliary functions
** overlap_2() is the accelerated function; it uses normalization_2(). distance() and doublefactorial() are the same in both cases.
abstract type AbstractBasisSet end
struct GaussianBasisSet <: AbstractBasisSet
R
Ī±::Matrix{Float64}
d::Matrix{Float64}
ā::Int
m::Int
n::Int
end
function doublefactorial(number)
fact = foldl(Base.:*, range(number, 1, step=-2))
return fact
end
function normalization_2(Ī±, ā, m, n)
N = (4 .* Ī±).^(ā + m + n)
N /=
doublefactorial(2 * ā - 1) * doublefactorial(2 * m - 1) * doublefactorial(2 * n - 1)
N .*= ((2 .* Ī±) ./ Ļ).^(3 / 2)
N = sqrt.(N)
return N
end
function distance(Rįµ¢, Rā±¼)
d = (Rįµ¢[1] - Rā±¼[1])^2 + (Rįµ¢[2] - Rā±¼[2])^2 + (Rįµ¢[3] - Rā±¼[3])^2
return d
end
function normalization(Ī±, ā, m, n)
N = (4 * Ī±)^(ā + m + n)
N /=
doublefactorial(2 * ā - 1) * doublefactorial(2 * m - 1) * doublefactorial(2 * n - 1)
N *= ((2 * Ī±) / Ļ)^(3 / 2)
N = sqrt(N)
return N
end
2. The overlap functions
function overlap(basis)
n = length(basis)
S = zeros(n, n)
for i in 1:n, j in 1:n
basisįµ¢ = basis[i]
basisā±¼ = basis[j]
Rįµ¢ = basisįµ¢.R
Rā±¼ = basisā±¼.R
dist = distance(Rįµ¢, Rā±¼)
m = length(basisįµ¢.Ī±)
p = length(basisā±¼.Ī±)
for k in 1:m, l in 1:p
Ī±įµ¢ = basisįµ¢.Ī±[k]
Ī±ā±¼ = basisā±¼.Ī±[l]
dįµ¢ = basisįµ¢.d[k]
dā±¼ = basisā±¼.d[l]
āįµ¢, mįµ¢, nįµ¢ = basisįµ¢.ā, basisįµ¢.m, basisįµ¢.n
āā±¼, mā±¼, nā±¼ = basisā±¼.ā, basisā±¼.m, basisā±¼.n
a = (
exp(-Ī±įµ¢ * Ī±ā±¼ * dist / (Ī±įµ¢ + Ī±ā±¼)) *
normalization(Ī±įµ¢, āįµ¢, mįµ¢, nįµ¢) *
normalization(Ī±ā±¼, āā±¼, mā±¼, nā±¼) *
dįµ¢ *
dā±¼ )
println("$i, $j")
S[i, j] += (
exp(-Ī±įµ¢ * Ī±ā±¼ * dist / (Ī±įµ¢ + Ī±ā±¼)) *
normalization(Ī±įµ¢, āįµ¢, mįµ¢, nįµ¢) *
normalization(Ī±ā±¼, āā±¼, mā±¼, nā±¼) *
dįµ¢ *
dā±¼
)
end
end
return S
end
function overlap_2(basis)
n = length(basis)
S = zeros(n, n)
for i in 1:n, j in 1:n
basisįµ¢ = basis[i]
basisā±¼ = basis[j]
Rįµ¢ = basisįµ¢.R
Rā±¼ = basisā±¼.R
dist = distance(Rįµ¢, Rā±¼)
Ī±įµ¢ = basisįµ¢.Ī±
Ī±ā±¼ = basisā±¼.Ī±
println("$i, $j")
dįµ¢ = basisįµ¢.d
dā±¼ = basisā±¼.d
āįµ¢, mįµ¢, nįµ¢ = basisįµ¢.ā, basisįµ¢.m, basisįµ¢.n
āā±¼, mā±¼, nā±¼ = basisā±¼.ā, basisā±¼.m, basisā±¼.n
a = exp.(-Ī±įµ¢ .* Ī±ā±¼ .* dist ./ (Ī±įµ¢ .+ Ī±ā±¼)) .*
normalization_2(Ī±įµ¢, āįµ¢, mįµ¢, nįµ¢) .*
normalization_2(Ī±ā±¼, āā±¼, mā±¼, nā±¼) .*
dįµ¢ .* dā±¼
println(a)
S[i, j] = sum(exp.(-Ī±įµ¢ .* Ī±ā±¼ .* dist ./ (Ī±įµ¢ .+ Ī±ā±¼)) .* normalization_2(Ī±įµ¢, āįµ¢, mįµ¢, nįµ¢) .* normalization_2(Ī±ā±¼, āā±¼, mā±¼, nā±¼) .* dįµ¢ .* dā±¼)
end
return S
end
Inputs
*** if you want to reproduce the calculations:
GaussianBasisSet[GaussianBasisSet([0.0 0.0 0.85], [3.425250914 0.6239137298 0.168855404], [0.1543289673 0.5353281423 0.4446345422], 0, 0, 0), GaussianBasisSet([0.0 0.0 -0.85], [207.015607 37.70815124 10.20529731], [0.1543289673 0.5353281423 0.4446345422], 0, 0, 0), GaussianBasisSet([0.0 0.0 -0.85], [8.24631512 1.916266291 0.6232292721], [-0.09996722919 0.3995128261 0.7001154689], 0, 0, 0), GaussianBasisSet([0.0 0.0 -0.85], [8.24631512 1.916266291 0.6232292721], [0.155916275 0.6076837186 0.3919573931], 1, 0, 0), GaussianBasisSet([0.0 0.0 -0.85], [8.24631512 1.916266291 0.6232292721], [0.155916275 0.6076837186 0.3919573931], 0, 1, 0), GaussianBasisSet([0.0 0.0 -0.85], [8.24631512 1.916266291 0.6232292721], [0.155916275 0.6076837186 0.3919573931], 0, 0, 1)]