#!/usr/bin/env python
# Copyright 2014-2021 The PySCF Developers. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author: Qiming Sun <osirpt.sun@gmail.com>
#
import numpy
from pyscf import lib
from pyscf.lib import logger
from pyscf import ao2mo
from pyscf.cc import ccsd
#
# JCP 95, 2623 (1991); DOI:10.1063/1.460915
# JCP 95, 2639 (1991); DOI:10.1063/1.460916
#
def _gamma1_intermediates(mycc, t1, t2, l1, l2):
nocc, nvir = t1.shape
doo =-numpy.einsum('ja,ia->ij', t1, l1)
dvv = numpy.einsum('ia,ib->ab', t1, l1)
xtv = numpy.einsum('ie,me->im', t1, l1)
dvo = t1.T - numpy.einsum('im,ma->ai', xtv, t1)
theta = t2 * 2 - t2.transpose(0,1,3,2)
doo -= lib.einsum('jkab,ikab->ij', theta, l2)
dvv += lib.einsum('jica,jicb->ab', theta, l2)
xt1 = lib.einsum('mnef,inef->mi', l2, theta)
xt2 = lib.einsum('mnaf,mnef->ea', l2, theta)
dvo += numpy.einsum('imae,me->ai', theta, l1)
dvo -= numpy.einsum('mi,ma->ai', xt1, t1)
dvo -= numpy.einsum('ie,ae->ai', t1, xt2)
dov = l1
return doo, dov, dvo, dvv
# gamma2 intermediates in Chemist's notation
def _gamma2_intermediates(mycc, t1, t2, l1, l2, compress_vvvv=False):
f = lib.H5TmpFile()
_gamma2_outcore(mycc, t1, t2, l1, l2, f, compress_vvvv)
d2 = (f['dovov'][:], f['dvvvv'][:], f['doooo'][:], f['doovv'][:],
f['dovvo'][:], None, f['dovvv'][:], f['dooov'][:])
return d2
def _gamma2_outcore(mycc, t1, t2, l1, l2, h5fobj, compress_vvvv=False):
log = logger.Logger(mycc.stdout, mycc.verbose)
nocc, nvir = t1.shape
nvir_pair = nvir * (nvir+1) //2
dtype = numpy.result_type(t1, t2, l1, l2).char
if compress_vvvv:
dvvvv = h5fobj.create_dataset('dvvvv', (nvir_pair,nvir_pair), dtype)
else:
dvvvv = h5fobj.create_dataset('dvvvv', (nvir,nvir,nvir,nvir), dtype)
dovvo = h5fobj.create_dataset('dovvo', (nocc,nvir,nvir,nocc), dtype,
chunks=(nocc,1,nvir,nocc))
fswap = lib.H5TmpFile()
time1 = logger.process_clock(), logger.perf_counter()
pvOOv = lib.einsum('ikca,jkcb->aijb', l2, t2)
moo = numpy.einsum('dljd->jl', pvOOv) * 2
mvv = numpy.einsum('blld->db', pvOOv) * 2
gooov = lib.einsum('kc,cija->jkia', t1, pvOOv)
fswap['mvOOv'] = pvOOv
pvOOv = None
pvoOV = -lib.einsum('ikca,jkbc->aijb', l2, t2)
theta = t2 * 2 - t2.transpose(0,1,3,2)
pvoOV += lib.einsum('ikac,jkbc->aijb', l2, theta)
moo += numpy.einsum('dljd->jl', pvoOV)
mvv += numpy.einsum('blld->db', pvoOV)
gooov -= lib.einsum('jc,cika->jkia', t1, pvoOV)
fswap['mvoOV'] = pvoOV
pvoOV = None
mia =(numpy.einsum('kc,ikac->ia', l1, t2) * 2 -
numpy.einsum('kc,ikca->ia', l1, t2))
mab = numpy.einsum('kc,kb->cb', l1, t1)
mij = numpy.einsum('kc,jc->jk', l1, t1) + moo*.5
tau = numpy.einsum('ia,jb->ijab', t1, t1)
tau += t2
goooo = lib.einsum('ijab,klab->ijkl', tau, l2)*.5
h5fobj['doooo'] = (goooo.transpose(0,2,1,3)*2 -
goooo.transpose(0,3,1,2)).conj()
gooov += numpy.einsum('ji,ka->jkia', -.5*moo, t1)
gooov += lib.einsum('la,jkil->jkia', 2*t1, goooo)
gooov -= lib.einsum('ib,jkba->jkia', l1, tau)
gooov = gooov.conj()
gooov -= lib.einsum('jkba,ib->jkia', l2, t1)
h5fobj['dooov'] = gooov.transpose(0,2,1,3)*2 - gooov.transpose(1,2,0,3)
tau = None
time1 = log.timer_debug1('rdm intermediates pass1', *time1)
goovv = numpy.einsum('ia,jb->ijab', mia.conj(), t1.conj())
max_memory = max(0, mycc.max_memory - lib.current_memory()[0])
unit = nocc**2*nvir*6
blksize = min(nocc, nvir, max(ccsd.BLKMIN, int(max_memory*.95e6/8/unit)))
doovv = h5fobj.create_dataset('doovv', (nocc,nocc,nvir,nvir), dtype,
chunks=(nocc,nocc,1,nvir))
log.debug1('rdm intermediates pass 2: block size = %d, nvir = %d in %d blocks',
blksize, nvir, int((nvir+blksize-1)/blksize))
for p0, p1 in lib.prange(0, nvir, blksize):
tau = numpy.einsum('ia,jb->ijab', t1[:,p0:p1], t1)
tau += t2[:,:,p0:p1]
tmpoovv = lib.einsum('ijkl,klab->ijab', goooo, tau)
tmpoovv -= lib.einsum('jk,ikab->ijab', mij, tau)
tmpoovv -= lib.einsum('cb,ijac->ijab', mab, t2[:,:,p0:p1])
tmpoovv -= lib.einsum('bd,ijad->ijab', mvv*.5, tau)
tmpoovv += .5 * tau
tmpoovv = tmpoovv.conj()
tmpoovv += .5 * l2[:,:,p0:p1]
goovv[:,:,p0:p1] += tmpoovv
pvOOv = fswap['mvOOv'][p0:p1]
pvoOV = fswap['mvoOV'][p0:p1]
gOvvO = lib.einsum('kiac,jc,kb->iabj', l2[:,:,p0:p1], t1, t1)
gOvvO += numpy.einsum('aijb->iabj', pvOOv)
govVO = numpy.einsum('ia,jb->iabj', l1[:,p0:p1], t1)
govVO -= lib.einsum('ikac,jc,kb->iabj', l2[:,:,p0:p1], t1, t1)
govVO += numpy.einsum('aijb->iabj', pvoOV)
dovvo[:,p0:p1] = 2*govVO + gOvvO
doovv[:,:,p0:p1] = (-2*gOvvO - govVO).transpose(3,0,1,2).conj()
gOvvO = govVO = None
tau -= t2[:,:,p0:p1] * .5
for q0, q1 in lib.prange(0, nvir, blksize):
goovv[:,:,q0:q1,:] += lib.einsum('dlib,jlda->ijab', pvOOv, tau[:,:,:,q0:q1]).conj()
goovv[:,:,:,q0:q1] -= lib.einsum('dlia,jldb->ijab', pvoOV, tau[:,:,:,q0:q1]).conj()
tmp = pvoOV[:,:,:,q0:q1] + pvOOv[:,:,:,q0:q1]*.5
goovv[:,:,q0:q1,:] += lib.einsum('dlia,jlbd->ijab', tmp, t2[:,:,:,p0:p1]).conj()
pvOOv = pvoOV = tau = None
time1 = log.timer_debug1('rdm intermediates pass2 [%d:%d]'%(p0, p1), *time1)
h5fobj['dovov'] = goovv.transpose(0,2,1,3) * 2 - goovv.transpose(1,2,0,3)
goovv = goooo = None
max_memory = max(0, mycc.max_memory - lib.current_memory()[0])
unit = max(nocc**2*nvir*2+nocc*nvir**2*3,
nvir**3*2+nocc*nvir**2*2+nocc**2*nvir*2)
blksize = min(nvir, max(ccsd.BLKMIN, int(max_memory*.9e6/8/unit)))
log.debug1('rdm intermediates pass 3: block size = %d, nvir = %d in %d blocks',
blksize, nocc, int((nvir+blksize-1)/blksize))
dovvv = h5fobj.create_dataset('dovvv', (nocc,nvir,nvir,nvir), dtype,
chunks=(nocc,min(nocc,nvir),1,nvir))
time1 = logger.process_clock(), logger.perf_counter()
for istep, (p0, p1) in enumerate(lib.prange(0, nvir, blksize)):
l2tmp = l2[:,:,p0:p1]
gvvvv = lib.einsum('ijab,ijcd->abcd', l2tmp, t2)
jabc = lib.einsum('ijab,ic->jabc', l2tmp, t1)
gvvvv += lib.einsum('jabc,jd->abcd', jabc, t1)
l2tmp = jabc = None
if compress_vvvv:
# symmetrize dvvvv because it does not affect the results of ccsd_grad
# dvvvv = gvvvv.transpose(0,2,1,3)-gvvvv.transpose(0,3,1,2)*.5
# dvvvv = (dvvvv+dvvvv.transpose(0,1,3,2)) * .5
# dvvvv = (dvvvv+dvvvv.transpose(1,0,2,3)) * .5
# now dvvvv == dvvvv.transpose(0,1,3,2) == dvvvv.transpose(1,0,3,2)
tmp = numpy.empty((nvir,nvir,nvir))
tmpvvvv = numpy.empty((p1-p0,nvir,nvir_pair))
for i in range(p1-p0):
vvv = gvvvv[i].conj().transpose(1,0,2)
tmp[:] = vvv - vvv.transpose(2,1,0)*.5
lib.pack_tril(tmp+tmp.transpose(0,2,1), out=tmpvvvv[i])
# tril of (dvvvv[p0:p1,p0:p1]+dvvvv[p0:p1,p0:p1].T)
for i in range(p0, p1):
for j in range(p0, i):
tmpvvvv[i-p0,j] += tmpvvvv[j-p0,i]
tmpvvvv[i-p0,i] *= 2
for i in range(p1, nvir):
off = i * (i+1) // 2
dvvvv[off+p0:off+p1] = tmpvvvv[:,i]
for i in range(p0, p1):
off = i * (i+1) // 2
if p0 > 0:
tmpvvvv[i-p0,:p0] += dvvvv[off:off+p0]
dvvvv[off:off+i+1] = tmpvvvv[i-p0,:i+1] * .25
tmp = tmpvvvv = None
else:
for i in range(p0, p1):
vvv = gvvvv[i-p0].conj().transpose(1,0,2)
dvvvv[i] = vvv - vvv.transpose(2,1,0)*.5
gvovv = lib.einsum('adbc,id->aibc', gvvvv, -t1)
gvvvv = None
gvovv += lib.einsum('akic,kb->aibc', fswap['mvoOV'][p0:p1], t1)
gvovv -= lib.einsum('akib,kc->aibc', fswap['mvOOv'][p0:p1], t1)
gvovv += lib.einsum('ja,jibc->aibc', l1[:,p0:p1], t2)
gvovv += lib.einsum('ja,jb,ic->aibc', l1[:,p0:p1], t1, t1)
gvovv += numpy.einsum('ba,ic->aibc', mvv[:,p0:p1]*.5, t1)
gvovv = gvovv.conj()
gvovv += lib.einsum('ja,jibc->aibc', t1[:,p0:p1], l2)
dovvv[:,:,p0:p1] = gvovv.transpose(1,3,0,2)*2 - gvovv.transpose(1,2,0,3)
gvovv = None
time1 = log.timer_debug1('rdm intermediates pass3 [%d:%d]'%(p0, p1), *time1)
fswap = None
dvvov = None
return (h5fobj['dovov'], h5fobj['dvvvv'], h5fobj['doooo'], h5fobj['doovv'],
h5fobj['dovvo'], dvvov , h5fobj['dovvv'], h5fobj['dooov'])
[docs]
def make_rdm1(mycc, t1, t2, l1, l2, ao_repr=False, with_frozen=True, with_mf=True):
r'''
Spin-traced one-particle density matrix in MO basis (the occupied-virtual
blocks from the orbital response contribution are not included).
dm1[p,q] = <q_alpha^\dagger p_alpha> + <q_beta^\dagger p_beta>
The convention of 1-pdm is based on McWeeney's book, Eq (5.4.20).
The contraction between 1-particle Hamiltonian and rdm1 is
E = einsum('pq,qp', h1, rdm1)
'''
d1 = _gamma1_intermediates(mycc, t1, t2, l1, l2)
return _make_rdm1(mycc, d1, with_frozen=with_frozen, ao_repr=ao_repr, with_mf=with_mf)
[docs]
def make_rdm2(mycc, t1, t2, l1, l2, ao_repr=False, with_frozen=True, with_dm1=True):
r'''
Spin-traced two-particle density matrix in MO basis
dm2[p,q,r,s] = \sum_{sigma,tau} <p_sigma^\dagger r_tau^\dagger s_tau q_sigma>
Note the contraction between ERIs (in Chemist's notation) and rdm2 is
E = einsum('pqrs,pqrs', eri, rdm2)
'''
d1 = _gamma1_intermediates(mycc, t1, t2, l1, l2)
f = lib.H5TmpFile()
d2 = _gamma2_outcore(mycc, t1, t2, l1, l2, f, False)
return _make_rdm2(mycc, d1, d2, with_dm1=with_dm1, with_frozen=with_frozen,
ao_repr=ao_repr)
def _make_rdm1(mycc, d1, with_frozen=True, ao_repr=False, with_mf=True):
r'''dm1[p,q] = <q_alpha^\dagger p_alpha> + <q_beta^\dagger p_beta>
The convention of 1-pdm is based on McWeeney's book, Eq (5.4.20).
The contraction between 1-particle Hamiltonian and rdm1 is
E = einsum('pq,qp', h1, rdm1)
'''
doo, dov, dvo, dvv = d1
nocc, nvir = dov.shape
nmo = nocc + nvir
dm1 = numpy.empty((nmo,nmo), dtype=doo.dtype)
dm1[:nocc,:nocc] = doo + doo.conj().T
dm1[:nocc,nocc:] = dov + dvo.conj().T
dm1[nocc:,:nocc] = dm1[:nocc,nocc:].conj().T
dm1[nocc:,nocc:] = dvv + dvv.conj().T
if with_mf:
dm1[numpy.diag_indices(nocc)] += 2
if with_frozen and mycc.frozen is not None:
nmo = mycc.mo_occ.size
nocc = numpy.count_nonzero(mycc.mo_occ > 0)
rdm1 = numpy.zeros((nmo,nmo), dtype=dm1.dtype)
if with_mf:
rdm1[numpy.diag_indices(nocc)] = 2
moidx = numpy.where(mycc.get_frozen_mask())[0]
rdm1[moidx[:,None],moidx] = dm1
dm1 = rdm1
if ao_repr:
mo = mycc.mo_coeff
dm1 = lib.einsum('pi,ij,qj->pq', mo, dm1, mo.conj())
return dm1
# Note vvvv part of 2pdm have been symmetrized. It does not correspond to
# vvvv part of CI 2pdm
def _make_rdm2(mycc, d1, d2, with_dm1=True, with_frozen=True, ao_repr=False):
r'''
dm2[p,q,r,s] = \sum_{sigma,tau} <p_sigma^\dagger r_tau^\dagger s_tau q_sigma>
Note the contraction between ERIs (in Chemist's notation) and rdm2 is
E = einsum('pqrs,pqrs', eri, rdm2)
'''
dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = d2
nocc, nvir = dovov.shape[:2]
nmo = nocc + nvir
dm2 = numpy.empty((nmo,nmo,nmo,nmo), dtype=doovv.dtype)
dovov = numpy.asarray(dovov)
dm2[:nocc,nocc:,:nocc,nocc:] = dovov
dm2[:nocc,nocc:,:nocc,nocc:]+= dovov.transpose(2,3,0,1)
dm2[nocc:,:nocc,nocc:,:nocc] = dm2[:nocc,nocc:,:nocc,nocc:].transpose(1,0,3,2).conj()
dovov = None
doovv = numpy.asarray(doovv)
dm2[:nocc,:nocc,nocc:,nocc:] = doovv
dm2[:nocc,:nocc,nocc:,nocc:]+= doovv.transpose(1,0,3,2).conj()
dm2[nocc:,nocc:,:nocc,:nocc] = dm2[:nocc,:nocc,nocc:,nocc:].transpose(2,3,0,1)
doovv = None
dovvo = numpy.asarray(dovvo)
dm2[:nocc,nocc:,nocc:,:nocc] = dovvo
dm2[:nocc,nocc:,nocc:,:nocc]+= dovvo.transpose(3,2,1,0).conj()
dm2[nocc:,:nocc,:nocc,nocc:] = dm2[:nocc,nocc:,nocc:,:nocc].transpose(1,0,3,2).conj()
dovvo = None
if dvvvv.ndim == 2:
# To handle the case of compressed vvvv, which is used in nuclear gradients
dvvvv = ao2mo.restore(1, dvvvv, nvir)
dm2[nocc:,nocc:,nocc:,nocc:] = dvvvv
dm2[nocc:,nocc:,nocc:,nocc:]*= 4
else:
dvvvv = numpy.asarray(dvvvv)
dm2[nocc:,nocc:,nocc:,nocc:] = dvvvv
dm2[nocc:,nocc:,nocc:,nocc:]+= dvvvv.transpose(1,0,3,2).conj()
dm2[nocc:,nocc:,nocc:,nocc:]*= 2
dvvvv = None
doooo = numpy.asarray(doooo)
dm2[:nocc,:nocc,:nocc,:nocc] = doooo
dm2[:nocc,:nocc,:nocc,:nocc]+= doooo.transpose(1,0,3,2).conj()
dm2[:nocc,:nocc,:nocc,:nocc]*= 2
doooo = None
dovvv = numpy.asarray(dovvv)
dm2[:nocc,nocc:,nocc:,nocc:] = dovvv
dm2[nocc:,nocc:,:nocc,nocc:] = dovvv.transpose(2,3,0,1)
dm2[nocc:,nocc:,nocc:,:nocc] = dovvv.transpose(3,2,1,0).conj()
dm2[nocc:,:nocc,nocc:,nocc:] = dovvv.transpose(1,0,3,2).conj()
dovvv = None
dooov = numpy.asarray(dooov)
dm2[:nocc,:nocc,:nocc,nocc:] = dooov
dm2[:nocc,nocc:,:nocc,:nocc] = dooov.transpose(2,3,0,1)
dm2[:nocc,:nocc,nocc:,:nocc] = dooov.transpose(1,0,3,2).conj()
dm2[nocc:,:nocc,:nocc,:nocc] = dooov.transpose(3,2,1,0).conj()
if with_frozen and mycc.frozen is not None:
nmo, nmo0 = mycc.mo_occ.size, nmo
nocc = numpy.count_nonzero(mycc.mo_occ > 0)
rdm2 = numpy.zeros((nmo,nmo,nmo,nmo), dtype=dm2.dtype)
moidx = numpy.where(mycc.get_frozen_mask())[0]
idx = (moidx.reshape(-1,1) * nmo + moidx).ravel()
lib.takebak_2d(rdm2.reshape(nmo**2,nmo**2),
dm2.reshape(nmo0**2,nmo0**2), idx, idx)
dm2 = rdm2
if with_dm1:
dm1 = _make_rdm1(mycc, d1, with_frozen)
dm1[numpy.diag_indices(nocc)] -= 2
for i in range(nocc):
dm2[i,i,:,:] += dm1 * 2
dm2[:,:,i,i] += dm1 * 2
dm2[:,i,i,:] -= dm1
dm2[i,:,:,i] -= dm1.T
for i in range(nocc):
for j in range(nocc):
dm2[i,i,j,j] += 4
dm2[i,j,j,i] -= 2
# dm2 was computed as dm2[p,q,r,s] = < p^\dagger r^\dagger s q > in the
# above. Transposing it so that it be contracted with ERIs (in Chemist's
# notation):
# E = einsum('pqrs,pqrs', eri, rdm2)
dm2 = dm2.transpose(1,0,3,2)
if ao_repr:
dm2 = _rdm2_mo2ao(dm2.transpose(1,0,3,2), mycc.mo_coeff)
return dm2
def _rdm2_mo2ao(dm2, mo):
mo_C = mo.conj()
return lib.einsum('ijkl,pi,qj,rk,sl->pqrs', dm2, mo, mo_C, mo, mo_C)
if __name__ == '__main__':
from functools import reduce
from pyscf import gto
from pyscf import scf
mol = gto.M()
mf = scf.RHF(mol)
mcc = ccsd.CCSD(mf)
numpy.random.seed(2)
nocc = 5
nmo = 12
nvir = nmo - nocc
eri0 = numpy.random.random((nmo,nmo,nmo,nmo))
eri0 = ao2mo.restore(1, ao2mo.restore(8, eri0, nmo), nmo)
fock0 = numpy.random.random((nmo,nmo))
fock0 = fock0 + fock0.T + numpy.diag(range(nmo))*2
t1 = numpy.random.random((nocc,nvir))
t2 = numpy.random.random((nocc,nocc,nvir,nvir))
t2 = t2 + t2.transpose(1,0,3,2)
l1 = numpy.random.random((nocc,nvir))
l2 = numpy.random.random((nocc,nocc,nvir,nvir))
l2 = l2 + l2.transpose(1,0,3,2)
h1 = fock0 - (numpy.einsum('kkpq->pq', eri0[:nocc,:nocc])*2 -
numpy.einsum('pkkq->pq', eri0[:,:nocc,:nocc]))
eris = lambda:None
eris.oooo = eri0[:nocc,:nocc,:nocc,:nocc].copy()
eris.ooov = eri0[:nocc,:nocc,:nocc,nocc:].copy()
eris.ovoo = eri0[:nocc,nocc:,:nocc,:nocc].copy()
eris.oovv = eri0[:nocc,:nocc,nocc:,nocc:].copy()
eris.ovov = eri0[:nocc,nocc:,:nocc,nocc:].copy()
eris.ovvo = eri0[:nocc,nocc:,nocc:,:nocc].copy()
eris.ovvv = eri0[:nocc,nocc:,nocc:,nocc:].copy()
eris.vvvv = eri0[nocc:,nocc:,nocc:,nocc:].copy()
eris.fock = fock0
doo, dov, dvo, dvv = _gamma1_intermediates(mcc, t1, t2, l1, l2)
print((numpy.einsum('ij,ij', doo, fock0[:nocc,:nocc]))*2+20166.329861034799)
print((numpy.einsum('ab,ab', dvv, fock0[nocc:,nocc:]))*2-58078.964019246778)
print((numpy.einsum('ai,ia', dvo, fock0[:nocc,nocc:]))*2+74994.356886784764)
print((numpy.einsum('ia,ai', dov, fock0[nocc:,:nocc]))*2-34.010188025702391)
fdm2 = lib.H5TmpFile()
dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = \
_gamma2_outcore(mcc, t1, t2, l1, l2, fdm2, True)
print('dovov', lib.finger(numpy.array(dovov)) - -14384.907042073517)
print('dvvvv', lib.finger(numpy.array(dvvvv)) - -25.374007033024839)
print('doooo', lib.finger(numpy.array(doooo)) - 60.114594698129963)
print('doovv', lib.finger(numpy.array(doovv)) - -79.176348067958401)
print('dovvo', lib.finger(numpy.array(dovvo)) - 9.864134457251815)
print('dovvv', lib.finger(numpy.array(dovvv)) - -421.90333700061342)
print('dooov', lib.finger(numpy.array(dooov)) - -592.66863759586136)
fdm2 = None
dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = \
_gamma2_intermediates(mcc, t1, t2, l1, l2)
print('dovov', lib.finger(numpy.array(dovov)) - -14384.907042073517)
print('dvvvv', lib.finger(numpy.array(dvvvv)) - 45.872344902116758)
print('doooo', lib.finger(numpy.array(doooo)) - 60.114594698129963)
print('doovv', lib.finger(numpy.array(doovv)) - -79.176348067958401)
print('dovvo', lib.finger(numpy.array(dovvo)) - 9.864134457251815)
print('dovvv', lib.finger(numpy.array(dovvv)) - -421.90333700061342)
print('dooov', lib.finger(numpy.array(dooov)) - -592.66863759586136)
print('doooo',numpy.einsum('kilj,kilj', doooo, eris.oooo)*2-15939.9007625418)
print('dvvvv',numpy.einsum('acbd,acbd', dvvvv, eris.vvvv)*2-37581.823919588 )
print('dooov',numpy.einsum('jkia,jkia', dooov, eris.ooov)*2-128470.009687716)
print('dovvv',numpy.einsum('icba,icba', dovvv, eris.ovvv)*2+166794.225195056)
print('dovov',numpy.einsum('iajb,iajb', dovov, eris.ovov)*2+719279.812916893)
print('dovvo',numpy.einsum('jbai,jbia', dovvo, eris.ovov)*2
+numpy.einsum('jiab,jiba', doovv, eris.oovv)*2+53634.0012286654)
dm1 = make_rdm1(mcc, t1, t2, l1, l2)
dm2 = make_rdm2(mcc, t1, t2, l1, l2)
e2 = (numpy.einsum('ijkl,ijkl', doooo, eris.oooo)*2 +
numpy.einsum('acbd,acbd', dvvvv, eris.vvvv)*2 +
numpy.einsum('jkia,jkia', dooov, eris.ooov)*2 +
numpy.einsum('icba,icba', dovvv, eris.ovvv)*2 +
numpy.einsum('iajb,iajb', dovov, eris.ovov)*2 +
numpy.einsum('jbai,jbia', dovvo, eris.ovov)*2 +
numpy.einsum('ijab,ijab', doovv, eris.oovv)*2 +
numpy.einsum('ij,ij', doo, fock0[:nocc,:nocc])*2 +
numpy.einsum('ia,ia', dov, fock0[:nocc,nocc:])*2 +
numpy.einsum('ai,ai', dvo, fock0[nocc:,:nocc])*2 +
numpy.einsum('ab,ab', dvv, fock0[nocc:,nocc:])*2 +
fock0[:nocc].trace()*2 -
numpy.einsum('kkpq->pq', eri0[:nocc,:nocc,:nocc,:nocc]).trace()*2 +
numpy.einsum('pkkq->pq', eri0[:nocc,:nocc,:nocc,:nocc]).trace())
print(e2+794721.197459942)
print(numpy.einsum('pqrs,pqrs', dm2, eri0)*.5 +
numpy.einsum('pq,qp', dm1, h1) - e2)
print(numpy.allclose(dm2, dm2.transpose(1,0,3,2)))
print(numpy.allclose(dm2, dm2.transpose(2,3,0,1)))
d1 = numpy.einsum('kkpq->qp', dm2) / 9
print(numpy.allclose(d1, dm1))
mol = gto.Mole()
mol.atom = [
[8 , (0. , 0. , 0.)],
[1 , (0. , -0.757 , 0.587)],
[1 , (0. , 0.757 , 0.587)]]
mol.basis = '631g'
mol.build()
mf = scf.RHF(mol).run()
mycc = ccsd.CCSD(mf)
mycc.frozen = 2
ecc, t1, t2 = mycc.kernel()
l1, l2 = mycc.solve_lambda()
dm1 = make_rdm1(mycc, t1, t2, l1, l2)
dm2 = make_rdm2(mycc, t1, t2, l1, l2)
nmo = mf.mo_coeff.shape[1]
eri = ao2mo.kernel(mf._eri, mf.mo_coeff, compact=False).reshape([nmo]*4)
hcore = mf.get_hcore()
h1 = reduce(numpy.dot, (mf.mo_coeff.T, hcore, mf.mo_coeff))
e1 = numpy.einsum('ij,ji', h1, dm1)
e1+= numpy.einsum('ijkl,ijkl', eri, dm2) * .5
e1+= mol.energy_nuc()
print(e1 - mycc.e_tot)