# 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 = nvir
n_doubles = nkpts * nkpts * nocc * nvir * nvir
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
nvir = adc.nmo - 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_vir = np.identity(nvir)
if eris is None:
eris = adc.transform_integrals()
eris_ovov = eris.ovov
# a-b block
# Zeroth-order terms
M_ab = np.empty((nkpts,nvir,nvir),dtype=mo_coeff.dtype)
for ka in range(nkpts):
kb = ka
M_ab[ka] = lib.einsum('ab,a->ab', idn_vir, e_vir[ka])
for kl in range(nkpts):
for km in range(nkpts):
kd = kconserv[kl,ka,km]
# Second-order terms
t2_1_mla = adc.t2[0][km,kl,ka]
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('mlad,lbmd->ab',t2_1_mla, eris_ovov[kl,kb,km],optimize=True)
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('mlad,ldmb->ab',t2_1_mla, eris_ovov[kl,kd,km],optimize=True)
t2_1_lma = adc.t2[0][kl,km,ka]
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('lmad,lbmd->ab',t2_1_lma, eris_ovov[kl,kb,km],optimize=True)
M_ab[ka] -= 0.5 * \
lib.einsum('lmad,lbmd->ab',t2_1_lma, eris_ovov[kl,kb,km],optimize=True)
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('lmad,ldmb->ab',t2_1_lma, eris_ovov[kl,kd,km],optimize=True)
del t2_1_lma
t2_1_lmb = adc.t2[0][kl,km,kb]
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('lmbd,lamd->ab',t2_1_lmb.conj(),
eris_ovov[kl,ka,km].conj(),optimize=True)
M_ab[ka] -= 0.5 * \
lib.einsum('lmbd,lamd->ab',t2_1_lmb.conj(),
eris_ovov[kl,ka,km].conj(),optimize=True)
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('lmbd,ldma->ab',t2_1_lmb.conj(),
eris_ovov[kl,kd,km].conj(),optimize=True)
del t2_1_lmb
t2_1_mlb = adc.t2[0][km,kl,kb]
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('mlbd,lamd->ab',t2_1_mlb.conj(),
eris_ovov[kl,ka,km].conj(),optimize=True)
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('mlbd,ldma->ab',t2_1_mlb.conj(),
eris_ovov[kl,kd,km].conj(),optimize=True)
del t2_1_mlb
cput0 = log.timer_debug1("Completed M_ab second-order terms ADC(2) calculation", *cput0)
if(method =='adc(3)'):
eris_oovv = eris.oovv
eris_ovvo = eris.ovvo
t1_2 = adc.t1[0]
for ka in range(nkpts):
kb = ka
for kl in range(nkpts):
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):
kd = kconserv[ka,kb,kl]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kd], eris.Lvv[ka,kb], p, chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
M_ab[ka] += 2. * lib.einsum('ld,ldab->ab',t1_2[kl]
[a:a+k], eris_ovvv,optimize=True)
del eris_ovvv
kd = kconserv[kb,ka,kl]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kd], eris.Lvv[kb,ka], p, chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
M_ab[ka] += 2. * lib.einsum('ld,ldba->ab',t1_2[kl]
[a:a+k].conj(), eris_ovvv.conj(),optimize=True)
del eris_ovvv
kd = kconserv[ka,kb,kl]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kb], eris.Lvv[ka,kd], p, chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
M_ab[ka] -= lib.einsum('ld,lbad->ab',t1_2[kl][a:a+k],
eris_ovvv,optimize=True)
del eris_ovvv
kd = kconserv[kb,ka,kl]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,ka], eris.Lvv[kb,kd], p, chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
M_ab[ka] -= lib.einsum('ld,labd->ab',t1_2[kl,a:a+k].conj(),
eris_ovvv.conj(),optimize=True)
del eris_ovvv
a += k
else :
eris_ovvv = eris.ovvv
kd = kconserv[ka,kb,kl]
M_ab[ka] += 2. * lib.einsum('ld,ldab->ab',t1_2[kl],
eris_ovvv[kl,kd,ka],optimize=True)
M_ab[ka] -= lib.einsum('ld,lbad->ab',t1_2[kl],
eris_ovvv[kl,kb,ka],optimize=True)
kd = kconserv[kb,ka,kl]
M_ab[ka] += 2. * lib.einsum('ld,ldba->ab',t1_2[kl].conj(),
eris_ovvv[kl,kd,kb].conj(),optimize=True)
M_ab[ka] -= lib.einsum('ld,labd->ab',t1_2[kl].conj(),
eris_ovvv[kl,ka,kb].conj(),optimize=True)
cput0 = log.timer_debug1("Completed M_ab ovvv ADC(3) calculation", *cput0)
for ka in range(nkpts):
kb = ka
for kl in range(nkpts):
for km in range(nkpts):
kd = kconserv[km,ka,kl]
t2_1 = adc.t2[0]
t2_2_lma = adc.t2[1][kl,km,ka]
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('lmad,lbmd->ab',t2_2_lma, eris_ovov[kl,kb,km],optimize=True)
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('lmad,ldmb->ab',t2_2_lma, eris_ovov[kl,kd,km],optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('lmad,lbmd->ab',
t2_2_lma, eris_ovov[kl,kb,km],optimize=True)
t2_2_mla = adc.t2[1][km,kl,ka]
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('mlad,lbmd->ab',t2_2_mla, eris_ovov[kl,kb,km],optimize=True)
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('mlad,ldmb->ab',t2_2_mla, eris_ovov[kl,kd,km],optimize=True)
t2_2_lmb = adc.t2[1][kl,km,kb]
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('lmbd,lamd->ab',t2_2_lmb.conj(),
eris_ovov[kl,ka,km].conj(),optimize=True)
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('lmbd,ldma->ab',t2_2_lmb.conj(),
eris_ovov[kl,kd,km].conj(),optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('lmbd,lamd->ab',t2_2_lmb.conj(),
eris_ovov[kl,ka,km].conj(),optimize=True)
t2_2_mlb = adc.t2[1][km,kl,kb]
M_ab[ka] += 0.5 * 0.5 * \
lib.einsum('mlbd,mdla->ab',t2_2_mlb.conj(),
eris_ovov[km,kd,kl].conj(),optimize=True)
M_ab[ka] -= 0.5 * 0.5 * \
lib.einsum('mlbd,ldma->ab',t2_2_mlb.conj(),
eris_ovov[kl,kd,km].conj(),optimize=True)
del t2_2_mlb
log.timer_debug1("Starting the small integrals calculation")
for kn, ke, kd in kpts_helper.loop_kkk(nkpts):
kl = kconserv[ke,kn,kd]
km = kconserv[kb,kl,kd]
temp_t2_v_1 = lib.einsum(
'lned,mlbd->nemb',t2_1[kl,kn,ke], t2_1[km,kl,kb].conj(),optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('nemb,nmae->ab',
temp_t2_v_1, eris_oovv[kn,km,ka], optimize=True)
M_ab[ka] += 0.5 *2. * lib.einsum('nemb,neam->ab',
temp_t2_v_1, eris_ovvo[kn,ke,ka], optimize=True)
M_ab[ka] += 0.5 *2. * lib.einsum('nema,nebm->ab',
temp_t2_v_1, eris_ovvo[kn,ke,kb], optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('nema,nmbe->ab',
temp_t2_v_1, eris_oovv[kn,km,kb], optimize=True)
del temp_t2_v_1
temp_t2_v_1 = lib.einsum(
'nled,lmbd->mbne',t2_1[kn,kl,ke], t2_1[kl,km,kb].conj(),optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('mbne,nmae->ab',
temp_t2_v_1, eris_oovv[kn,km,ka], optimize=True)
M_ab[ka] += 0.5 *2. * lib.einsum('mbne,neam->ab',
temp_t2_v_1, eris_ovvo[kn,ke,ka], optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('mane,nmbe->ab',
temp_t2_v_1, eris_oovv[kn,km,kb], optimize=True)
M_ab[ka] += 0.5 *2. * lib.einsum('mane,nebm->ab',
temp_t2_v_1, eris_ovvo[kn,ke,kb], optimize=True)
del temp_t2_v_1
temp_t2_v_2 = lib.einsum(
'nled,mlbd->nemb',t2_1[kn,kl,ke], t2_1[km,kl,kb].conj(),optimize=True)
M_ab[ka] += 0.5 * 2. * lib.einsum('nemb,nmae->ab',
temp_t2_v_2, eris_oovv[kn,km,ka], optimize=True)
M_ab[ka] -= 0.5 * 4. * lib.einsum('nemb,neam->ab',
temp_t2_v_2, eris_ovvo[kn,ke,ka], optimize=True)
M_ab[ka] += 0.5 * 2. * lib.einsum('nema,nmbe->ab',
temp_t2_v_2, eris_oovv[kn,km,kb], optimize=True)
M_ab[ka] -= 0.5 * 4. * lib.einsum('nema,nebm->ab',
temp_t2_v_2, eris_ovvo[kn,ke,kb], optimize=True)
del temp_t2_v_2
temp_t2_v_3 = lib.einsum(
'lned,lmbd->nemb',t2_1[kl,kn,ke], t2_1[kl,km,kb].conj(),optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('nemb,neam->ab',
temp_t2_v_3, eris_ovvo[kn,ke,ka], optimize=True)
M_ab[ka] += 0.5 * 2. * lib.einsum('nemb,nmae->ab',
temp_t2_v_3, eris_oovv[kn,km,ka], optimize=True)
M_ab[ka] += 0.5 * 2. * lib.einsum('nema,nmbe->ab',
temp_t2_v_3, eris_oovv[kn,km,kb], optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('nema,nebm->ab',
temp_t2_v_3, eris_ovvo[kn,ke,kb], optimize=True)
del temp_t2_v_3
kl = kconserv[ke,kn,kd]
km = kconserv[ke,kl,kd]
temp_t2_v_8 = lib.einsum(
'lned,mled->mn',t2_1[kl,kn,ke], t2_1[km,kl,ke].conj(),optimize=True)
M_ab[ka] += 2.* lib.einsum('mn,nmab->ab',temp_t2_v_8,
eris_oovv[kn,km,ka], optimize=True)
M_ab[ka] -= lib.einsum('mn,nbam->ab', temp_t2_v_8,
eris_ovvo[kn,kb,ka], optimize=True)
del temp_t2_v_8
temp_t2_v_9 = lib.einsum(
'nled,mled->mn',t2_1[kn,kl,ke], t2_1[km,kl,ke].conj(),optimize=True)
M_ab[ka] -= 4. * lib.einsum('mn,nmab->ab',temp_t2_v_9,
eris_oovv[kn,km,ka], optimize=True)
M_ab[ka] += 2. * lib.einsum('mn,nbam->ab',temp_t2_v_9,
eris_ovvo[kn,kb,ka], optimize=True)
del temp_t2_v_9
for km in range(nkpts):
for kl in range(nkpts):
kf = kconserv[km,kl,ka]
temp_t2 = adc.imds.t2_1_vvvv[:]
t2_1_mla = adc.t2[0][km,kl,ka]
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('mlaf,mlbf->ab',t2_1_mla,
temp_t2[km,kl,kb].conj(), optimize=True)
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('mlaf,lmbf->ab',t2_1_mla,
temp_t2[kl,km,kb].conj(), optimize=True)
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('mlaf,mlfb->ab',t2_1_mla,
temp_t2[km,kl,kf].conj(), optimize=True)
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('mlaf,lmfb->ab',t2_1_mla,
temp_t2[kl,km,kf].conj(), optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('mlaf,mlbf->ab',
t2_1_mla, temp_t2[km,kl,kb].conj(), optimize=True)
del t2_1_mla
t2_1_lma = adc.t2[0][kl,km,ka]
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('lmaf,mlbf->ab',t2_1_lma,
temp_t2[km,kl,kb].conj(), optimize=True)
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('lmaf,lmbf->ab',t2_1_lma,
temp_t2[kl,km,kb].conj(), optimize=True)
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('lmaf,mlfb->ab',t2_1_lma,
temp_t2[km,kl,kf].conj(), optimize=True)
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('lmaf,lmfb->ab',t2_1_lma,
temp_t2[kl,km,kf].conj(), optimize=True)
del t2_1_lma
kd = kconserv[km,ka,kl]
t2_1_mlb = adc.t2[0][km,kl,kb]
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('mlad,mlbd->ab', temp_t2[km,
kl,ka].conj(), t2_1_mlb, optimize=True)
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('lmad,mlbd->ab', temp_t2[kl,
km,ka].conj(), t2_1_mlb, optimize=True)
M_ab[ka] -= 0.5 * lib.einsum('mlad,mlbd->ab',
temp_t2[km,kl,ka].conj(), t2_1_mlb, optimize=True)
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('lmad,mlbd->ab', temp_t2[kl,
km,ka].conj(), t2_1_mlb, optimize=True)
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('mlad,mlbd->ab', temp_t2[km,
kl,ka].conj(), t2_1_mlb, optimize=True)
del t2_1_mlb
t2_1_lmb = adc.t2[0][kl,km,kb]
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('mlad,lmbd->ab', temp_t2[km,
kl,ka].conj(), t2_1_lmb, optimize=True)
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('lmad,lmbd->ab', temp_t2[kl,
km,ka].conj(), t2_1_lmb, optimize=True)
M_ab[ka] -= 0.5 * 0.25* \
lib.einsum('lmad,lmbd->ab', temp_t2[kl,
km,ka].conj(), t2_1_lmb, optimize=True)
M_ab[ka] += 0.5 * 0.25* \
lib.einsum('mlad,lmbd->ab', temp_t2[km,
kl,ka].conj(), t2_1_lmb, optimize=True)
del temp_t2
del t2_1_lmb
for kd in range(nkpts):
kf = kconserv[km,kd,kl]
ke = kconserv[kb,ka,kf]
if isinstance(eris.vvvv, type(None)):
chnk_size = adc.chnk_size
if chnk_size > nvir:
chnk_size = nvir
a = 0
for p in range(0,nvir,chnk_size):
eris_vvvv = dfadc.get_vvvv_df(
adc, eris.Lvv[kb,ka], eris.Lvv[ke,kf], p, chnk_size)/nkpts
k = eris_vvvv.shape[0]
M_ab[ka,a:a+k] -= lib.einsum('mldf,mled,aebf->ab',t2_1[km,kl,kd],
t2_1[km,kl,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] += lib.einsum('mldf,lmed,aebf->ab',t2_1[km,kl,kd],
t2_1[kl,km,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] += lib.einsum('lmdf,mled,aebf->ab',t2_1[kl,km,kd],
t2_1[km,kl,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] -= lib.einsum('lmdf,lmed,aebf->ab',t2_1[kl,km,kd],
t2_1[kl,km,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] += 2.*lib.einsum(
'mlfd,mled,aebf->ab',t2_1[km,kl,kf], t2_1[km,kl,ke].conj(), eris_vvvv,
optimize=True)
del eris_vvvv
eris_vvvv = dfadc.get_vvvv_df(
adc, eris.Lvv[kb,kf], eris.Lvv[ke,ka], p, chnk_size)/nkpts
M_ab[ka,a:a+k] += 0.5*lib.einsum(
'mldf,mled,aefb->ab',t2_1[km,kl,kd], t2_1[km,kl,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] -= 0.5*lib.einsum(
'mldf,lmed,aefb->ab',t2_1[km,kl,kd], t2_1[kl,km,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] -= 0.5*lib.einsum(
'lmdf,mled,aefb->ab',t2_1[kl,km,kd], t2_1[km,kl,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] += 0.5*lib.einsum(
'lmdf,lmed,aefb->ab',t2_1[kl,km,kd], t2_1[kl,km,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] -= lib.einsum('mlfd,mled,aefb->ab',t2_1[km,kl,kf],
t2_1[km,kl,ke].conj(), eris_vvvv, optimize=True)
del eris_vvvv
a += k
elif isinstance(eris.vvvv, np.ndarray):
eris_vvvv = eris.vvvv
M_ab[ka] -= lib.einsum('mldf,mled,aebf->ab',t2_1[km,kl,kd],
t2_1[km,kl,ke].conj(), eris_vvvv[ka,ke,kb], optimize=True)
M_ab[ka] += lib.einsum('mldf,lmed,aebf->ab',t2_1[km,kl,kd],
t2_1[kl,km,ke].conj(), eris_vvvv[ka,ke,kb], optimize=True)
M_ab[ka] += lib.einsum('lmdf,mled,aebf->ab',t2_1[kl,km,kd],
t2_1[km,kl,ke].conj(), eris_vvvv[ka,ke,kb], optimize=True)
M_ab[ka] -= lib.einsum('lmdf,lmed,aebf->ab',t2_1[kl,km,kd],
t2_1[kl,km,ke].conj(), eris_vvvv[ka,ke,kb], optimize=True)
M_ab[ka] += 2.*lib.einsum('mlfd,mled,aebf->ab',t2_1[km,kl,kf],
t2_1[km,kl,ke].conj(), eris_vvvv[ka,ke,kb], optimize=True)
M_ab[ka] += 0.5*lib.einsum('mldf,mled,aefb->ab',t2_1[km,kl,kd],
t2_1[km,kl,ke].conj(), eris_vvvv[ka,ke,kf], optimize=True)
M_ab[ka] -= 0.5*lib.einsum('mldf,lmed,aefb->ab',t2_1[km,kl,kd],
t2_1[kl,km,ke].conj(), eris_vvvv[ka,ke,kf], optimize=True)
M_ab[ka] -= 0.5*lib.einsum('lmdf,mled,aefb->ab',t2_1[kl,km,kd],
t2_1[km,kl,ke].conj(), eris_vvvv[ka,ke,kf], optimize=True)
M_ab[ka] += 0.5*lib.einsum('lmdf,lmed,aefb->ab',t2_1[kl,km,kd],
t2_1[kl,km,ke].conj(), eris_vvvv[ka,ke,kf], optimize=True)
M_ab[ka] -= lib.einsum('mlfd,mled,aefb->ab',t2_1[km,kl,kf],
t2_1[km,kl,ke].conj(), eris_vvvv[ka,ke,kf], optimize=True)
else :
chnk_size = adc.chnk_size
if chnk_size > nvir:
chnk_size = nvir
a = 0
for p in range(0,nvir,chnk_size):
eris_vvvv = eris.vvvv[kb,ke,ka,p:p+chnk_size]
k = eris_vvvv.shape[0]
M_ab[ka,a:a+k] -= lib.einsum('mldf,mled,aebf->ab',t2_1[km,kl,kd],
t2_1[km,kl,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] += lib.einsum('mldf,lmed,aebf->ab',t2_1[km,kl,kd],
t2_1[kl,km,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] += lib.einsum('lmdf,mled,aebf->ab',t2_1[kl,km,kd],
t2_1[km,kl,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] -= lib.einsum('lmdf,lmed,aebf->ab',t2_1[kl,km,kd],
t2_1[kl,km,ke].conj(), eris_vvvv, optimize=True)
M_ab[ka,a:a+k] += 2.*lib.einsum(
'mlfd,mled,aebf->ab',t2_1[km,kl,kf], t2_1[km,kl,ke].conj(), eris_vvvv,
optimize=True)
del eris_vvvv
eris_vvvv = eris.vvvv[ka,ke,kf,p:p+chnk_size]
M_ab[ka,a:a+k] += 0.5*lib.einsum(
'mldf,mled,aefb->ab',t2_1[km,kl,kd], t2_1[km,kl,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] -= 0.5*lib.einsum(
'mldf,lmed,aefb->ab',t2_1[km,kl,kd], t2_1[kl,km,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] -= 0.5*lib.einsum(
'lmdf,mled,aefb->ab',t2_1[kl,km,kd], t2_1[km,kl,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] += 0.5*lib.einsum(
'lmdf,lmed,aefb->ab',t2_1[kl,km,kd], t2_1[kl,km,ke].conj(), eris_vvvv,
optimize=True)
M_ab[ka,a:a+k] -= lib.einsum('mlfd,mled,aefb->ab',t2_1[km,kl,kf],
t2_1[km,kl,ke].conj(), eris_vvvv, optimize=True)
del eris_vvvv
a += k
cput0 = log.timer_debug1("Completed M_ab ADC(3) calculation", *cput0)
return M_ab
[docs]
def get_diag(adc,kshift,M_ab=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_ab is None:
M_ab = adc.get_imds()
nkpts = adc.nkpts
kconserv = adc.khelper.kconserv
nocc = adc.nocc
nvir = adc.nmo - adc.nocc
n_singles = nvir
n_doubles = nkpts * nkpts * nocc * nvir * nvir
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
nmo = adc.nmo
nvir = nmo - 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,nocc*nvir*nvir),dtype=np.complex128)
# Compute precond in h1-h1 block
M_ab_diag = np.diagonal(M_ab[kshift])
diag[s1:f1] = M_ab_diag.copy()
# Compute precond in 2p1h-2p1h block
for kj in range(nkpts):
for ka in range(nkpts):
kb = kconserv[kshift,ka,kj]
d_ab = e_vir[ka][:,None] + e_vir[kb]
d_i = e_occ[kj][:,None]
D_n = -d_i + d_ab.reshape(-1)
doubles[kj,ka] += D_n.reshape(-1)
diag[s2:f2] = doubles.reshape(-1)
log.timer_debug1("Completed ea_diag calculation")
return diag
[docs]
def matvec(adc, kshift, M_ab=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
nvir = adc.nmo - adc.nocc
n_singles = nvir
n_doubles = nkpts * nkpts * nocc * nvir * nvir
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_ab is None:
M_ab = 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,nocc,nvir,nvir)
s2 = np.zeros((nkpts,nkpts,nocc,nvir,nvir), dtype=np.complex128)
cell = adc.cell
kpts = adc.kpts
madelung = tools.madelung(cell, kpts)
############ ADC(2) ij block ############################
s1 = lib.einsum('ab,b->a',M_ab[kshift],r1)
########### ADC(2) coupling blocks #########################
for kb in range(nkpts):
for kc in range(nkpts):
ki = kconserv[kb,kshift, 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[kshift,kb], p, chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
s1 += 2. * lib.einsum('icab,ibc->a', eris_ovvv.conj(),
r2[ki,kb,a:a+k], optimize=True)
s2[ki,kb,a:a+k] += lib.einsum('icab,a->ibc', eris_ovvv, r1, optimize=True)
del eris_ovvv
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[ki,kb], eris.Lvv[kshift,kc], p, chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
s1 -= lib.einsum('ibac,ibc->a', eris_ovvv.conj(),
r2[ki,kb,a:a+k], optimize=True)
del eris_ovvv
a += k
else :
eris_ovvv = eris.ovvv[:]
s1 += 2. * lib.einsum('icab,ibc->a',
eris_ovvv[ki,kc,kshift].conj(), r2[ki,kb], optimize=True)
s2[ki,kb] += lib.einsum('icab,a->ibc', eris_ovvv[ki,
kc,kshift], r1, optimize=True)
del eris_ovvv
######### ########## ADC(2) ajk - bil block ############################
s2[ki, kb] -= lib.einsum('i,ibc->ibc', e_occ[ki], r2[ki, kb])
s2[ki, kb] += lib.einsum('b,ibc->ibc', e_vir[kb], r2[ki, kb])
s2[ki, kb] += lib.einsum('c,ibc->ibc', e_vir[kc], r2[ki, kb])
################ ADC(3) ajk - bil block ############################
if (method == "adc(2)-x" or method == "adc(3)"):
eris_oovv = eris.oovv
eris_ovvo = eris.ovvo
for kx in range(nkpts):
for ky in range(nkpts):
ki = kconserv[ky,kshift, kx]
for kz in range(nkpts):
kw = kconserv[kx, kz, ky]
if isinstance(eris.vvvv, np.ndarray):
eris_vvvv = eris.vvvv.reshape(nkpts,nkpts,nkpts,nvir*nvir,nvir*nvir)
r2_1 = r2.reshape(nkpts,nkpts,nocc,nvir*nvir)
s2[ki, kx] += np.dot(r2_1[ki,kw],eris_vvvv[kx,ky,
kw].T.conj()).reshape(nocc,nvir,nvir)
elif isinstance(eris.vvvv, type(None)):
s2[ki,kx] += ea_contract_r_vvvv(adc,r2[ki,kw],eris.Lvv,kx,ky,kw)
else :
s2[ki,kx] += ea_contract_r_vvvv(adc,r2[ki,kw],eris.vvvv,kx,ky,kw)
for kj in range(nkpts):
kz = kconserv[ky,ki,kj]
s2[ki,kx] -= 0.5*lib.einsum('iyzj,jzx->ixy',
eris_ovvo[ki,ky,kz],r2[kj,kz],optimize=True)
s2[ki,kx] += lib.einsum('iyzj,jxz->ixy',eris_ovvo[ki,
ky,kz],r2[kj,kx],optimize=True)
s2[ki,kx] -= 0.5*lib.einsum('ijzy,jxz->ixy',
eris_oovv[ki,kj,kz],r2[kj,kx],optimize=True)
kz = kconserv[kj,ki,kx]
s2[ki,kx] -= 0.5*lib.einsum('ijzx,jzy->ixy',
eris_oovv[ki,kj,kz],r2[kj,kz],optimize=True)
kw = kconserv[kj,ki,kx]
s2[ki,kx] -= 0.5*lib.einsum('ijwx,jwy->ixy',
eris_oovv[ki,kj,kw],r2[kj,kw],optimize=True)
kw = kconserv[kj,ki,ky]
s2[ki,kx] -= 0.5*lib.einsum('ijwy,jxw->ixy',
eris_oovv[ki,kj,kw],r2[kj,kx],optimize=True)
s2[ki,kx] += lib.einsum('iywj,jxw->ixy',eris_ovvo[ki,
ky,kw],r2[kj,kx],optimize=True)
s2[ki,kx] -= 0.5*lib.einsum('iywj,jwx->ixy',
eris_ovvo[ki,ky,kw],r2[kj,kw],optimize=True)
if adc.exxdiv is not None:
s2 += -madelung * r2
if (method == "adc(3)"):
eris_ovoo = eris.ovoo
################ ADC(3) a - ibc block and ibc-a coupling blocks ########################
t2_1 = adc.t2[0]
for kz in range(nkpts):
for kw in range(nkpts):
kj = kconserv[kw, kshift, kz]
for kl in range(nkpts):
km = kconserv[kw, kl, kz]
t2_1_lmz = adc.t2[0][kl,km,kz]
ka = kconserv[km, kj, kl]
temp_1 = lib.einsum('lmzw,jzw->jlm',t2_1_lmz,r2[kj,kz])
temp = 0.25 * lib.einsum('lmzw,jzw->jlm',t2_1_lmz,r2[kj,kz])
temp -= 0.25 * lib.einsum('lmzw,jwz->jlm',t2_1_lmz,r2[kj,kw])
del t2_1_lmz
t2_1_mlz = adc.t2[0][km,kl,kz]
temp -= 0.25 * lib.einsum('mlzw,jzw->jlm',t2_1_mlz,r2[kj,kz])
temp += 0.25 * lib.einsum('mlzw,jwz->jlm',t2_1_mlz,r2[kj,kw])
del t2_1_mlz
s1 += lib.einsum('jlm,lamj->a',temp, eris_ovoo[kl,ka,km], optimize=True)
s1 -= lib.einsum('jlm,malj->a',temp, eris_ovoo[km,ka,kl], optimize=True)
s1 += lib.einsum('jlm,lamj->a',temp_1, eris_ovoo[kl,ka,km], optimize=True)
del temp
del temp_1
for kx in range(nkpts):
for ky in range(nkpts):
ki = kconserv[ky, kshift, kx]
for kl in range(nkpts):
km = kconserv[kx, kl, ky]
kb = kconserv[km,ki,kl]
temp = lib.einsum(
'b,lbmi->lmi',r1,eris_ovoo[kl,kb,km].conj(), optimize=True)
s2[ki,kx] += lib.einsum('lmi,lmxy->ixy',temp,
t2_1[kl,km,kx].conj(), optimize=True)
del temp
for kz in range(nkpts):
for kw in range(nkpts):
kj = kconserv[kz, kshift, kw]
for kl in range(nkpts):
kd = kconserv[kj, kw, kl]
t2_1_jlw = adc.t2[0][kj,kl,kw]
temp_s_a = lib.einsum('jlwd,jzw->lzd',t2_1_jlw,r2[kj,kz],optimize=True)
temp_s_a -= lib.einsum('jlwd,jwz->lzd',t2_1_jlw,r2[kj,kw],optimize=True)
temp_t2_r2_1 = lib.einsum('jlwd,jzw->lzd',t2_1_jlw,r2[kj,kz],optimize=True)
temp_t2_r2_1 -= lib.einsum('jlwd,jwz->lzd',t2_1_jlw,r2[kj,kw],optimize=True)
temp_t2_r2_1 += lib.einsum('jlwd,jzw->lzd',t2_1_jlw,r2[kj,kz],optimize=True)
del t2_1_jlw
t2_1_ljw = adc.t2[0][kl,kj,kw]
temp_s_a -= lib.einsum('ljwd,jzw->lzd',t2_1_ljw,r2[kj,kz],optimize=True)
temp_s_a += lib.einsum('ljwd,jwz->lzd',t2_1_ljw,r2[kj,kw],optimize=True)
temp_s_a += lib.einsum('ljdw,jzw->lzd',
t2_1[kl,kj,kd],r2[kj,kz],optimize=True)
temp_t2_r2_1 -= lib.einsum('ljwd,jzw->lzd',t2_1_ljw,r2[kj,kz],optimize=True)
del t2_1_ljw
temp_t2_r2_4 = lib.einsum(
'jldw,jwz->lzd',t2_1[kj,kl,kd],r2[kj,kw], optimize=True)
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):
ka = kconserv[kz, kd, kl]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kd], eris.Lvv[kz,ka], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
s1 += 0.5*lib.einsum('lzd,ldza->a',
temp_s_a[a:a+k],eris_ovvv,optimize=True)
s1 += 0.5*lib.einsum('lzd,ldza->a',
temp_t2_r2_1[a:a+k],eris_ovvv,optimize=True)
del eris_ovvv
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,ka], eris.Lvv[kz,kd], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
s1 -= 0.5*lib.einsum('lzd,lazd->a',
temp_s_a[a:a+k],eris_ovvv,optimize=True)
s1 -= 0.5*lib.einsum('lzd,lazd->a',
temp_t2_r2_4[a:a+k],eris_ovvv,optimize=True)
del eris_ovvv
a += k
else :
ka = kconserv[kz, kd, kl]
eris_ovvv = eris.ovvv[:]
s1 += 0.5*lib.einsum('lzd,ldza->a',temp_s_a,
eris_ovvv[kl,kd,kz],optimize=True)
s1 += 0.5*lib.einsum('lzd,ldza->a',temp_t2_r2_1,
eris_ovvv[kl,kd,kz],optimize=True)
s1 -= 0.5*lib.einsum('lzd,lazd->a',temp_s_a,
eris_ovvv[kl,ka,kz],optimize=True)
s1 -= 0.5*lib.einsum('lzd,lazd->a',temp_t2_r2_4,
eris_ovvv[kl,ka,kz],optimize=True)
del eris_ovvv
del temp_s_a
del temp_t2_r2_1
del temp_t2_r2_4
for kz in range(nkpts):
for kw in range(nkpts):
kj = kconserv[kz, kshift, kw]
for kl in range(nkpts):
kd = kconserv[kj, kz, kl]
t2_1_jlz = adc.t2[0][kj,kl,kz]
temp_s_a_1 = -lib.einsum('jlzd,jwz->lwd',
t2_1_jlz,r2[kj,kw],optimize=True)
temp_s_a_1 += lib.einsum('jlzd,jzw->lwd',
t2_1_jlz,r2[kj,kz],optimize=True)
temp_t2_r2_2 = -lib.einsum('jlzd,jwz->lwd',
t2_1_jlz,r2[kj,kw],optimize=True)
temp_t2_r2_2 += lib.einsum('jlzd,jzw->lwd',
t2_1_jlz,r2[kj,kz],optimize=True)
temp_t2_r2_2 -= lib.einsum('jlzd,jwz->lwd',
t2_1_jlz,r2[kj,kw],optimize=True)
del t2_1_jlz
t2_1_ljz = adc.t2[0][kl,kj,kz]
temp_s_a_1 += lib.einsum('ljzd,jwz->lwd',t2_1_ljz,r2[kj,kw],optimize=True)
temp_s_a_1 -= lib.einsum('ljzd,jzw->lwd',t2_1_ljz,r2[kj,kz],optimize=True)
temp_s_a_1 -= lib.einsum('ljdz,jwz->lwd',
t2_1[kl,kj,kd],r2[kj,kw],optimize=True)
temp_t2_r2_2 += lib.einsum('ljzd,jwz->lwd',t2_1_ljz,r2[kj,kw],optimize=True)
temp_t2_r2_3 = -lib.einsum('ljzd,jzw->lwd',t2_1_ljz,r2[kj,kz],optimize=True)
del t2_1_ljz
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):
ka = kconserv[kw, kd, kl]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kd], eris.Lvv[kw,ka], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
s1 -= 0.5*lib.einsum('lwd,ldwa->a',
temp_s_a_1[a:a+k],eris_ovvv,optimize=True)
s1 -= 0.5*lib.einsum('lwd,ldwa->a',
temp_t2_r2_2[a:a+k],eris_ovvv,optimize=True)
del eris_ovvv
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,ka], eris.Lvv[kw,kd], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
s1 += 0.5*lib.einsum('lwd,lawd->a',
temp_s_a_1[a:a+k],eris_ovvv,optimize=True)
s1 += 0.5*lib.einsum('lwd,lawd->a',
temp_t2_r2_3[a:a+k],eris_ovvv,optimize=True)
del eris_ovvv
a += k
else :
ka = kconserv[kw, kd, kl]
eris_ovvv = eris.ovvv[:]
s1 -= 0.5*lib.einsum('lwd,ldwa->a',temp_s_a_1,
eris_ovvv[kl,kd,kw],optimize=True)
s1 += 0.5*lib.einsum('lwd,lawd->a',temp_s_a_1,
eris_ovvv[kl,ka,kw],optimize=True)
s1 -= 0.5*lib.einsum('lwd,ldwa->a',temp_t2_r2_2,
eris_ovvv[kl,kd,kw],optimize=True)
s1 += 0.5*lib.einsum('lwd,lawd->a',temp_t2_r2_3,
eris_ovvv[kl,ka,kw],optimize=True)
del eris_ovvv
del temp_s_a_1
del temp_t2_r2_2
del temp_t2_r2_3
for kx in range(nkpts):
for ky in range(nkpts):
ki = kconserv[ky,kshift,kx]
for kl in range(nkpts):
temp = np.zeros((nocc,nvir,nvir),dtype=eris.oooo.dtype)
temp_1_1 = np.zeros((nocc,nvir,nvir),dtype=eris.oooo.dtype)
temp_2_1 = np.zeros((nocc,nvir,nvir),dtype=eris.oooo.dtype)
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):
kd = kconserv[kl, kshift, kx]
kb = kconserv[kl,kd,kx]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kd], eris.Lvv[kx,kb], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
k = eris_ovvv.shape[0]
temp_1_1[a:a+k] += lib.einsum('ldxb,b->lxd',
eris_ovvv,r1,optimize=True)
temp_2_1[a:a+k] += lib.einsum('ldxb,b->lxd',
eris_ovvv,r1,optimize=True)
del eris_ovvv
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kb], eris.Lvv[kx,kd], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
temp_1_1[a:a+k] -= lib.einsum('lbxd,b->lxd',
eris_ovvv,r1,optimize=True)
del eris_ovvv
kd = kconserv[kl, kshift, ky]
kb = kconserv[ky,kd,kl]
eris_ovvv = dfadc.get_ovvv_df(
adc, eris.Lov[kl,kb], eris.Lvv[ky,kd], p,
chnk_size).reshape(-1,nvir,nvir,nvir)/nkpts
temp[a:a+k] -= lib.einsum('lbyd,b->lyd', eris_ovvv,r1,optimize=True)
del eris_ovvv
a += k
else :
kd = kconserv[ki, ky, kl]
kb = kconserv[kl,kd,kx]
eris_ovvv = eris.ovvv[:]
temp_1_1 += lib.einsum('ldxb,b->lxd',
eris_ovvv[kl,kd,kx],r1,optimize=True)
temp_1_1 -= lib.einsum('lbxd,b->lxd',
eris_ovvv[kl,kb,kx],r1,optimize=True)
temp_2_1 += lib.einsum('ldxb,b->lxd',
eris_ovvv[kl,kd,kx],r1,optimize=True)
kd = kconserv[kl, kshift, ky]
kb = kconserv[ky,kd,kl]
temp -= lib.einsum('lbyd,b->lyd', eris_ovvv[kl,kb,ky],r1,optimize=True)
del eris_ovvv
kd = kconserv[kl,ky,ki]
s2[ki,kx] += lib.einsum('lxd,lidy->ixy',temp_1_1.conj(),
t2_1[kl,ki,kd].conj(),optimize=True)
s2[ki,kx] += lib.einsum('lxd,ilyd->ixy',temp_2_1.conj(),
t2_1[ki,kl,ky].conj(),optimize=True)
s2[ki,kx] -= lib.einsum('lxd,ildy->ixy',temp_2_1.conj(),
t2_1[ki,kl,kd].conj(),optimize=True)
kd = kconserv[kl,kx,ki]
s2[ki,kx] += lib.einsum('lyd,lixd->ixy',temp.conj(),
t2_1[kl,ki,kx].conj(),optimize=True)
del temp
del temp_1_1
del temp_2_1
s2 = s2.reshape(-1)
s = np.hstack((s1,s2))
del s1
del s2
cput0 = log.timer_debug1("completed sigma vector calculation", *cput0)
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_vir = np.identity(nvir)
T1 = np.zeros((nvir),dtype=np.complex128)
T2 = np.zeros((nkpts,nkpts,nocc,nvir,nvir), dtype=np.complex128)
######## ADC(2) 1h part ############################################
if orb < nocc:
if (adc.approx_trans_moments is False or adc.method == "adc(3)"):
t1_2 = adc.t1[0]
T1 -= t1_2[kshift][orb,:]
for kj in range(nkpts):
for ka in range(nkpts):
kb = adc.khelper.kconserv[kj, ka, kshift]
ki = adc.khelper.kconserv[ka, kj, kb]
t2_1_t= t2_1[ki,kj,ka].transpose(1,0,2,3)
T2[kj,ka] -= t2_1_t[:,orb,:,:].conj()
else:
T1 += idn_vir[(orb-nocc), :]
for kk in range(nkpts):
for kc in range(nkpts):
kl = adc.khelper.kconserv[kc, kk, kshift]
ka = adc.khelper.kconserv[kc, kl, kk]
T1 -= 0.25* \
lib.einsum('klc,klac->a',t2_1[kk,kl,kshift][:,:,
(orb-nocc),:], t2_1[kk,kl,ka].conj(), optimize=True)
T1 -= 0.25* \
lib.einsum('lkc,lkac->a',t2_1[kl,kk,kshift][:,:,
(orb-nocc),:], t2_1[kl,kk,ka].conj(), optimize=True)
T1 -= 0.25* \
lib.einsum('klc,klac->a',t2_1[kk,kl,kshift][:,:,
(orb-nocc),:], t2_1[kk,kl,ka].conj(), optimize=True)
T1 += 0.25* \
lib.einsum('lkc,klac->a',t2_1[kl,kk,kshift][:,:,
(orb-nocc),:], t2_1[kk,kl,ka].conj(), optimize=True)
T1 += 0.25* \
lib.einsum('klc,lkac->a',t2_1[kk,kl,kshift][:,:,
(orb-nocc),:], t2_1[kl,kk,ka].conj(), optimize=True)
T1 -= 0.25* \
lib.einsum('lkc,lkac->a',t2_1[kl,kk,kshift][:,:,
(orb-nocc),:], t2_1[kl,kk,ka].conj(), optimize=True)
######### ADC(3) 2p-1h 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 kj in range(nkpts):
for ka in range(nkpts):
kb = adc.khelper.kconserv[kj, ka, kshift]
ki = adc.khelper.kconserv[ka, kj, kb]
t2_2_t = t2_2[ki,kj,ka].conj().transpose(1,0,2,3)
T2[kj,ka] -= t2_2_t[:,orb,:,:].conj()
########### ADC(3) 1p part ############################################
if(method=='adc(3)'):
if orb < nocc:
for kk in range(nkpts):
for kc in range(nkpts):
ka = adc.khelper.kconserv[kk, kc, kshift]
T1 += 0.5*lib.einsum('kac,ck->a',
t2_1[kk,kshift,kc][:,orb,:,:], t1_2[kc].T,optimize=True)
T1 -= 0.5*lib.einsum('kac,ck->a',
t2_1[kshift,kk,ka][orb,:,:,:], t1_2[kc].T,optimize=True)
T1 -= 0.5*lib.einsum('kac,ck->a',
t2_1[kshift,kk,ka][orb,:,:,:], t1_2[kc].T,optimize=True)
else:
for kk in range(nkpts):
for kc in range(nkpts):
kl = adc.khelper.kconserv[kk, kc, kshift]
ka = adc.khelper.kconserv[kl, kc, kk]
T1 -= 0.25* \
lib.einsum('klc,klac->a',t2_1[kk,kl,kshift][:,:,
(orb-nocc),:], t2_2[kk,kl,ka].conj(), optimize=True)
T1 -= 0.25* \
lib.einsum('lkc,lkac->a',t2_1[kl,kk,kshift][:,:,
(orb-nocc),:], t2_2[kl,kk,ka].conj(), optimize=True)
T1 -= 0.25* \
lib.einsum('klc,klac->a',t2_1[kk,kl,kshift][:,:,
(orb-nocc),:], t2_2[kk,kl,ka].conj(), optimize=True)
T1 += 0.25* \
lib.einsum('klc,lkac->a',t2_1[kk,kl,kshift][:,:,
(orb-nocc),:], t2_2[kl,kk,ka].conj(), optimize=True)
T1 += 0.25* \
lib.einsum('lkc,klac->a',t2_1[kl,kk,kshift][:,:,
(orb-nocc),:], t2_2[kk,kl,ka].conj(), optimize=True)
T1 -= 0.25* \
lib.einsum('lkc,lkac->a',t2_1[kl,kk,kshift][:,:,
(orb-nocc),:], t2_2[kl,kk,ka].conj(), optimize=True)
T1 -= 0.25* \
lib.einsum('klac,klc->a',t2_1[kk,kl,ka].conj(),
t2_2[kk,kl,kshift][:,:,(orb-nocc),:],optimize=True)
T1 -= 0.25* \
lib.einsum('lkac,lkc->a',t2_1[kl,kk,ka].conj(),
t2_2[kl,kk,kshift][:,:,(orb-nocc),:],optimize=True)
T1 -= 0.25* \
lib.einsum('klac,klc->a',t2_1[kk,kl,ka].conj(),
t2_2[kk,kl,kshift][:,:,(orb-nocc),:],optimize=True)
T1 += 0.25* \
lib.einsum('klac,lkc->a',t2_1[kk,kl,ka].conj(),
t2_2[kl,kk,kshift][:,:,(orb-nocc),:],optimize=True)
T1 += 0.25* \
lib.einsum('lkac,klc->a',t2_1[kl,kk,ka].conj(),
t2_2[kk,kl,kshift][:,:,(orb-nocc),:],optimize=True)
T1 -= 0.25* \
lib.einsum('lkac,lkc->a',t2_1[kl,kk,ka].conj(),
t2_2[kl,kk,kshift][:,:,(orb-nocc),:],optimize=True)
del t2_2
del t2_1
for ka in range(nkpts):
for kb in range(nkpts):
ki = adc.khelper.kconserv[kb,kshift, ka]
T2[ki,ka] += T2[ki,ka] - T2[ki,kb].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]
nvir = adc.nmo - adc.nocc
n_singles = nvir
for I in range(U.shape[1]):
U1 = U[:n_singles,I]
U2 = U[n_singles:,I].reshape(nkpts,nkpts,nocc,nvir,nvir)
UdotU = np.dot(U1.conj().ravel(),U1.ravel())
for ka in range(nkpts):
for kb in range(nkpts):
ki = adc.khelper.kconserv[kb,kshift, ka]
UdotU += 2.*np.dot(U2[ki,ka].conj().ravel(), U2[ki,ka].ravel()) - \
np.dot(U2[ki,ka].conj().ravel(),
U2[ki,kb].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 RADCEA(kadc_rhf.RADC):
'''restricted ADC for EA 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_ea : float or list of floats
EA 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_ea : array
Eigenvectors for each EA transition.
p_ea : float
Spectroscopic amplitudes for each EA 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
[docs]
def ea_contract_r_vvvv(adc,r2,vvvv,ka,kb,kc):
nocc = r2.shape[0]
nvir = r2.shape[1]
nkpts = adc.nkpts
kconserv = adc.khelper.kconserv
kd = kconserv[ka, kc, kb]
r2 = np.ascontiguousarray(r2.reshape(nocc,-1))
r2_vvvv = np.zeros((nvir,nvir,nocc),dtype=r2.dtype)
chnk_size = adc.chnk_size
if chnk_size > nvir:
chnk_size = nvir
a = 0
if isinstance(vvvv, np.ndarray):
vv1 = vvvv[ka,kc]
vv2 = vvvv[kb,kd]
for p in range(0,nvir,chnk_size):
vvvv_p = dfadc.get_vvvv_df(adc, vv1, vv2, p, chnk_size)/nkpts
k = vvvv_p.shape[0]
vvvv_p = vvvv_p.reshape(-1,nvir*nvir)
r2_vvvv[a:a+k] += np.dot(vvvv_p.conj(),r2.T).reshape(-1,nvir,nocc)
del vvvv_p
a += k
else :
for p in range(0,nvir,chnk_size):
vvvv_p = vvvv[ka,kb,kc][p:p+chnk_size].reshape(-1,nvir*nvir)
k = vvvv_p.shape[0]
r2_vvvv[a:a+k] += np.dot(vvvv_p.conj(),r2.T).reshape(-1,nvir,nocc)
del vvvv_p
a += k
r2_vvvv = np.ascontiguousarray(r2_vvvv.transpose(2,0,1))
return r2_vvvv