Skip to content

Commit cd4cd0d

Browse files
committed
Add example for ring CCD (fix pyscf#1149)
1 parent ccedc56 commit cd4cd0d

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed

examples/cc/055-drccd.py

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
'''
2+
Restricted direct ring-CCD.
3+
4+
See also the relevant dicussions in https://github.com/pyscf/pyscf/issues/1149
5+
6+
Ref: Scuseria et al., J. Chem. Phys. 129, 231101 (2008)
7+
Ref: Masios et al., Phys. Rev. Lett. 131, 186401 (2023)
8+
9+
Original Source:
10+
Modified from pyscf/cc/rccsd_slow.py
11+
12+
Contact:
13+
14+
'''
15+
16+
from functools import reduce
17+
import numpy as np
18+
from pyscf.cc import ccsd
19+
from pyscf import lib
20+
from pyscf.ao2mo import _ao2mo
21+
22+
einsum = lib.einsum
23+
24+
def update_amps(cc, t1, t2, eris):
25+
# Ref: Masios et al., Phys. Rev. Lett. 131, 186401 (2023) Eq.(3)
26+
nocc, nvir = t1.shape
27+
t1[:] = 0.0
28+
29+
eris_ovvo = np.asarray(eris.ovvo)
30+
eris_ovov = np.asarray(eris.ovov)
31+
32+
t2new = 2*einsum('iack, kjcb->iajb', eris_ovvo, t2)
33+
t2new += 2*einsum('ikac, jbck->iajb', t2, eris_ovvo)
34+
tmp = einsum('ikac, kcld->iald', t2, eris_ovov)
35+
t2new += 4*einsum('iald, ljdb->iajb', tmp, t2)
36+
t2new = t2new.transpose(0,2,1,3)
37+
38+
t2new += np.asarray(eris.ovov).conj().transpose(0,2,1,3).copy()
39+
40+
mo_e = eris.fock.diagonal().real
41+
eia = mo_e[:nocc,None] - mo_e[None,nocc:]
42+
eijab = lib.direct_sum('ia,jb->ijab',eia,eia)
43+
t2new /= eijab
44+
45+
return t1, t2new
46+
47+
def energy(cc, t1, t2, eris):
48+
# Ref: Scuseria et al., J. Chem. Phys. 129, 231101 (2008) Eq.(11)
49+
nocc, nvir = t1.shape
50+
fock = eris.fock
51+
eris_ovov = np.asarray(eris.ovov)
52+
e = 2*einsum('ijab,iajb', t2, eris_ovov)
53+
return e.real
54+
55+
def init_amps(cc, eris):
56+
nocc = cc.nocc
57+
mo_e = eris.fock.diagonal().real
58+
eia = mo_e[:nocc,None] - mo_e[None,nocc:]
59+
eijab = lib.direct_sum('ia,jb->ijab', eia, eia)
60+
t1 = np.zeros_like(eris.fock[:nocc,nocc:])
61+
62+
eris_ovov = np.asarray(eris.ovov)
63+
t2 = eris_ovov.transpose(0,2,1,3).conj() / eijab
64+
cc.emp2 = 2*einsum('ijab,iajb', t2, eris_ovov)
65+
lib.logger.info(cc, 'Init t2, dMP2 energy = %.15g', cc.emp2)
66+
return cc.emp2, t1, t2
67+
68+
def ao2mo(cc, mo_coeff=None):
69+
return _ChemistsERIs(cc, mo_coeff)
70+
71+
class _ChemistsERIs:
72+
def __init__(self, cc, mo_coeff=None, method='incore'):
73+
if mo_coeff is None:
74+
self.mo_coeff = mo_coeff = ccsd._mo_without_core(cc, cc.mo_coeff)
75+
else:
76+
self.mo_coeff = mo_coeff = ccsd._mo_without_core(cc, mo_coeff)
77+
dm = cc._scf.make_rdm1(cc.mo_coeff, cc.mo_occ)
78+
fockao = cc._scf.get_hcore() + cc._scf.get_veff(cc.mol, dm)
79+
self.fock = reduce(np.dot, (mo_coeff.T, fockao, mo_coeff))
80+
81+
nocc = cc.nocc
82+
nmo = cc.nmo
83+
nvir = nmo - nocc
84+
# eri1 = ao2mo.incore.full(cc._scf._eri, mo_coeff)
85+
# eri1 = ao2mo.restore(1, eri1, nmo)
86+
mo = cc._scf.mo_coeff
87+
Lpq = cc._scf._cderi
88+
ijslice = (0, nocc, nocc, nmo)
89+
Lov = _ao2mo.nr_e2(Lpq, mo, ijslice, aosym='s2', mosym='s1')
90+
eris_ovov = Lov.T @ Lov
91+
self.ovov = eris_ovov.reshape(nocc, nvir, nocc, nvir)
92+
self.ovvo = self.ovov.transpose(0,1,3,2).copy()
93+
self.Lov = Lov
94+
95+
96+
class drCCD(ccsd.CCSD):
97+
init_amps = init_amps
98+
update_amps = update_amps
99+
energy = energy
100+
ao2mo = ao2mo
101+
102+
103+
if __name__ == '__main__':
104+
from pyscf import gto, dft, scf
105+
mol = gto.Mole()
106+
mol.verbose = 4
107+
mol.atom = 'H 0 0 0; F 0 0 1.1'
108+
mol.basis = 'ccpvdz'
109+
110+
mol.build()
111+
mf = scf.RHF(mol).density_fit()
112+
mf.kernel()
113+
114+
mycc = drCCD(mf)
115+
e_drccd, _, t2 = mycc.kernel()
116+
from pyscf.gw import rpa
117+
myrpa = rpa.RPA(mf)
118+
e_rpa = myrpa.kernel()
119+
print(f"Difference between drccd and drpa: {e_drccd-e_rpa} Ha." )

0 commit comments

Comments
 (0)