# Copyright 2014-2022 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: Samragni Banerjee <samragnibanerjee4@gmail.com>
# Alexander Sokolov <alexander.y.sokolov@gmail.com>
#
import time
import numpy as np
import pyscf.ao2mo as ao2mo
import pyscf.adc
import pyscf.adc.radc
from pyscf.adc import radc_ao2mo
import itertools
from itertools import product
from pyscf import lib
from pyscf.pbc import scf
from pyscf.pbc import df
from pyscf.pbc import mp
from pyscf.lib import logger
from pyscf.pbc.adc import kadc_rhf
from pyscf.pbc.adc import kadc_ao2mo
from pyscf.pbc.adc import dfadc
from pyscf import __config__
from pyscf.pbc.mp.kmp2 import (get_nocc, get_nmo, padding_k_idx,_padding_k_idx,
padded_mo_coeff, get_frozen_mask, _add_padding)
from pyscf.pbc.cc.kccsd_rhf import _get_epq
from pyscf.pbc.cc.kccsd_t_rhf import _get_epqr
from pyscf.pbc.lib import kpts_helper
from pyscf.lib.parameters import LOOSE_ZERO_TOL, LARGE_DENOM # noqa
from pyscf.pbc import tools
import h5py
import tempfile
[docs]
def vector_size(adc):
nkpts = adc.nkpts
nocc = adc.nocc
nvir = adc.nmo - adc.nocc
n_singles = nocc
n_doubles = nkpts * nkpts * nvir * nocc * nocc
size = n_singles + n_doubles
return size
[docs]
def get_imds(adc, eris=None):
cput0 = (time.process_time(), time.time())
log = logger.Logger(adc.stdout, adc.verbose)
if adc.method not in ("adc(2)", "adc(2)-x", "adc(3)"):
raise NotImplementedError(adc.method)
method = adc.method
nkpts = adc.nkpts
mo_energy = adc.mo_energy
mo_coeff = adc.mo_coeff
nocc = adc.nocc
kconserv = adc.khelper.kconserv
mo_coeff, mo_energy = _add_padding(adc, mo_coeff, mo_energy)
e_occ = [mo_energy[k][:nocc] for k in range(nkpts)]
e_vir = [mo_energy[k][nocc:] for k in range(nkpts)]
e_occ = np.array(e_occ)
e_vir = np.array(e_vir)
idn_occ = np.identity(nocc)
M_ij = np.empty((nkpts,nocc,nocc),dtype=mo_coeff.dtype)
if eris is None:
eris = adc.transform_integrals()
# i-j block
# Zeroth-order terms
t2_1 = adc.t2[0]
eris_ovov = eris.ovov
for ki in range(nkpts):
kj = ki
M_ij[ki] = lib.einsum('ij,j->ij', idn_occ , e_occ[kj])
for kl in range(nkpts):
for kd in range(nkpts):
ke = kconserv[kj,kd,kl]
t2_1 = adc.t2[0]
t2_1_ild = adc.t2[0][ki,kl,kd]
M_ij[ki] += 0.5 * 0.5 * \
lib.einsum('ilde,jdle->ij',t2_1_ild, eris_ovov[kj,kd,kl],optimize=True)
M_ij[ki] -= 0.5 * 0.5 * \
lib.einsum('ilde,jeld->ij',t2_1_ild, eris_ovov[kj,ke,kl],optimize=True)
M_ij[ki] += 0.5 * lib.einsum('ilde,jdle->ij',t2_1_ild,
eris_ovov[kj,kd,kl],optimize=True)
del t2_1_ild
t2_1_lid = adc.t2[0][kl,ki,kd]
M_ij[ki] -= 0.5 * 0.5 * \
lib.einsum('lide,jdle->ij',t2_1_lid, eris_ovov[kj,kd,kl],optimize=True)
M_ij[ki] += 0.5 * 0.5 * \
lib.einsum('lide,jeld->ij',t2_1_lid, eris_ovov[kj,ke,kl],optimize=True)
del t2_1_lid
t2_1_jld = adc.t2[0][kj,kl,kd]
M_ij[ki] += 0.5 * 0.5 * \
lib.einsum('jlde,idle->ij',t2_1_jld.conj(),
eris_ovov[ki,kd,kl].conj(),optimize=True)
M_ij[ki] -= 0.5 * 0.5 * \
lib.einsum('jlde,ield->ij',t2_1_jld.conj(),
eris_ovov[ki,ke,kl].conj(),optimize=True)
M_ij[ki] += 0.5 * lib.einsum('jlde,idle->ij',t2_1_jld.conj(),
eris_ovov[ki,kd,kl].conj(),optimize=True)
del t2_1_jld
t2_1_ljd = adc.t2[0][kl,kj,kd]
M_ij[ki] -= 0.5 * 0.5 * \
lib.einsum('ljde,idle->ij',t2_1_ljd.conj(),
eris_ovov[ki,kd,kl].conj(),optimize=True)
M_ij[ki] += 0.5 * 0.5 * \
lib.einsum('ljde,ield->ij',t2_1_ljd.conj(),
eris_ovov[ki,ke,kl].conj(),optimize=True)
del t2_1_ljd
del t2_1
cput0 = log.timer_debug1("Completed M_ij second-order terms ADC(2) calculation", *cput0)
if (method == "adc(3)"):
t1_2 = adc.t1[0]
eris_ovoo = eris.ovoo
eris_ovvo = eris.ovvo
eris_oovv = eris.oovv
eris_oooo = eris.oooo
for ki in range(nkpts):
kj = ki
for kl in range(nkpts):
kd = kconserv[kj,ki,kl]
M_ij[ki] += 2. * lib.einsum('ld,ldji->ij',t1_2[kl],
eris_ovoo[kl,kd,kj],optimize=True)
M_ij[ki] -= lib.einsum('ld,jdli->ij',t1_2[kl],
eris_ovoo[kj,kd,kl],optimize=True)
kd = kconserv[ki,kj,kl]
M_ij[ki] += 2. * lib.einsum('ld,ldij->ij',t1_2[kl].conj(),
eris_ovoo[kl,kd,ki].conj(),optimize=True)
M_ij[ki] -= lib.einsum('ld,idlj->ij',t1_2[kl].conj(),
eris_ovoo[ki,kd,kl].conj(),optimize=True)
for kd in range(nkpts):
t2_1 = adc.t2[0]
ke = kconserv[kj,kd,kl]
t2_2_ild = adc.t2[1][ki,kl,kd]
M_ij[ki] += 0.5 * 0.5* \
lib.einsum('ilde,jdle->ij',t2_2_ild, eris_ovov[kj,kd,kl],optimize=True)
M_ij[ki] -= 0.5 * 0.5* \
lib.einsum('ilde,jeld->ij',t2_2_ild, eris_ovov[kj,ke,kl],optimize=True)
M_ij[ki] += 0.5 * \
lib.einsum('ilde,jdle->ij',t2_2_ild, eris_ovov[kj,kd,kl],optimize=True)
del t2_2_ild
t2_2_lid = adc.t2[1][kl,ki,kd]
M_ij[ki] -= 0.5 * 0.5* \
lib.einsum('lide,jdle->ij',t2_2_lid, eris_ovov[kj,kd,kl],optimize=True)
M_ij[ki] += 0.5 * 0.5* \
lib.einsum('lide,jeld->ij',t2_2_lid, eris_ovov[kj,ke,kl],optimize=True)
t2_2_jld = adc.t2[1][kj,kl,kd]
M_ij[ki] += 0.5 * 0.5* \
lib.einsum('jlde,leid->ij',t2_2_jld.conj(),
eris_ovov[kl,ke,ki].conj(),optimize=True)
M_ij[ki] -= 0.5 * 0.5* \
lib.einsum('jlde,ield->ij',t2_2_jld.conj(),
eris_ovov[ki,ke,kl].conj(),optimize=True)
M_ij[ki] += 0.5 * lib.einsum('jlde,leid->ij',t2_2_jld.conj(),
eris_ovov[kl,ke,ki].conj(),optimize=True)
t2_2_ljd = adc.t2[1][kl,kj,kd]
M_ij[ki] -= 0.5 * 0.5* \
lib.einsum('ljde,leid->ij',t2_2_ljd.conj(),
eris_ovov[kl,ke,ki].conj(),optimize=True)
M_ij[ki] += 0.5 * 0.5* \
lib.einsum('ljde,ield->ij',t2_2_ljd.conj(),
eris_ovov[ki,ke,kl].conj(),optimize=True)
for km, ke, kd in kpts_helper.loop_kkk(nkpts):
t2_1 = adc.t2[0]
kl = kconserv[kd,km,ke]
kf = kconserv[kj,kd,kl]
temp_t2_v_1 = lib.einsum(
'lmde,jldf->mejf',t2_1[kl,km,kd].conj(), t2_1[kj,kl,kd],optimize=True)
M_ij[ki] -= 0.5 * 2 * lib.einsum('mejf,ifem->ij',
temp_t2_v_1, eris_ovvo[ki,kf,ke],optimize=True)
M_ij[ki] -= 0.5 * 2 * lib.einsum('meif,jfem->ij',temp_t2_v_1.conj(),
eris_ovvo[kj,kf,ke].conj(),optimize=True)
M_ij[ki] += 0.5 * lib.einsum('mejf,imef->ij',
temp_t2_v_1, eris_oovv[ki,km,ke],optimize=True)
M_ij[ki] += 0.5 * lib.einsum('meif,jmef->ij',temp_t2_v_1.conj(),
eris_oovv[kj,km,ke].conj(),optimize=True)
temp_t2_v_new = lib.einsum(
'mlde,ljdf->mejf',t2_1[km,kl,kd].conj(), t2_1[kl,kj,kd],optimize=True)
M_ij[ki] -= 0.5 * 2 * lib.einsum('mejf,ifem->ij',
temp_t2_v_new, eris_ovvo[ki,kf,ke],optimize=True)
M_ij[ki] += 0.5 * lib.einsum('mejf,imef->ij',
temp_t2_v_new, eris_oovv[ki,km,ke],optimize=True)
M_ij[ki] -= 0.5 * 2 * lib.einsum('meif,jfem->ij',temp_t2_v_new.conj(),
eris_ovvo[kj,kf,ke].conj(),optimize=True)
M_ij[ki] += 0.5 * lib.einsum('meif,jmef->ij',temp_t2_v_new.conj(),
eris_oovv[kj,km,ke].conj(),optimize=True)
del temp_t2_v_new
temp_t2_v_2 = lib.einsum(
'lmde,ljdf->mejf',t2_1[kl,km,kd].conj(), t2_1[kl,kj,kd],optimize=True)
M_ij[ki] += 0.5 * 4 * lib.einsum('mejf,ifem->ij',
temp_t2_v_2, eris_ovvo[ki,kf,ke],optimize=True)
M_ij[ki] += 0.5 * 4 * lib.einsum('meif,jfem->ij',temp_t2_v_2.conj(),
eris_ovvo[kj,kf,ke].conj(),optimize=True)
M_ij[ki] -= 0.5 * 2 * lib.einsum('meif,jmef->ij',temp_t2_v_2.conj(),
eris_oovv[kj,km,ke].conj(),optimize=True)
M_ij[ki] -= 0.5 * 2 * lib.einsum('mejf,imef->ij',
temp_t2_v_2, eris_oovv[ki,km,ke],optimize=True)
del temp_t2_v_2
temp_t2_v_3 = lib.einsum(
'mlde,jldf->mejf',t2_1[km,kl,kd].conj(), t2_1[kj,kl,kd],optimize=True)
M_ij[ki] += 0.5 * lib.einsum('mejf,ifem->ij',
temp_t2_v_3, eris_ovvo[ki,kf,ke],optimize=True)
M_ij[ki] += 0.5 * lib.einsum('meif,jfem->ij',temp_t2_v_3.conj(),
eris_ovvo[kj,kf,ke].conj(),optimize=True)
M_ij[ki] -= 0.5 *2 * lib.einsum('meif,jmef->ij',temp_t2_v_3.conj(),
eris_oovv[kj,km,ke].conj(),optimize=True)
M_ij[ki] -= 0.5 *2 * lib.einsum('mejf,imef->ij',
temp_t2_v_3, eris_oovv[ki,km,ke],optimize=True)
del temp_t2_v_3
for km, ke, kd in kpts_helper.loop_kkk(nkpts):
kl = kconserv[kd,km,ke]
kf = kconserv[kl,kd,km]
temp_t2_v_8 = lib.einsum(
'lmdf,lmde->fe',t2_1[kl,km,kd], t2_1[kl,km,kd].conj(),optimize=True)
M_ij[ki] += 3.0 * lib.einsum('fe,jief->ij',temp_t2_v_8,
eris_oovv[kj,ki,ke], optimize=True)
M_ij[ki] -= 1.5 * lib.einsum('fe,jfei->ij',temp_t2_v_8,
eris_ovvo[kj,kf,ke], optimize=True)
M_ij[ki] += lib.einsum('ef,jief->ij',temp_t2_v_8.T,
eris_oovv[kj,ki,ke], optimize=True)
M_ij[ki] -= 0.5 * lib.einsum('ef,jfei->ij',temp_t2_v_8.T,
eris_ovvo[kj,kf,ke], optimize=True)
del temp_t2_v_8
temp_t2_v_9 = lib.einsum(
'lmdf,mlde->fe',t2_1[kl,km,kd], t2_1[km,kl,kd].conj(),optimize=True)
M_ij[ki] -= 1.0 * lib.einsum('fe,jief->ij',temp_t2_v_9,
eris_oovv[kj,ki,ke], optimize=True)
M_ij[ki] -= 1.0 * lib.einsum('ef,jief->ij',temp_t2_v_9.T,
eris_oovv[kj,ki,ke], optimize=True)
M_ij[ki] += 0.5 * lib.einsum('fe,jfei->ij',temp_t2_v_9,
eris_ovvo[kj,kf,ke], optimize=True)
M_ij[ki] += 0.5 * lib.einsum('ef,jfei->ij',temp_t2_v_9.T,
eris_ovvo[kj,kf,ke], optimize=True)
del temp_t2_v_9
kl = kconserv[kd,km,ke]
kn = kconserv[kd,kl,ke]
temp_t2_v_10 = lib.einsum(
'lnde,lmde->nm',t2_1[kl,kn,kd], t2_1[kl,km,kd].conj(),optimize=True)
M_ij[ki] -= 3.0 * lib.einsum('nm,jinm->ij',temp_t2_v_10,
eris_oooo[kj,ki,kn], optimize=True)
M_ij[ki] -= 1.0 * lib.einsum('mn,jinm->ij',temp_t2_v_10.T,
eris_oooo[kj,ki,kn], optimize=True)
M_ij[ki] += 1.5 * lib.einsum('nm,jmni->ij',temp_t2_v_10,
eris_oooo[kj,km,kn], optimize=True)
M_ij[ki] += 0.5 * lib.einsum('mn,jmni->ij',temp_t2_v_10.T,
eris_oooo[kj,km,kn], optimize=True)
del temp_t2_v_10
temp_t2_v_11 = lib.einsum(
'lnde,mlde->nm',t2_1[kl,kn,kd], t2_1[km,kl,kd].conj(),optimize=True)
M_ij[ki] += 1.0 * lib.einsum('nm,jinm->ij',temp_t2_v_11,
eris_oooo[kj,ki,kn], optimize=True)
M_ij[ki] -= 0.5 * lib.einsum('nm,jmni->ij',temp_t2_v_11,
eris_oooo[kj,km,kn], optimize=True)
M_ij[ki] -= 0.5 * lib.einsum('mn,jmni->ij',temp_t2_v_11.T,
eris_oooo[kj,km,kn], optimize=True)
M_ij[ki] += 1.0 * lib.einsum('mn,jinm->ij',temp_t2_v_11.T,
eris_oooo[kj,ki,kn], optimize=True)
del temp_t2_v_11
for km, ke, kd in kpts_helper.loop_kkk(nkpts):
t2_1 = adc.t2[0]
kl = kconserv[kd,km,ke]
kn = kconserv[kd,ki,ke]
temp_t2_v_12 = lib.einsum(
'inde,lmde->inlm',t2_1[ki,kn,kd].conj(), t2_1[kl,km,kd],optimize=True)
M_ij[ki] += 0.5 * 1.25 * \
lib.einsum('inlm,jlnm->ij',temp_t2_v_12,
eris_oooo[kj,kl,kn].conj(), optimize=True)
M_ij[ki] -= 0.5 * 0.25 * \
lib.einsum('inlm,jmnl->ij',temp_t2_v_12,
eris_oooo[kj,km,kn].conj(), optimize=True)
M_ij[ki] += 0.5 * 1.25 * \
lib.einsum('jnlm,ilnm->ij',temp_t2_v_12.conj(),
eris_oooo[ki,kl,kn], optimize=True)
M_ij[ki] -= 0.5 * 0.25 * \
lib.einsum('jnlm,imnl->ij',temp_t2_v_12.conj(),
eris_oooo[ki,km,kn], optimize=True)
del temp_t2_v_12
temp_t2_v_12_1 = lib.einsum(
'nide,mlde->inlm',t2_1[kn,ki,kd].conj(), t2_1[km,kl,kd],optimize=True)
M_ij[ki] += 0.5 * 0.25 * \
lib.einsum('inlm,jlnm->ij',temp_t2_v_12_1,
eris_oooo[kj,kl,kn].conj(), optimize=True)
M_ij[ki] -= 0.5 * 0.25 * \
lib.einsum('inlm,jmnl->ij',temp_t2_v_12_1,
eris_oooo[kj,km,kn].conj(), optimize=True)
M_ij[ki] += 0.5 * 0.25 * \
lib.einsum('jnlm,ilnm->ij',temp_t2_v_12_1.conj(),
eris_oooo[ki,kl,kn], optimize=True)
M_ij[ki] -= 0.5 * 0.25 * \
lib.einsum('jnlm,imnl->ij',temp_t2_v_12_1.conj(),
eris_oooo[ki,km,kn], optimize=True)
temp_t2_v_13 = lib.einsum(
'inde,mlde->inml',t2_1[ki,kn,kd].conj(), t2_1[km,kl,kd],optimize=True)
M_ij[ki] -= 0.5 * 0.5 * \
lib.einsum('inml,jlnm->ij',temp_t2_v_13,
eris_oooo[kj,kl,kn].conj(), optimize=True)
M_ij[ki] += 0.5 * 0.25 * \
lib.einsum('inml,jmnl->ij',temp_t2_v_13,
eris_oooo[kj,km,kn].conj(), optimize=True)
M_ij[ki] -= 0.5 * 0.5 * \
lib.einsum('jnml,ilnm->ij',temp_t2_v_13.conj(),
eris_oooo[ki,kl,kn], optimize=True)
M_ij[ki] += 0.5 * 0.25 * \
lib.einsum('jnml,imnl->ij',temp_t2_v_13.conj(),
eris_oooo[ki,km,kn], optimize=True)
del temp_t2_v_13
temp_t2_v_13_1 = lib.einsum(
'nide,lmde->inml',t2_1[kn,ki,kd].conj(), t2_1[kl,km,kd],optimize=True)
M_ij[ki] += 0.5 * 0.25 * \
lib.einsum('inml,jmnl->ij',temp_t2_v_13_1,
eris_oooo[kj,km,kn].conj(), optimize=True)
M_ij[ki] += 0.5 * 0.25 * \
lib.einsum('jnml,imnl->ij',temp_t2_v_13_1.conj(),
eris_oooo[ki,km,kn], optimize=True)
del temp_t2_v_13_1
return M_ij
[docs]
def get_diag(adc,kshift,M_ij=None,eris=None):
log = logger.Logger(adc.stdout, adc.verbose)
if adc.method not in ("adc(2)", "adc(2)-x", "adc(3)"):
raise NotImplementedError(adc.method)
if M_ij is None:
M_ij = adc.get_imds()
nkpts = adc.nkpts
kconserv = adc.khelper.kconserv
nocc = adc.nocc
n_singles = nocc
nvir = adc.nmo - adc.nocc
n_doubles = nkpts * nkpts * nvir * nocc * nocc
dim = n_singles + n_doubles
s1 = 0
f1 = n_singles
s2 = f1
f2 = s2 + n_doubles
mo_energy = adc.mo_energy
mo_coeff = adc.mo_coeff
nocc = adc.nocc
mo_coeff, mo_energy = _add_padding(adc, mo_coeff, mo_energy)
e_occ = [mo_energy[k][:nocc] for k in range(nkpts)]
e_vir = [mo_energy[k][nocc:] for k in range(nkpts)]
e_vir = np.array(e_vir)
e_occ = np.array(e_occ)
diag = np.zeros((dim), dtype=np.complex128)
doubles = np.zeros((nkpts,nkpts,nvir*nocc*nocc),dtype=np.complex128)
# Compute precond in h1-h1 block
M_ij_diag = np.diagonal(M_ij[kshift])
diag[s1:f1] = M_ij_diag.copy()
# Compute precond in 2p1h-2p1h block
for ka in range(nkpts):
for ki in range(nkpts):
kj = kconserv[kshift,ki,ka]
d_ij = e_occ[ki][:,None] + e_occ[kj]
d_a = e_vir[ka][:,None]
D_n = -d_a + d_ij.reshape(-1)
doubles[ka,ki] += D_n.reshape(-1)
diag[s2:f2] = doubles.reshape(-1)
diag = -diag
log.timer_debug1("Completed ea_diag calculation")
return diag
[docs]
def matvec(adc, kshift, M_ij=None, eris=None):
if adc.method not in ("adc(2)", "adc(2)-x", "adc(3)"):
raise NotImplementedError(adc.method)
method = adc.method
nkpts = adc.nkpts
nocc = adc.nocc
kconserv = adc.khelper.kconserv
n_singles = nocc
nvir = adc.nmo - adc.nocc
n_doubles = nkpts * nkpts * nvir * nocc * nocc
s_singles = 0
f_singles = n_singles
s_doubles = f_singles
f_doubles = s_doubles + n_doubles
mo_energy = adc.mo_energy
mo_coeff = adc.mo_coeff
mo_coeff, mo_energy = _add_padding(adc, mo_coeff, mo_energy)
e_occ = [mo_energy[k][:nocc] for k in range(nkpts)]
e_vir = [mo_energy[k][nocc:] for k in range(nkpts)]
e_vir = np.array(e_vir)
e_occ = np.array(e_occ)
if M_ij is None:
M_ij = adc.get_imds()
#Calculate sigma vector
def sigma_(r):
cput0 = (time.process_time(), time.time())
log = logger.Logger(adc.stdout, adc.verbose)
r1 = r[s_singles:f_singles]
r2 = r[s_doubles:f_doubles]
r2 = r2.reshape(nkpts,nkpts,nvir,nocc,nocc)
s2 = np.zeros((nkpts,nkpts,nvir,nocc,nocc), dtype=np.complex128)
cell = adc.cell
kpts = adc.kpts
madelung = tools.madelung(cell, kpts)
eris_ovoo = eris.ovoo
############ ADC(2) ij block ############################
s1 = lib.einsum('ij,j->i',M_ij[kshift],r1)
########### ADC(2) i - kja block #########################
for kj in range(nkpts):
for kk in range(nkpts):
ka = kconserv[kk, kshift, kj]
ki = kconserv[kj, kk, ka]
s1 += 2. * lib.einsum('jaki,ajk->i',
eris_ovoo[kj,ka,kk].conj(), r2[ka,kj], optimize=True)
s1 -= lib.einsum('kaji,ajk->i',
eris_ovoo[kk,ka,kj].conj(), r2[ka,kj], optimize=True)
#################### ADC(2) ajk - i block ############################
s2[ka,kj] += lib.einsum('jaki,i->ajk', eris_ovoo[kj,ka,kk], r1, optimize=True)
################# ADC(2) ajk - bil block ############################
s2[ka, kj] -= lib.einsum('a,ajk->ajk', e_vir[ka], r2[ka, kj])
s2[ka, kj] += lib.einsum('j,ajk->ajk', e_occ[kj], r2[ka, kj])
s2[ka, kj] += lib.einsum('k,ajk->ajk', e_occ[kk], r2[ka, kj])
############### ADC(3) ajk - bil block ############################
if (method == "adc(2)-x" or method == "adc(3)"):
eris_oooo = eris.oooo
eris_oovv = eris.oovv
eris_ovvo = eris.ovvo
for kj in range(nkpts):
for kk in range(nkpts):
ka = kconserv[kk, kshift, kj]
for kl in range(nkpts):
ki = kconserv[kj, kl, kk]
s2[ka,kj] -= 0.5*lib.einsum('kijl,ali->ajk',
eris_oooo[kk,ki,kj], r2[ka,kl], optimize=True)
s2[ka,kj] -= 0.5*lib.einsum('klji,ail->ajk',
eris_oooo[kk,kl,kj],r2[ka,ki], optimize=True)
for kl in range(nkpts):
kb = kconserv[ka, kk, kl]
s2[ka,kj] += 0.5*lib.einsum('klba,bjl->ajk',
eris_oovv[kk,kl,kb],r2[kb,kj],optimize=True)
kb = kconserv[kl, kj, ka]
s2[ka,kj] += 0.5*lib.einsum('jabl,bkl->ajk',
eris_ovvo[kj,ka,kb],r2[kb,kk],optimize=True)
s2[ka,kj] -= lib.einsum('jabl,blk->ajk',
eris_ovvo[kj,ka,kb],r2[kb,kl],optimize=True)
kb = kconserv[ka, kj, kl]
s2[ka,kj] += 0.5*lib.einsum('jlba,blk->ajk',
eris_oovv[kj,kl,kb],r2[kb,kl],optimize=True)
for ki in range(nkpts):
kb = kconserv[ka, kk, ki]
s2[ka,kj] += 0.5*lib.einsum('kiba,bji->ajk',
eris_oovv[kk,ki,kb],r2[kb,kj],optimize=True)
kb = kconserv[ka, kj, ki]
s2[ka,kj] += 0.5*lib.einsum('jiba,bik->ajk',
eris_oovv[kj,ki,kb],r2[kb,ki],optimize=True)
s2[ka,kj] -= lib.einsum('jabi,bik->ajk',eris_ovvo[kj,
ka,kb],r2[kb,ki],optimize=True)
kb = kconserv[ki, kj, ka]
s2[ka,kj] += 0.5*lib.einsum('jabi,bki->ajk',
eris_ovvo[kj,ka,kb],r2[kb,kk],optimize=True)
if adc.exxdiv is not None:
s2 += madelung * r2
if (method == "adc(3)"):
eris_ovoo = eris.ovoo
################# ADC(3) i - kja block and ajk - i ############################
for kj in range(nkpts):
for kk in range(nkpts):
ka = kconserv[kj,kshift,kk]
for kb in range(nkpts):
kc = kconserv[kj,kb,kk]
t2_1 = adc.t2[0]
temp_1 = lib.einsum(
'jkbc,ajk->abc',t2_1[kj,kk,kb], r2[ka,kj], optimize=True)
temp = 0.25 * lib.einsum('jkbc,ajk->abc',
t2_1[kj,kk,kb], r2[ka,kj], optimize=True)
temp -= 0.25 * lib.einsum('jkbc,akj->abc',
t2_1[kj,kk,kb], r2[ka,kk], optimize=True)
temp -= 0.25 * lib.einsum('kjbc,ajk->abc',
t2_1[kk,kj,kb], r2[ka,kj], optimize=True)
temp += 0.25 * lib.einsum('kjbc,akj->abc',
t2_1[kk,kj,kb], r2[ka,kk], optimize=True)
ki = kconserv[kc,ka,kb]
if isinstance(eris.ovvv, type(None)):
chnk_size = adc.chnk_size
if chnk_size > nocc:
chnk_size = nocc
a = 0
for p in range(0,nocc,chnk_size):
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[ki,kc], eris.Lvv[ka,kb], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
s1[a:a+k] += lib.einsum('abc,icab->i',temp_1,
eris_ovvv, optimize=True)
s1[a:a+k] += lib.einsum('abc,icab->i',temp,
eris_ovvv, optimize=True)
del eris_ovvv
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[ki,kb], eris.Lvv[ka,kc], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
s1[a:a+k] -= lib.einsum('abc,ibac->i',temp,
eris_ovvv, optimize=True)
del eris_ovvv
a += k
else :
eris_ovvv = eris.ovvv[:]
s1 += lib.einsum('abc,icab->i',temp_1,
eris_ovvv[ki,kc,ka], optimize=True)
s1 += lib.einsum('abc,icab->i',temp,
eris_ovvv[ki,kc,ka], optimize=True)
s1 -= lib.einsum('abc,ibac->i',temp,
eris_ovvv[ki,kb,ka], optimize=True)
del eris_ovvv
del temp
del temp_1
t2_1 = adc.t2[0]
for kj in range(nkpts):
for kk in range(nkpts):
ka = kconserv[kj, kshift, kk]
for kc in range(nkpts):
kb = kconserv[kj, kc, kk]
ki = kconserv[kb,ka,kc]
if isinstance(eris.ovvv, type(None)):
chnk_size = adc.chnk_size
if chnk_size > nocc:
chnk_size = nocc
a = 0
for p in range(0,nocc,chnk_size):
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[ki,kc], eris.Lvv[ka,kb], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
temp = lib.einsum(
'i,icab->cba',r1[a:a+k],eris_ovvv.conj(), optimize=True)
del eris_ovvv
a += k
else :
eris_ovvv = eris.ovvv[:]
temp = lib.einsum(
'i,icab->cba',r1,eris_ovvv[ki,kc,ka].conj(),optimize=True)
del eris_ovvv
s2[ka,kj] += lib.einsum('cba,jkbc->ajk',temp,
t2_1[kj,kk,kb].conj(), optimize=True)
del temp
for kj in range(nkpts):
for kk in range(nkpts):
ka = kconserv[kj, kshift, kk]
for kb in range(nkpts):
kl = kconserv[ka, kj, kb]
t2_1 = adc.t2[0]
temp = lib.einsum('ljba,ajk->blk',t2_1[kl,kj,kb],r2[ka,kj],optimize=True)
temp_2 = lib.einsum('jlba,akj->blk',t2_1[kj,kl,kb],r2[ka,kk], optimize=True)
del t2_1
t2_1_jla = adc.t2[0][kj,kl,ka]
temp += lib.einsum('jlab,ajk->blk',t2_1_jla,r2[ka,kj],optimize=True)
temp -= lib.einsum('jlab,akj->blk',t2_1_jla,r2[ka,kk],optimize=True)
temp_1 = lib.einsum('jlab,ajk->blk',t2_1_jla,r2[ka,kj],optimize=True)
temp_1 -= lib.einsum('jlab,akj->blk',t2_1_jla,r2[ka,kk],optimize=True)
temp_1 += lib.einsum('jlab,ajk->blk',t2_1_jla,r2[ka,kj],optimize=True)
del t2_1_jla
t2_1_lja = adc.t2[0][kl,kj,ka]
temp -= lib.einsum('ljab,ajk->blk',t2_1_lja,r2[ka,kj],optimize=True)
temp += lib.einsum('ljab,akj->blk',t2_1_lja,r2[ka,kk],optimize=True)
temp_1 -= lib.einsum('ljab,ajk->blk',t2_1_lja,r2[ka,kj],optimize=True)
del t2_1_lja
ki = kconserv[kk, kl, kb]
s1 += 0.5*lib.einsum('blk,lbik->i',temp, eris_ovoo[kl,kb,ki],optimize=True)
s1 -= 0.5*lib.einsum('blk,iblk->i',temp, eris_ovoo[ki,kb,kl],optimize=True)
s1 += 0.5*lib.einsum('blk,lbik->i',temp_1,eris_ovoo[kl,kb,ki],optimize=True)
s1 -= 0.5*lib.einsum('blk,iblk->i',temp_2,eris_ovoo[ki,kb,kl],optimize=True)
del temp
del temp_1
del temp_2
for kb in range(nkpts):
kl = kconserv[ka, kk, kb]
t2_1 = adc.t2[0]
temp = -lib.einsum('lkba,akj->blj',t2_1[kl,kk,kb],r2[ka,kk],optimize=True)
temp_2 = -lib.einsum('klba,ajk->blj',t2_1[kk,kl,kb],r2[ka,kj],optimize=True)
del t2_1
t2_1_kla = adc.t2[0][kk,kl,ka]
temp -= lib.einsum('klab,akj->blj',t2_1_kla,r2[ka,kk],optimize=True)
temp += lib.einsum('klab,ajk->blj',t2_1_kla,r2[ka,kj],optimize=True)
temp_1 = -2.0 * lib.einsum('klab,akj->blj',
t2_1_kla,r2[ka,kk],optimize=True)
temp_1 += lib.einsum('klab,ajk->blj',t2_1_kla,r2[ka,kj],optimize=True)
del t2_1_kla
t2_1_lka = adc.t2[0][kl,kk,ka]
temp += lib.einsum('lkab,akj->blj',t2_1_lka,r2[ka,kk],optimize=True)
temp -= lib.einsum('lkab,ajk->blj',t2_1_lka,r2[ka,kj],optimize=True)
temp_1 += lib.einsum('lkab,akj->blj',t2_1_lka,r2[ka,kk],optimize=True)
del t2_1_lka
ki = kconserv[kj, kl, kb]
s1 -= 0.5*lib.einsum('blj,lbij->i',temp, eris_ovoo[kl,kb,ki],optimize=True)
s1 += 0.5*lib.einsum('blj,iblj->i',temp, eris_ovoo[ki,kb,kl],optimize=True)
s1 -= 0.5*lib.einsum('blj,lbij->i',temp_1,eris_ovoo[kl,kb,ki],optimize=True)
s1 += 0.5*lib.einsum('blj,iblj->i',temp_2,eris_ovoo[ki,kb,kl],optimize=True)
del temp
del temp_1
del temp_2
for kj in range(nkpts):
for kk in range(nkpts):
ka = kconserv[kk, kshift, kj]
for kl in range(nkpts):
kb = kconserv[kj, ka, kl]
ki = kconserv[kk,kl,kb]
temp_1 = lib.einsum(
'i,lbik->kbl',r1,eris_ovoo[kl,kb,ki].conj(), optimize=True)
temp = lib.einsum(
'i,lbik->kbl',r1,eris_ovoo[kl,kb,ki].conj(), optimize=True)
temp -= lib.einsum('i,iblk->kbl',r1,
eris_ovoo[ki,kb,kl].conj(), optimize=True)
t2_1 = adc.t2[0]
s2[ka,kj] += lib.einsum('kbl,ljba->ajk',temp,
t2_1[kl,kj,kb].conj(), optimize=True)
s2[ka,kj] += lib.einsum('kbl,jlab->ajk',temp_1,
t2_1[kj,kl,ka].conj(), optimize=True)
s2[ka,kj] -= lib.einsum('kbl,ljab->ajk',temp_1,
t2_1[kl,kj,ka].conj(), optimize=True)
kb = kconserv[kk, ka, kl]
ki = kconserv[kj,kl,kb]
temp_2 = -lib.einsum('i,iblj->jbl',r1,
eris_ovoo[ki,kb,kl].conj(), optimize=True)
s2[ka,kj] += lib.einsum('jbl,klba->ajk',temp_2,
t2_1[kk,kl,kb].conj(), optimize=True)
del t2_1
s2 = s2.reshape(-1)
s = np.hstack((s1,s2))
del s1
del s2
cput0 = log.timer_debug1("completed sigma vector calculation", *cput0)
s *= -1.0
return s
return sigma_
[docs]
def get_trans_moments(adc,kshift):
nmo = adc.nmo
T = []
for orb in range(nmo):
T_a = get_trans_moments_orbital(adc,orb,kshift)
T.append(T_a)
T = np.array(T)
return T
[docs]
def get_trans_moments_orbital(adc, orb, kshift):
if adc.method not in ("adc(2)", "adc(2)-x", "adc(3)"):
raise NotImplementedError(adc.method)
method = adc.method
nkpts = adc.nkpts
nocc = adc.nocc
nvir = adc.nmo - adc.nocc
t2_1 = adc.t2[0]
idn_occ = np.identity(nocc)
T1 = np.zeros((nocc), dtype=np.complex128)
T2 = np.zeros((nkpts,nkpts,nvir,nocc,nocc), dtype=np.complex128)
######## ADC(2) 1h part ############################################
if orb < nocc:
T1 += idn_occ[orb, :]
for kk in range(nkpts):
for kc in range(nkpts):
kd = adc.khelper.kconserv[kk, kc, kshift]
ki = adc.khelper.kconserv[kc, kk, kd]
T1 += 0.25*lib.einsum('kdc,ikdc->i',t2_1[kk,kshift,kd]
[:,orb,:,:].conj(), t2_1[ki,kk,kd], optimize=True)
T1 -= 0.25*lib.einsum('kcd,ikdc->i',t2_1[kk,kshift,kc]
[:,orb,:,:].conj(), t2_1[ki,kk,kd], optimize=True)
T1 -= 0.25*lib.einsum('kdc,ikcd->i',t2_1[kk,kshift,kd]
[:,orb,:,:].conj(), t2_1[ki,kk,kc], optimize=True)
T1 += 0.25*lib.einsum('kcd,ikcd->i',t2_1[kk,kshift,kc]
[:,orb,:,:].conj(), t2_1[ki,kk,kc], optimize=True)
T1 -= 0.25*lib.einsum('kdc,ikdc->i',t2_1[kshift,kk,kd]
[orb,:,:,:].conj(), t2_1[ki,kk,kd], optimize=True)
T1 -= 0.25*lib.einsum('kcd,ikcd->i',t2_1[kshift,kk,kc]
[orb,:,:,:].conj(), t2_1[ki,kk,kc], optimize=True)
else :
if (adc.approx_trans_moments is False or adc.method == "adc(3)"):
t1_2 = adc.t1[0]
T1 += t1_2[kshift][:,(orb-nocc)]
######## ADC(2) 2h-1p part ############################################
for ki in range(nkpts):
for kj in range(nkpts):
ka = adc.khelper.kconserv[kj, kshift, ki]
t2_1_t = -t2_1[ki,kj,ka].transpose(2,3,1,0)
T2[ka,kj] += t2_1_t[:,(orb-nocc),:,:].conj()
del t2_1_t
####### ADC(3) 2h-1p part ############################################
if (adc.method == "adc(2)-x" and adc.approx_trans_moments is False) or (adc.method == "adc(3)"):
t2_2 = adc.t2[1]
if orb >= nocc:
for ki in range(nkpts):
for kj in range(nkpts):
ka = adc.khelper.kconserv[kj, kshift, ki]
t2_2_t = -t2_2[ki,kj,ka].transpose(2,3,1,0)
T2[ka,kj] += t2_2_t[:,(orb-nocc),:,:].conj()
######### ADC(3) 1h part ############################################
if(method=='adc(3)'):
if orb < nocc:
for kk in range(nkpts):
for kc in range(nkpts):
kd = adc.khelper.kconserv[kk, kc, kshift]
ki = adc.khelper.kconserv[kd, kk, kc]
T1 += 0.25* \
lib.einsum('kdc,ikdc->i',t2_1[kk,ki,kd][:,orb,
:,:].conj(), t2_2[ki,kk,kd], optimize=True)
T1 -= 0.25* \
lib.einsum('kcd,ikdc->i',t2_1[kk,ki,kc][:,orb,
:,:].conj(), t2_2[ki,kk,kd], optimize=True)
T1 -= 0.25* \
lib.einsum('kdc,ikcd->i',t2_1[kk,ki,kd][:,orb,
:,:].conj(), t2_2[ki,kk,kc], optimize=True)
T1 += 0.25* \
lib.einsum('kcd,ikcd->i',t2_1[kk,ki,kc][:,orb,
:,:].conj(), t2_2[ki,kk,kc], optimize=True)
T1 -= 0.25* \
lib.einsum('kdc,ikdc->i',t2_1[ki,kk,kd][orb,:,
:,:].conj(), t2_2[ki,kk,kd], optimize=True)
T1 -= 0.25* \
lib.einsum('kcd,ikcd->i',t2_1[ki,kk,kc][orb,:,
:,:].conj(), t2_2[ki,kk,kc], optimize=True)
T1 += 0.25* \
lib.einsum('ikdc,kdc->i',t2_1[ki,kk,kd],
t2_2[kk,ki,kd][:,orb,:,:].conj(),optimize=True)
T1 -= 0.25* \
lib.einsum('ikcd,kdc->i',t2_1[ki,kk,kc],
t2_2[kk,ki,kd][:,orb,:,:].conj(),optimize=True)
T1 -= 0.25* \
lib.einsum('ikdc,kcd->i',t2_1[ki,kk,kd],
t2_2[kk,ki,kc][:,orb,:,:].conj(),optimize=True)
T1 += 0.25* \
lib.einsum('ikcd,kcd->i',t2_1[ki,kk,kc],
t2_2[kk,ki,kc][:,orb,:,:].conj(),optimize=True)
T1 -= 0.25* \
lib.einsum('ikcd,kcd->i',t2_1[ki,kk,kc],
t2_2[ki,kk,kc][orb,:,:,:].conj(),optimize=True)
T1 -= 0.25* \
lib.einsum('ikdc,kdc->i',t2_1[ki,kk,kd],
t2_2[ki,kk,kd][orb,:,:,:].conj(),optimize=True)
else:
for kk in range(nkpts):
for kc in range(nkpts):
ki = adc.khelper.kconserv[kshift,kk,kc]
T1 += 0.5 * lib.einsum('kic,kc->i',
t2_1[kk,ki,kc][:,:,:,(orb-nocc)], t1_2[kk],optimize=True)
T1 -= 0.5*lib.einsum('ikc,kc->i',t2_1[ki,kk,kc]
[:,:,:,(orb-nocc)], t1_2[kk],optimize=True)
T1 += 0.5*lib.einsum('kic,kc->i',t2_1[kk,ki,kc]
[:,:,:,(orb-nocc)], t1_2[kk],optimize=True)
del t2_2
del t2_1
for ki in range(nkpts):
for kj in range(nkpts):
ka = adc.khelper.kconserv[kj,kshift, ki]
T2[ka,kj] += T2[ka,kj] - T2[ka,ki].transpose(0,2,1)
T2 = T2.reshape(-1)
T = np.hstack((T1,T2))
return T
[docs]
def renormalize_eigenvectors(adc, kshift, U, nroots=1):
nkpts = adc.nkpts
nocc = adc.t2[0].shape[3]
n_singles = nocc
nvir = adc.nmo - adc.nocc
for I in range(U.shape[1]):
U1 = U[:n_singles,I]
U2 = U[n_singles:,I].reshape(nkpts,nkpts,nvir,nocc,nocc)
UdotU = np.dot(U1.conj().ravel(),U1.ravel())
for kj in range(nkpts):
for kk in range(nkpts):
ka = adc.khelper.kconserv[kj, kshift, kk]
UdotU += 2.*np.dot(U2[ka,kj].conj().ravel(), U2[ka,kj].ravel()) - \
np.dot(U2[ka,kj].conj().ravel(),
U2[ka,kk].transpose(0,2,1).ravel())
U[:,I] /= np.sqrt(UdotU)
U = U.reshape(-1,nroots)
return U
[docs]
def get_properties(adc, kshift, U, nroots=1):
#Transition moments
T = adc.get_trans_moments(kshift)
#Spectroscopic amplitudes
U = adc.renormalize_eigenvectors(kshift,U,nroots)
X = np.dot(T, U).reshape(-1, nroots)
#Spectroscopic factors
P = 2.0*lib.einsum("pi,pi->i", X.conj(), X)
P = P.real
return P,X
[docs]
class RADCIP(kadc_rhf.RADC):
'''restricted ADC for IP energies and spectroscopic amplitudes
Attributes:
verbose : int
Print level. Default value equals to :class:`Mole.verbose`
max_memory : float or int
Allowed memory in MB. Default value equals to :class:`Mole.max_memory`
incore_complete : bool
Avoid all I/O. Default is False.
method : string
nth-order ADC method. Options are : ADC(2), ADC(2)-X, ADC(3). Default is ADC(2).
conv_tol : float
Convergence threshold for Davidson iterations. Default is 1e-12.
max_cycle : int
Number of Davidson iterations. Default is 50.
max_space : int
Space size to hold trial vectors for Davidson iterative diagonalization. Default is 12.
Kwargs:
nroots : int
Number of roots (eigenvalues) requested. Default value is 1.
>>> myadc = adc.RADC(mf).run()
>>> myadcip = adc.RADC(myadc).run()
Saved results
e_ip : float or list of floats
IP energy (eigenvalue). For nroots = 1, it is a single float number. If nroots > 1, it is a list
of floats for the lowest nroots eigenvalues.
v_ip : array
Eigenvectors for each IP transition.
p_ip : float
Spectroscopic amplitudes for each IP transition.
'''
_keys = {
'tol_residual','conv_tol', 'e_corr', 'method', 'mo_coeff', 'mo_energy_b',
't1', 'mo_energy_a', 'max_space', 't2', 'max_cycle',
'kpts', 'exxdiv', 'khelper', 'cell', 'nkop_chk', 'kop_npick', 'chnk_size',
}
def __init__(self, adc):
self.verbose = adc.verbose
self.stdout = adc.stdout
self.max_memory = adc.max_memory
self.max_space = adc.max_space
self.max_cycle = adc.max_cycle
self.conv_tol = adc.conv_tol
self.tol_residual = adc.tol_residual
self.t1 = adc.t1
self.t2 = adc.t2
self.method = adc.method
self.method_type = adc.method_type
self._scf = adc._scf
self.compute_properties = adc.compute_properties
self.approx_trans_moments = adc.approx_trans_moments
self.kpts = adc._scf.kpts
self.exxdiv = adc.exxdiv
self.verbose = adc.verbose
self.max_memory = adc.max_memory
self.method = adc.method
self.khelper = adc.khelper
self.cell = adc.cell
self.mo_coeff = adc.mo_coeff
self.mo_occ = adc.mo_occ
self.frozen = adc.frozen
self._nocc = adc._nocc
self._nmo = adc._nmo
self._nvir = adc._nvir
self.nkop_chk = adc.nkop_chk
self.kop_npick = adc.kop_npick
self.t2 = adc.t2
self.e_corr = adc.e_corr
self.mo_energy = adc.mo_energy
self.imds = adc.imds
self.chnk_size = adc.chnk_size
kernel = kadc_rhf.kernel
get_imds = get_imds
get_diag = get_diag
matvec = matvec
vector_size = vector_size
get_trans_moments = get_trans_moments
renormalize_eigenvectors = renormalize_eigenvectors
get_properties = get_properties
[docs]
def get_init_guess(self, nroots=1, diag=None, ascending=True):
if diag is None :
diag = self.get_diag()
idx = None
dtype = getattr(diag, 'dtype', np.complex128)
if ascending:
idx = np.argsort(diag)
else:
idx = np.argsort(diag)[::-1]
guess = np.zeros((diag.shape[0], nroots), dtype=dtype)
min_shape = min(diag.shape[0], nroots)
guess[:min_shape,:min_shape] = np.identity(min_shape)
g = np.zeros((diag.shape[0], nroots), dtype=dtype)
g[idx] = guess.copy()
guess = []
for p in range(g.shape[1]):
guess.append(g[:,p])
return guess
[docs]
def gen_matvec(self,kshift,imds=None, eris=None):
if imds is None:
imds = self.get_imds(eris)
diag = self.get_diag(kshift,imds,eris)
matvec = self.matvec(kshift, imds, eris)
return matvec, diag
#return diag