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)]