-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhf.jl
130 lines (106 loc) · 3.11 KB
/
hf.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#Hartree-Fock code
module hf
using LinearAlgebra
#Should this even exist...?
function getCachedNuclearRepulsion(;
basepath = @__DIR__,
folder::String = "cache",
filename::String = "nucrepl",
fileformat::String = ".txt")
path = joinpath(basepath, folder, filename*fileformat)
open(path) do f
return Meta.parse(readline(f))
end
end
function scourFP!(a, threshold=1.0e-15)
#Remove FP-error values
#Always work in units ~ 1!
for (i, val) in enumerate(a)
if abs(val) < threshold
a[i] = 0.0
end
end
end
function getOccupiedOrbitals()
#TODO improve this
return 1:5
end
function constructDensityMatrix(MO::Array{Float64})
density = zeros(eltype(MO), size(MO))
for i = 1:size(density)[1]
for j = 1:size(density)[2]
for m in getOccupiedOrbitals()
density[i,j] += MO[i,m] .* MO[j,m]
end
end
end
return density
end
function getNextFock(H::Array{Float64}, D::Array{Float64}, TEI::Array{Float64},
triangleCache::Array{Int64})
Fnew = copy(H)
n = size(H)[1]
teiInd(a,b,c,d) = getHypertriangleIndex(a,b,c,d,triangleCache)
for i = 1:n
for j = 1:n
for k = 1:n
for l = 1:n
Fnew[i,j] += D[k,l] * (2 * TEI[teiInd(i,j,k,l)] - TEI[teiInd(i,k,j,l)])
end
end
end
end
return Fnew
end
function checkConvergence(E1::Float64, E2::Float64,
D1::Array{Float64}, D2::Array{Float64},
δe::Float64, δd::Float64)
if E2 - E1 > δe
return false
elseif √(sum((D2-D1)^2)) > δd
return false
else
return true
end
end
function runExample()
nuclearRepulsion = getCachedNuclearRepulsion(fileformat=".dat")
overlapIntegrals = getCachedOneElectronIntegrals("overlap", fileformat=".dat")
TIntegrals = getCachedOneElectronIntegrals("kinetic", fileformat=".dat")
nucVIntegrals = getCachedOneElectronIntegrals("nucpoten", fileformat=".dat")
tei, tricache = getCachedTwoElectronIntegrals("eepoten", fileformat=".dat")
Hcore = TIntegrals + nucVIntegrals
orth = overlapIntegrals^(-1//2)
torth = transpose(orth)
unorth = inv(orth)
tunorth = transpose(unorth)
Fprime0 = torth * Hcore * orth
F = tunorth*Fprime0*unorth
C0 = orth*eigvecs(Symmetric(Fprime0))
#scourFP!(C0, 1e-14)
D0 = constructDensityMatrix(C0)
Einit = sum(D0 .* (Hcore + F))
converged = false
itermax = 50
it = 0
H = Hcore
Dnew = D0
Enew = Einit
electronicEnergies = Vector{Float64}([])
while !converged && it < itermax
it += 1
Eprev = Enew
Dprev = Dnew
push!(electronicEnergies, Enew)
F = getNextFock(H, Dnew, tei, tricache)
Fprime = Symmetric(torth*F*orth)
C = orth*eigvecs(Fprime)
#scourFP!(C, 1e-14)
Dnew = constructDensityMatrix(C)
Enew = sum(Dnew .* (Hcore + F))
converged = checkConvergence(Eprev, Enew, Dprev, Dnew, 0.000000000001, 0.00000000001)
end
return electronicEnergies .+ nuclearRepulsion
end
export rhf
end