import numpy as np
[docs]def D3_element(fs,a,b,c,i,j,k):
tmp = fs[i,i] + fs[j,j] + fs[k,k]\
- fs[a,a] - fs[b,b] - fs[c,c]
return tmp
[docs]def t3d_element(fs,ts,spinints,a,b,c,i,j,k):
tmp = 0
tmp += fun_d(ts,spinints,a,b,c,i,j,k)
tmp -= fun_d(ts,spinints,b,a,c,i,j,k)
tmp -= fun_d(ts,spinints,c,b,a,i,j,k)
tmp -= fun_d(ts,spinints,a,b,c,j,i,k)
tmp += fun_d(ts,spinints,b,a,c,j,i,k)
tmp += fun_d(ts,spinints,c,b,a,j,i,k)
tmp -= fun_d(ts,spinints,a,b,c,k,j,i)
tmp += fun_d(ts,spinints,b,a,c,k,j,i)
tmp += fun_d(ts,spinints,c,b,a,k,j,i)
tmp /= D3_element(fs,a,b,c,i,j,k)
return tmp
[docs]def t3c_element(Nelec,dim,fs,td,spinints,a,b,c,i,j,k):
tmp = 0
tmp += fun_c(Nelec,dim,td,spinints,a,b,c,i,j,k)
tmp -= fun_c(Nelec,dim,td,spinints,b,a,c,i,j,k)
tmp -= fun_c(Nelec,dim,td,spinints,c,b,a,i,j,k)
tmp -= fun_c(Nelec,dim,td,spinints,a,b,c,j,i,k)
tmp += fun_c(Nelec,dim,td,spinints,b,a,c,j,i,k)
tmp += fun_c(Nelec,dim,td,spinints,c,b,a,j,i,k)
tmp -= fun_c(Nelec,dim,td,spinints,a,b,c,k,j,i)
tmp += fun_c(Nelec,dim,td,spinints,b,a,c,k,j,i)
tmp += fun_c(Nelec,dim,td,spinints,c,b,a,k,j,i)
tmp /= D3_element(fs,a,b,c,i,j,k)
return tmp
[docs]def fun_d (ts,spinints,a,b,c,i,j,k):
tmp = ts[a,i]*spinints[j,k,b,c]
return tmp
[docs]def fun_c (Nelec,dim,td,spinints,a,b,c,i,j,k):
tmp = 0
for e in range(Nelec,dim):
tmp += td[a,e,j,k]*spinints[e,i,b,c]
for m in range(0,Nelec):
tmp -= td[b,c,i,m]*spinints[m,a,j,k]
return tmp
################################
[docs]def spinfock(eorbitals):
"""
"""
if type(eorbitals) is np.ndarray:
dim = 2*len(eorbitals)
fs = np.zeros(dim)
for i in range(0,dim):
fs[i] = eorbitals[i//2]
fs = np.diag(fs) # put MO energies in diagonal array
elif type(eorbitals) is dict:
dim = 2*len(eorbitals['alpha'])
fs = np.zeros(dim)
for i in range(0,dim):
if i%2==0:
fs[i] = eorbitals['alpha'][i//2]
elif i%2==0:
fs[i] = eorbitals['beta'][i//2]
fs = np.diag(fs) # put MO energies in diagonal array
return fs
[docs]def initialize(fs,spinints,Nelec,dim):
"""
Init empty T1 (ts) and T2 (td) arrays
and make denominator arrays Dai, Dabij
"""
# Initial guess for T1 and T2
ts = np.zeros((dim,dim))
td = np.zeros((dim,dim,dim,dim))
for a in range(Nelec,dim):
for b in range(Nelec,dim):
for i in range(0,Nelec):
for j in range(0,Nelec):
td[a,b,i,j] += spinints[i,j,a,b]/(fs[i,i] + fs[j,j] - fs[a,a] - fs[b,b])
# Equation (12) of Stanton
Dai = np.zeros((dim,dim))
for a in range(Nelec,dim):
for i in range(0,Nelec):
Dai[a,i] = fs[i,i] - fs[a,a]
# Stanton eq (13)
Dabij = np.zeros((dim,dim,dim,dim))
for a in range(Nelec,dim):
for b in range(Nelec,dim):
for i in range(0,Nelec):
for j in range(0,Nelec):
Dabij[a,b,i,j] = fs[i,i] + fs[j,j] - fs[a,a] - fs[b,b]
return ts,td,Dai,Dabij
# Stanton eq (9)
[docs]def taus(ts,td,a,b,i,j):
taus = td[a,b,i,j] + 0.5*(ts[a,i]*ts[b,j] - ts[b,i]*ts[a,j])
return taus
# Stanton eq (10)
[docs]def tau(ts,td,a,b,i,j):
tau = td[a,b,i,j] + ts[a,i]*ts[b,j] - ts[b,i]*ts[a,j]
return tau
# We need to update our intermediates at the beginning, and
# at the end of each iteration. Each iteration provides a new
# guess at the amplitudes T1 (ts) and T2 (td), that *hopefully*
# converges to a stable, ground-state, solution.
# makeT1 and makeT2, as they imply, construct the actual amplitudes necessary for computing
# the CCSD energy (or computing an EOM-CCSD Hamiltonian, etc)
# Stanton eq (1)
[docs]def makeT1(x,Nelec,dim,fs,spinints,ts,td,Dai,Fae,Fmi,Fme):
if x == True:
tsnew = np.zeros((dim,dim))
for a in range(Nelec,dim):
for i in range(0,Nelec):
tsnew[a,i] = fs[i,a]
for e in range(Nelec,dim):
tsnew[a,i] += ts[e,i]*Fae[a,e]
for m in range(0,Nelec):
tsnew[a,i] += -ts[a,m]*Fmi[m,i]
for e in range(Nelec,dim):
tsnew[a,i] += td[a,e,i,m]*Fme[m,e]
for f in range(Nelec,dim):
tsnew[a,i] += -0.5*td[e,f,i,m]*spinints[m,a,e,f]
for n in range(0,Nelec):
tsnew[a,i] += -0.5*td[a,e,m,n]*spinints[n,m,e,i]
for n in range(0,Nelec):
for f in range(Nelec,dim):
tsnew[a,i] += -ts[f,n]*spinints[n,a,i,f]
tsnew[a,i] = tsnew[a,i]/Dai[a,i]
return tsnew
# Stanton eq (2)
[docs]def makeT2(x,Nelec,dim,fs,spinints,ts,td,Dabij,Fae,Fmi,Fme,Wmnij,Wabef,Wmbej):
if x == True:
tdnew = np.zeros((dim,dim,dim,dim))
for a in range(Nelec,dim):
for b in range(Nelec,dim):
for i in range(0,Nelec):
for j in range(0,Nelec):
tdnew[a,b,i,j] += spinints[i,j,a,b]
for e in range(Nelec,dim):
tdnew[a,b,i,j] += td[a,e,i,j]*Fae[b,e] - td[b,e,i,j]*Fae[a,e]
for m in range(0,Nelec):
tdnew[a,b,i,j] += -0.5*td[a,e,i,j]*ts[b,m]*Fme[m,e] + 0.5*td[a,e,i,j]*ts[a,m]*Fme[m,e]
continue
for m in range(0,Nelec):
tdnew[a,b,i,j] += -td[a,b,i,m]*Fmi[m,j] + td[a,b,j,m]*Fmi[m,i]
for e in range(Nelec,dim):
tdnew[a,b,i,j] += -0.5*td[a,b,i,m]*ts[e,j]*Fme[m,e] + 0.5*td[a,b,i,m]*ts[e,i]*Fme[m,e]
continue
for e in range(Nelec,dim):
tdnew[a,b,i,j] += ts[e,i]*spinints[a,b,e,j] - ts[e,j]*spinints[a,b,e,i]
for f in range(Nelec,dim):
tdnew[a,b,i,j] += 0.5*tau(ts,td,e,f,i,j)*Wabef[a,b,e,f]
continue
for m in range(0,Nelec):
tdnew[a,b,i,j] += -ts[a,m]*spinints[m,b,i,j] + ts[b,m]*spinints[m,a,i,j]
for e in range(Nelec,dim):
tdnew[a,b,i,j] += td[a,e,i,m]*Wmbej[m,b,e,j] - ts[e,i]*ts[a,m]*spinints[m,b,e,j]
tdnew[a,b,i,j] += -td[a,e,j,m]*Wmbej[m,b,e,i] + ts[e,j]*ts[a,m]*spinints[m,b,e,i]
tdnew[a,b,i,j] += -td[b,e,i,m]*Wmbej[m,a,e,j] - ts[e,i]*ts[b,m]*spinints[m,a,e,j]
tdnew[a,b,i,j] += td[b,e,j,m]*Wmbej[m,a,e,i] - ts[e,j]*ts[b,m]*spinints[m,a,e,i]
continue
for n in range(0,Nelec):
tdnew[a,b,i,j] += 0.5*tau(ts,td,a,b,m,n)*Wmnij[m,n,i,j]
continue
tdnew[a,b,i,j] = tdnew[a,b,i,j]/Dabij[a,b,i,j]
return tdnew
# Expression from Crawford, Schaefer (2000)
# DOI: 10.1002/9780470125915.ch2
# Equation (134) and (173)
# computes CCSD energy given T1 and T2
[docs]def ccsdenergy(Nelec,dim,fs,spinints,ts,td):
ECCSD = 0.0
for i in range(0,Nelec):
for a in range(Nelec,dim):
ECCSD += fs[i,a]*ts[a,i]
for j in range(0,Nelec):
for b in range(Nelec,dim):
ECCSD += 0.25*spinints[i,j,a,b]*td[a,b,i,j] + 0.5*spinints[i,j,a,b]*(ts[a,i])*(ts[b,j])
return ECCSD
[docs]def E_triples_correction(Nelec,dim,fs,ts,td,spinints):
Et = 0.0
for i in range(0,Nelec):
for j in range(0,Nelec):
for k in range(0,Nelec):
for a in range(Nelec,dim):
for b in range(Nelec,dim):
for c in range(Nelec,dim):
Et += t3c_element(Nelec,dim,fs,td,spinints,a,b,c,i,j,k)*D3_element(fs,a,b,c,i,j,k)\
*(t3c_element(Nelec,dim,fs,td,spinints,a,b,c,i,j,k)+t3d_element(fs,ts,spinints,a,b,c,i,j,k))
Et *= 1/36
return Et