#!/usr/bin/env python
# Copyright 2017-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.
#
# Authors: James D. McClain
# Mario Motta
# Yang Gao
# Qiming Sun <osirpt.sun@gmail.com>
# Jason Yu
#
import itertools
import numpy as np
from pyscf import lib
from pyscf.lib import logger
from pyscf.pbc.cc import eom_kccsd_ghf as eom_kgccsd
from pyscf.pbc.cc import kccsd
from pyscf.pbc.lib import kpts_helper
from pyscf.lib.parameters import LOOSE_ZERO_TOL, LARGE_DENOM # noqa
from pyscf.pbc.cc import kintermediates_uhf
from pyscf.pbc.mp.kump2 import (get_frozen_mask, get_nocc, get_nmo,
padded_mo_coeff, padding_k_idx) # noqa
einsum = lib.einsum
########################################
# EOM-IP-CCSD
########################################
[docs]
def amplitudes_to_vector_ip(r1, r2, kshift, kconserv):
r1a, r1b = r1
r2aaa, r2baa, r2abb, r2bbb = r2
nkpts = r2aaa.shape[0]
nocca, noccb = r1a.shape[0], r1b.shape[0]
nvira, nvirb = r2aaa.shape[-1], r2bbb.shape[-1]
# From symmetry for aaa and bbb terms, only store lower
# triangular part (ki,i) < (kj,j)
idxa, idya = np.tril_indices(nkpts*nocca, -1)
idxb, idyb = np.tril_indices(nkpts*noccb, -1)
r2aaa = r2aaa.transpose(0,2,1,3,4).reshape(nkpts*nocca,nkpts*nocca,nvira)
r2bbb = r2bbb.transpose(0,2,1,3,4).reshape(nkpts*noccb,nkpts*noccb,nvirb)
return np.hstack((r1a, r1b, r2aaa[idxa,idya].ravel(),
r2baa.ravel(), r2abb.ravel(),
r2bbb[idxb,idyb].ravel()))
[docs]
def vector_to_amplitudes_ip(vector, kshift, nkpts, nmo, nocc, kconserv):
nocca, noccb = nocc
nmoa, nmob = nmo
nvira, nvirb = nmoa-nocca, nmob-noccb
sizes = (nocca, noccb, (nkpts*nocca)*(nkpts*nocca-1)*nvira//2,
nkpts**2*noccb*nocca*nvira, nkpts**2*nocca*noccb*nvirb,
nkpts*noccb*(nkpts*noccb-1)*nvirb//2)
sections = np.cumsum(sizes[:-1])
r1a, r1b, r2a, r2baa, r2abb, r2b = np.split(vector, sections)
r2a = r2a.reshape(nkpts*nocca*(nkpts*nocca-1)//2,nvira)
r2b = r2b.reshape(nkpts*noccb*(nkpts*noccb-1)//2,nvirb)
idxa, idya = np.tril_indices(nkpts*nocca, -1)
idxb, idyb = np.tril_indices(nkpts*noccb, -1)
r2aaa = np.zeros((nkpts*nocca,nkpts*nocca,nvira), dtype=r2a.dtype)
r2aaa[idxa,idya] = r2a.copy()
r2aaa[idya,idxa] = -r2a.copy() # Fill in value : kj, j < ki, i
r2aaa = r2aaa.reshape(nkpts,nocca,nkpts,nocca,nvira)
r2aaa = r2aaa.transpose(0,2,1,3,4)
r2baa = r2baa.reshape(nkpts,nkpts,noccb,nocca,nvira).copy()
r2abb = r2abb.reshape(nkpts,nkpts,nocca,noccb,nvirb).copy()
r2bbb = np.zeros((nkpts*noccb,nkpts*noccb,nvirb), dtype=r2b.dtype)
r2bbb[idxb,idyb] = r2b.copy()
r2bbb[idyb,idxb] = -r2b.copy() # Fill in value : kj, j < ki, i
r2bbb = r2bbb.reshape(nkpts,noccb,nkpts,noccb,nvirb)
r2bbb = r2bbb.transpose(0,2,1,3,4)
r1 = (r1a.copy(), r1b.copy())
r2 = (r2aaa, r2baa, r2abb, r2bbb)
return r1, r2
[docs]
def ipccsd_matvec(eom, vector, kshift, imds=None, diag=None):
'''2ph operators are of the form s_{ij}^{ b}, i.e. 'jb' indices are coupled'''
if imds is None: imds = eom.make_imds()
t1, t2= imds.t1, imds.t2
t1a, t1b = t1
t2aa, t2ab, t2bb = t2
nocca, noccb, nvira, nvirb = t2ab.shape[3:]
nmoa, nmob = nocca + nvira, noccb + nvirb
kconserv = imds.kconserv
nkpts = eom.nkpts
r1, r2 = eom.vector_to_amplitudes(vector, kshift, nkpts, (nmoa, nmob), (nocca, noccb), kconserv)
#nocc = eom.nocc
#nmo = eom.nmo
#nvir = (nmo[0]-nocc[0], nmo[1]-nocc[1])
#nocca, noccb = nocc
#nvira, nvirb = nvir
#nkpts = eom.nkpts
#r1, r2 = eom.vector_to_amplitudes(vector, nkpts, nmo[0]+nmo[1], nocc[0]+nocc[1]) # spin
#spatial_r1, spatial_r2 = eom_kgccsd.spin2spatial_ip_doublet(r1, r2, kconserv, kshift, orbspin)
#imds = imds._imds
#t2aa, t2ab, t2bb = t2
# k-point spin orbital version of ipccsd
#Hr1 = -0.0*np.einsum('mi,m->i', imds.Foo[kshift], r1)
#Hr2 = np.zeros_like(r2)
r1a, r1b = r1
r2aaa, r2baa, r2abb, r2bbb = r2
#Foo term
# -\sum_{kk,k} U_{kk,k,ki,i} s_{kk,k}
Hr1a = -np.einsum('mi,m->i', imds.Foo[kshift], r1a)
Hr1b = -np.einsum('MI,M->I', imds.FOO[kshift], r1b)
#Fov term
# \sum_{kL,kD,L,D} U_{kL,kD,L,D} S_{ki,i,kL,L}^{kD,D} + \sum_{kl,kd,l,d} U_{kl,kd,l,d} S_{ki,i,kl,l}^{kd,d}
for km in range(nkpts):
Hr1a += einsum('me,mie->i', imds.Fov[km], r2aaa[km,kshift])
Hr1a -= einsum('ME,iME->i', imds.FOV[km], r2abb[kshift,km])
Hr1b += einsum('ME,MIE->I', imds.FOV[km], r2bbb[km,kshift])
Hr1b -= einsum('me,Ime->I', imds.Fov[km], r2baa[kshift,km])
#Wooov
# \sum_{kk,kl,kd,k,l,d} W_{kk,ki,kl,kd,k,i,l,d} s_{kl,kk,l,k}^{kd,d}
# \sum_{kk,kL,kD,k,L,D} W_{kk,ki,kL,kD,k,i,L,D} s_{kL,kk,L,k}^{kD,D}
for km in range(nkpts):
for kn in range(nkpts):
Hr1a += -0.5 * einsum('nime,mne->i', imds.Wooov[kn,kshift,km], r2aaa[km,kn])
Hr1b += einsum('NIme,Nme->I', imds.WOOov[kn,kshift,km], r2baa[kn,km])
Hr1b += -0.5 * einsum('NIME,MNE->I', imds.WOOOV[kn,kshift,km], r2bbb[km,kn])
Hr1a += einsum('niME,nME->i', imds.WooOV[kn,kshift,km], r2abb[kn,km])
dtype = np.result_type(Hr1a, *r2)
Hr2aaa = np.zeros((nkpts, nkpts, nocca, nocca, nvira), dtype=dtype)
Hr2baa = np.zeros((nkpts, nkpts, noccb, nocca, nvira), dtype=dtype)
Hr2abb = np.zeros((nkpts, nkpts, nocca, noccb, nvirb), dtype=dtype)
Hr2bbb = np.zeros((nkpts, nkpts, noccb, noccb, nvirb), dtype=dtype)
# Fvv term
# \sum_{kd,d} U_{kb,kd,b,d} S_{ki,kj,i,j}^{kd,d} = (\bar{H}S)_{ki,kj,i,j}^{kb,b}
# \sum_{kD,D} S_{ki,kJ,i,J}^{kD,D} U_{kB,kD,B,D} = (\bar{H}S)_{ki,kJ,i,J}^{kB,B}
for kb, ki in itertools.product(range(nkpts),repeat=2):
kj = kconserv[kshift,ki,kb]
Hr2aaa[ki,kj] += lib.einsum('be,ije->ijb', imds.Fvv[kb], r2aaa[ki,kj])
Hr2abb[ki,kj] += lib.einsum('BE,iJE->iJB', imds.FVV[kb], r2abb[ki,kj])
Hr2bbb[ki,kj] += lib.einsum('BE,IJE->IJB', imds.FVV[kb], r2bbb[ki,kj])
Hr2baa[ki,kj] += lib.einsum('be,Ije->Ijb', imds.Fvv[kb], r2baa[ki,kj])
# Foo term
# \sum_{kl,l} U_{kl,ki,l,i} s_{kl,kj,l,j}^{kb,b} = (\bar{H}S)_{ki,kj,i,j}^{kb,b}
# \sum_{kl,l} U_{kl,kj,l,j} S_{ki,kl,i,l}^{kb,b} = (\bar{H}S)_{ki,kj,i,j}^{kb,b}
# \sum_{kl,l} S_{kl,kJ,l,J}^{kB,B} U_{kl,ki,l,i} = (\bar{H}S)_{ki,kJ,i,J}^{kB,B}
# \sum_{KL,L} S_{ki,kL,i,L}^{kB,B} U_{kL,kJ,L,J} = (\bar{H}S)_{ki,kJ,i,J}^{kB,B}
for ki, kj in itertools.product(range(nkpts), repeat=2):
tmpa = lib.einsum('mi,mjb->ijb', imds.Foo[ki], r2aaa[ki,kj])
tmpb = lib.einsum('mj,mib->ijb', imds.Foo[kj], r2aaa[kj,ki])
Hr2aaa[ki,kj] -= tmpa - tmpb
Hr2abb[ki,kj] -= lib.einsum('mi,mJB->iJB', imds.Foo[ki], r2abb[ki,kj])
Hr2abb[ki,kj] -= lib.einsum('MJ,iMB->iJB', imds.FOO[kj], r2abb[ki,kj])
Hr2baa[ki,kj] -= lib.einsum('MI,Mjb->Ijb', imds.FOO[ki], r2baa[ki,kj])
Hr2baa[ki,kj] -= lib.einsum('mj,Imb->Ijb', imds.Foo[kj], r2baa[ki,kj])
tmpb = lib.einsum('MI,MJB->IJB', imds.FOO[ki], r2bbb[ki,kj])
tmpa = lib.einsum('MJ,MIB->IJB', imds.FOO[kj], r2bbb[kj,ki])
Hr2bbb[ki,kj] -= tmpb - tmpa
# Wovoo term
# \sum_{kk,k} W_{kk,kb,kj,ki,k,b,j,i} s_{kk,k} = (\bar{H}S)_{ki,kj,i,j}^{kb,b}
# \sum_{kk,k} W_{kk,kB,ki,kJ,k,B,i,J} S_{kk,k} = (\bar{H}S)_{ki,kJ,i,J}^{kB,B}
for ki, kj in itertools.product(range(nkpts), repeat=2):
kb = kconserv[ki, kshift, kj]
Hr2aaa[ki,kj] -= einsum('mjbi,m->ijb', imds.Woovo[kshift,kj,kb], r1a)
Hr2abb[ki,kj] += einsum('miBJ,m->iJB', imds.WooVO[kshift,ki,kb], r1a)
Hr2baa[ki,kj] += einsum('MIbj,M->Ijb', imds.WOOvo[kshift,ki,kb], r1b)
Hr2bbb[ki,kj] -= einsum('MJBI,M->IJB', imds.WOOVO[kshift,kj,kb], r1b)
# Woooo term
# \sum_{kk,kl,k,l} W_{kk,ki,kl,kj,k,i,l,j} S_{kk,kl,k,l}^{kb,b} = (\bar{H}S)_{ki,kj,i,j}^{kb,b}
# \sum_{kk,kL,k,L} W_{kk,kL,ki,kJ,k,L,i,J} S_{kk,kl,k,L}^{kB,B} = (\bar{H}S)_{ki,kJ,i,J}^{kB,B}
for ki, kj in itertools.product(range(nkpts), repeat=2):
kb = kconserv[ki, kshift, kj]
for kn in range(nkpts):
km = kconserv[kj, kn, ki]
Hr2aaa[ki, kj] += .5 * lib.einsum('minj,mnb->ijb', imds.Woooo[km, ki, kn], r2aaa[km, kn])
Hr2abb[ki, kj] += lib.einsum('miNJ,mNB->iJB', imds.WooOO[km, ki, kn], r2abb[km, kn])
Hr2bbb[ki, kj] += .5 * lib.einsum('MINJ,MNB->IJB', imds.WOOOO[km, ki, kn], r2bbb[km, kn])
Hr2baa[ki, kj] += lib.einsum('njMI,Mnb->Ijb', imds.WooOO[kn, kj, km], r2baa[km, kn])
# T2 term
# - \sum_{kc,c} t_{kj,ki,j,i}^{kb,kc,b,c} [ \sum_{kk,kL,kD,k,L,D} W_{kL,kk,kD,kc,L,k,D,c} S_{kk,kL,k,L}^{kD,D}
# + \sum{kk,kl,kd,k,l,d} W_{kl,kk,kd,kc,l,k,d,c} S_{kk,kl,k,l}^{kd,d} ] = (\bar{H}S)_{ki,kj,i,j}^{kb,b}
#
# - \sum_{kc,c} t_{ki,kJ,i,J}^{kc,kB,c,B} [ \sum_{kk,kL,kD,k,L,D} W_{kL,kk,kD,kc,L,k,D,c} S_{Kk,kL,k,L}^{kD,D}
# + \sum{kk,kl,kd,k,l,d} W_{kl,kk,kd,kc,l,k,d,c} S_{kk,kl,k,l}^{kd,d} ] = (\bar{H}S)_{ki,kJ,i,J}^{kB,B}
tmp_aaa = lib.einsum('xymenf,xymnf->e', imds.Wovov[:,kshift,:], r2aaa)
tmp_bbb = lib.einsum('xyMENF,xyMNF->E', imds.WOVOV[:,kshift,:], r2bbb)
tmp_abb = lib.einsum('xymeNF,xymNF->e', imds.WovOV[:,kshift,:], r2abb)
tmp_baa = np.zeros(tmp_bbb.shape, dtype=tmp_bbb.dtype)
for km, kn in itertools.product(range(nkpts), repeat=2):
kf = kconserv[kn, kshift, km]
tmp_baa += lib.einsum('nfME, Mnf->E', imds.WovOV[kn, kf, km], r2baa[km, kn])
for ki, kj in itertools.product(range(nkpts), repeat=2):
kb = kconserv[ki, kshift, kj]
Hr2aaa[ki,kj] -= 0.5 * lib.einsum('e,jibe->ijb', tmp_aaa, t2aa[kj,ki,kb])
Hr2aaa[ki,kj] -= lib.einsum('e,jibe->ijb', tmp_abb, t2aa[kj,ki,kb])
Hr2abb[ki,kj] -= 0.5 * lib.einsum('e,iJeB->iJB', tmp_aaa, t2ab[ki,kj,kshift])
Hr2abb[ki,kj] -= lib.einsum('e,iJeB->iJB', tmp_abb, t2ab[ki,kj,kshift])
Hr2baa[ki,kj] -= 0.5 * lib.einsum('E,jIbE->Ijb', tmp_bbb, t2ab[kj,ki,kb])
Hr2baa[ki,kj] -= lib.einsum('E,jIbE->Ijb', tmp_baa, t2ab[kj,ki,kb])
Hr2bbb[ki,kj] -= 0.5 * lib.einsum('E,JIBE->IJB', tmp_bbb, t2bb[kj,ki,kb])
Hr2bbb[ki,kj] -= lib.einsum('E,JIBE->IJB', tmp_baa, t2bb[kj,ki,kb])
#idxoa = [np.where(orbspin[k][:nocca+noccb] == 0)[0] for k in range(nkpts)]
#idxva = [np.where(orbspin[k][nocca+noccb:] == 0)[0] for k in range(nkpts)]
#idxob = [np.where(orbspin[k][:nocca+noccb] == 1)[0] for k in range(nkpts)]
#idxvb = [np.where(orbspin[k][nocca+noccb:] == 1)[0] for k in range(nkpts)]
# j \/ b | i
# --- |
# /\ |
# m \/ e|
# -------
for ki, kj in itertools.product(range(nkpts), repeat=2):
kb = kconserv[ki, kshift, kj]
for km in range(nkpts):
ke = kconserv[km, kshift, ki]
# \sum_{kL,kD,L,D} W_{kL,kD,kb,kj,L,D,b,j} S_{ki,kL,i,L}^{kb,b}
# \sum_{kl,kd,l,d} W_{kl,kd,kb,kj,l,d,b,j} S_{ki,kl,i,l}^{kb,b}
Hr2aaa[ki, kj] += lib.einsum('mebj,ime->ijb', imds.Wovvo[km, ke, kb],
r2aaa[ki, km])
Hr2aaa[ki, kj] += lib.einsum('MEbj,iME->ijb', imds.WOVvo[km, ke, kb],
r2abb[ki, km])
# P(ij)
ke = kconserv[km, kshift, kj]
Hr2aaa[ki, kj] -= lib.einsum('mebi,jme->ijb', imds.Wovvo[km, ke, kb],
r2aaa[kj, km])
Hr2aaa[ki, kj] -= lib.einsum('MEbi,jME->ijb', imds.WOVvo[km, ke, kb],
r2abb[kj, km])
# \sum_{kL,kD,L,D} W_{kL,kD,kb,kJ,L,D,b,J} S_{ki,kL,i,L}^{kD,D}
# \sum_{kl,kd,l,d} W_{kl,kd,kB,kJ,l,d,B,J} S_{ki,kl,i,l}^{kd,d}
ke = kconserv[km, kshift, ki]
Hr2abb[ki, kj] += lib.einsum('meBJ,ime->iJB', imds.WovVO[km, ke, kb],
r2aaa[ki, km])
Hr2abb[ki, kj] += lib.einsum('MEBJ,iME->iJB', imds.WOVVO[km, ke, kb],
r2abb[ki, km])
ke = kconserv[km, kshift, kj]
Hr2abb[ki, kj] -= lib.einsum('miBE,mJE->iJB', imds.WooVV[km, ki, kb],
r2abb[km, kj])
ke = kconserv[km, kshift, ki]
Hr2baa[ki, kj] += lib.einsum('MEbj,IME->Ijb', imds.WOVvo[km, ke, kb],
r2bbb[ki, km])
Hr2baa[ki, kj] += lib.einsum('mebj,Ime->Ijb', imds.Wovvo[km, ke, kb],
r2baa[ki, km])
ke = kconserv[km, kshift, kj]
Hr2baa[ki, kj] -= lib.einsum('MIbe,Mje->Ijb', imds.WOOvv[km, ki, kb],
r2baa[km, kj])
ke = kconserv[km, kshift, ki]
Hr2bbb[ki, kj] += lib.einsum('MEBJ,IME->IJB', imds.WOVVO[km, ke, kb],
r2bbb[ki, km])
Hr2bbb[ki, kj] += lib.einsum('meBJ,Ime->IJB', imds.WovVO[km, ke, kb],
r2baa[ki, km])
# P(ij)
ke = kconserv[km, kshift, kj]
Hr2bbb[ki, kj] -= lib.einsum('MEBI,JME->IJB', imds.WOVVO[km, ke, kb],
r2bbb[kj, km])
Hr2bbb[ki, kj] -= lib.einsum('meBI,Jme->IJB', imds.WovVO[km, ke, kb],
r2baa[kj, km])
#spatial_Hr1 = [Hr1a, Hr1b]
#spatial_Hr2 = [Hr2aaa, Hr2baa, Hr2abb, Hr2bbb]
#spin_Hr1, spin_Hr2 = eom_kgccsd.spatial2spin_ip_doublet(spatial_Hr1, spatial_Hr2,
# kconserv, kshift, orbspin)
#Hr1 += spin_Hr1
#Hr2 += spin_Hr2
#vector = eom.amplitudes_to_vector(Hr1, Hr2)
vector = amplitudes_to_vector_ip([Hr1a, Hr1b], [Hr2aaa, Hr2baa, Hr2abb, Hr2bbb], kshift, kconserv)
return vector
[docs]
def ipccsd_diag(eom, kshift, imds=None):
if imds is None: imds = eom.make_imds()
t1, t2 = imds.t1, imds.t2
t1a, t1b = t1
t2aa, t2ab, t2bb = t2
nkpts, nocc_a, nvir_a = t1a.shape
nkpts, nocc_b, nvir_b = t1b.shape
kconserv = imds.kconserv
Hr1a = -np.diag(imds.Foo[kshift])
Hr1b = -np.diag(imds.FOO[kshift])
Hr2aaa = np.zeros((nkpts,nkpts,nocc_a,nocc_a,nvir_a), dtype=t1[0].dtype)
Hr2bbb = np.zeros((nkpts,nkpts,nocc_b,nocc_b,nvir_b), dtype=t1[0].dtype)
Hr2abb = np.zeros((nkpts,nkpts,nocc_a,nocc_b,nvir_b), dtype=t1[0].dtype)
Hr2baa = np.zeros((nkpts,nkpts,nocc_b,nocc_a,nvir_a), dtype=t1[0].dtype)
if eom.partition == 'mp':
raise Exception("MP diag is not tested") # remove this to use untested code
#foo = eris.fock[0][:,:nocc_a,:nocc_a]
#fOO = eris.fock[1][:,:nocc_b,:nocc_b]
#fvv = eris.fock[0][:,:nvir_a,:nvir_a]
#fVV = eris.fock[1][:,:nvir_b,:nvir_b]
for ki in range(nkpts):
for kj in range(nkpts):
ka = kconserv[ki,kshift,kj]
Hr2aaa[ki,kj] = imds.Fvv[ka].diagonal()
Hr2aaa[ki,kj] -= imds.Foo[ki].diagonal()[:,None,None]
Hr2aaa[ki,kj] -= imds.Foo[kj].diagonal()[None,:,None]
Hr2bbb[ki,kj] = imds.FVV[ka].diagonal()
Hr2bbb[ki,kj] -= imds.FOO[ki].diagonal()[:,None,None]
Hr2bbb[ki,kj] -= imds.FOO[kj].diagonal()[None,:,None]
Hr2aba[ki,kj] = imds.Fvv[ka].diagonal()
Hr2aba[ki,kj] -= imds.Foo[ki].diagonal()[:,None,None]
Hr2aba[ki,kj] -= imds.FOO[kj].diagonal()[None,:,None]
Hr2bab[ki,kj] = imds.FVV[ka].diagonal()
Hr2bab[ki,kj] -= imds.FOO[ki].diagonal()[:,None,None]
Hr2bab[ki,kj] -= imds.Foo[kj].diagonal()[None,:,None]
else:
for ka in range(nkpts):
for ki in range(nkpts):
kj = kconserv[kshift,ki,ka]
Hr2aaa[ki,kj] += imds.Fvv[ka].diagonal()
Hr2abb[ki,kj] += imds.FVV[ka].diagonal()
Hr2bbb[ki,kj] += imds.FVV[ka].diagonal()
Hr2baa[ki,kj] += imds.Fvv[ka].diagonal()
Hr2aaa[ki,kj] -= imds.Foo[ki].diagonal()[:,None,None]
Hr2aaa[ki,kj] -= imds.Foo[kj].diagonal()[None,:,None]
Hr2abb[ki,kj] -= imds.Foo[ki].diagonal()[:,None,None]
Hr2abb[ki,kj] -= imds.FOO[kj].diagonal()[None,:,None]
Hr2baa[ki,kj] -= imds.FOO[ki].diagonal()[:,None,None]
Hr2baa[ki,kj] -= imds.Foo[kj].diagonal()[None,:,None]
Hr2bbb[ki,kj] -= imds.FOO[ki].diagonal()[:,None,None]
Hr2bbb[ki,kj] -= imds.FOO[kj].diagonal()[None,:,None]
for ki, kj in itertools.product(range(nkpts), repeat=2):
Hr2aaa[ki, kj] += lib.einsum('iijj->ij', imds.Woooo[ki, ki, kj])[:,:,None]
Hr2abb[ki, kj] += lib.einsum('iiJJ->iJ', imds.WooOO[ki, ki, kj])[:,:,None]
Hr2bbb[ki, kj] += lib.einsum('IIJJ->IJ', imds.WOOOO[ki, ki, kj])[:,:,None]
Hr2baa[ki, kj] += lib.einsum('jjII->Ij', imds.WooOO[kj, kj, ki])[:,:,None]
kb = kconserv[ki, kshift, kj]
Hr2aaa[ki,kj] -= lib.einsum('iejb,jibe->ijb', imds.Wovov[ki,kshift,kj], t2aa[kj,ki,kb])
Hr2abb[ki,kj] -= lib.einsum('ieJB,iJeB->iJB', imds.WovOV[ki,kshift,kj], t2ab[ki,kj,kshift])
Hr2baa[ki,kj] -= lib.einsum('jbIE,jIbE->Ijb', imds.WovOV[kj,kb,ki], t2ab[kj,ki,kb])
Hr2bbb[ki,kj] -= lib.einsum('IEJB,JIBE->IJB', imds.WOVOV[ki,kshift,kj], t2bb[kj,ki,kb])
Hr2aaa[ki, kj] += lib.einsum('ibbi->ib', imds.Wovvo[ki, kb, kb])[:,None,:]
Hr2aaa[ki, kj] += lib.einsum('jbbj->jb', imds.Wovvo[kj, kb, kb])[None,:,:]
Hr2baa[ki, kj] += lib.einsum('jbbj->jb', imds.Wovvo[kj, kb, kb])[None,:,:]
Hr2baa[ki, kj] -= lib.einsum('IIbb->Ib', imds.WOOvv[ki, ki, kb])[:,None,:]
Hr2abb[ki, kj] += lib.einsum('JBBJ->JB', imds.WOVVO[kj, kb, kb])[None,:,:]
Hr2abb[ki, kj] -= lib.einsum('iiBB->iB', imds.WooVV[ki, ki, kb])[:,None,:]
Hr2bbb[ki, kj] += lib.einsum('IBBI->IB', imds.WOVVO[ki, kb, kb])[:,None,:]
Hr2bbb[ki, kj] += lib.einsum('JBBJ->JB', imds.WOVVO[kj, kb, kb])[None,:,:]
vector = amplitudes_to_vector_ip((Hr1a,Hr1b), (Hr2aaa,Hr2baa,Hr2abb,Hr2bbb), kshift, kconserv)
return vector
[docs]
def mask_frozen_ip(eom, vector, kshift, const=LARGE_DENOM):
'''Replaces all frozen orbital indices of `vector` with the value `const`.'''
nkpts = eom.nkpts
nocca, noccb = eom.nocc
nmoa, nmob = eom.nmo
kconserv = eom.kconserv
r1, r2 = eom.vector_to_amplitudes(vector, kshift, nkpts, (nmoa, nmob), (nocca, noccb), kconserv)
r1a, r1b = r1
r2aaa, r2baa, r2abb, r2bbb = r2
# Get location of padded elements in occupied and virtual space
nonzero_opadding, nonzero_vpadding = eom.nonzero_opadding, eom.nonzero_vpadding
nonzero_opadding_a, nonzero_opadding_b = nonzero_opadding
nonzero_vpadding_a, nonzero_vpadding_b = nonzero_vpadding
new_r1a = const * np.ones_like(r1a)
new_r1b = const * np.ones_like(r1b)
new_r2aaa = const * np.ones_like(r2aaa)
new_r2baa = const * np.ones_like(r2baa)
new_r2abb = const * np.ones_like(r2abb)
new_r2bbb = const * np.ones_like(r2bbb)
# r1a/b case
new_r1a[nonzero_opadding_a[kshift]] = r1a[nonzero_opadding_a[kshift]]
new_r1b[nonzero_opadding_b[kshift]] = r1b[nonzero_opadding_b[kshift]]
# r2aaa case
for ki in range(nkpts):
for kj in range(nkpts):
kb = kconserv[ki, kshift, kj]
idx = np.ix_([ki], [kj], nonzero_opadding_a[ki], nonzero_opadding_a[kj], nonzero_vpadding_a[kb])
new_r2aaa[idx] = r2aaa[idx]
# r2baa case
for ki in range(nkpts):
for kj in range(nkpts):
kb = kconserv[ki, kshift, kj]
idx = np.ix_([ki], [kj], nonzero_opadding_b[ki], nonzero_opadding_a[kj], nonzero_vpadding_a[kb])
new_r2baa[idx] = r2baa[idx]
# r2abb case
for ki in range(nkpts):
for kj in range(nkpts):
kb = kconserv[ki, kshift, kj]
idx = np.ix_([ki], [kj], nonzero_opadding_a[ki], nonzero_opadding_b[kj], nonzero_vpadding_b[kb])
new_r2abb[idx] = r2abb[idx]
# r2bbb case
for ki in range(nkpts):
for kj in range(nkpts):
kb = kconserv[ki, kshift, kj]
idx = np.ix_([ki], [kj], nonzero_opadding_b[ki], nonzero_opadding_b[kj], nonzero_vpadding_b[kb])
new_r2bbb[idx] = r2bbb[idx]
return eom.amplitudes_to_vector((new_r1a,new_r1b), (new_r2aaa,new_r2baa,new_r2abb,new_r2bbb), kshift, kconserv)
[docs]
def get_padding_k_idx(eom, cc):
# Get location of padded elements in occupied and virtual space
nonzero_padding_alpha, nonzero_padding_beta = padding_k_idx(cc, kind="split")
nonzero_opadding_alpha, nonzero_vpadding_alpha = nonzero_padding_alpha
nonzero_opadding_beta, nonzero_vpadding_beta = nonzero_padding_beta
return ((nonzero_opadding_alpha, nonzero_opadding_beta),
(nonzero_vpadding_alpha, nonzero_vpadding_beta))
[docs]
class EOMIP(eom_kgccsd.EOMIP):
def __init__(self, cc):
#if not isinstance(cc, kccsd.GCCSD):
# raise TypeError
self.kpts = cc.kpts
eom_kgccsd.EOMIP.__init__(self, cc)
get_diag = ipccsd_diag
matvec = ipccsd_matvec
get_padding_k_idx = get_padding_k_idx
mask_frozen = mask_frozen_ip
[docs]
def get_init_guess(self, kshift, nroots=1, koopmans=False, diag=None):
size = self.vector_size()
dtype = getattr(diag, 'dtype', np.complex128)
nroots = min(nroots, size)
nocca, noccb = self.nocc
guess = []
if koopmans:
idx = np.zeros(nroots, dtype=int)
tmp_oalpha, tmp_obeta = self.nonzero_opadding[kshift]
tmp_oalpha = list(tmp_oalpha)
tmp_obeta = list(tmp_obeta)
if len(tmp_obeta) + len(tmp_oalpha) < nroots:
raise ValueError("Max number of roots for k-point (idx=%3d) for koopmans "
"is %3d.\nRequested %3d." %
(kshift, len(tmp_obeta)+len(tmp_oalpha), nroots))
total_count = 0
while (total_count < nroots):
if total_count % 2 == 0 and len(tmp_oalpha) > 0:
idx[total_count] = tmp_oalpha.pop()
else:
# Careful! index depends on how we create vector
# (here the first elements are r1a, then r1b)
idx[total_count] = nocca + tmp_obeta.pop()
total_count += 1
else:
idx = diag.argsort()
for i in idx[:nroots]:
g = np.zeros(size, dtype)
g[i] = 1.0
g = self.mask_frozen(g, kshift, const=0.0)
guess.append(g)
return guess
[docs]
def gen_matvec(self, kshift, imds=None, left=False, **kwargs):
if imds is None: imds = self.make_imds()
diag = self.get_diag(kshift, imds)
if left:
raise NotImplementedError
matvec = lambda xs: [self.l_matvec(x, kshift, imds, diag) for x in xs]
else:
matvec = lambda xs: [self.matvec(x, kshift, imds, diag) for x in xs]
return matvec, diag
[docs]
def vector_to_amplitudes(self, vector, kshift, nkpts=None, nmo=None, nocc=None, kconserv=None):
if nmo is None: nmo = self.nmo
if nocc is None: nocc = self.nocc
if nkpts is None: nkpts = self.nkpts
if kconserv is None: kconserv = self.kconserv
return vector_to_amplitudes_ip(vector, kshift, nkpts, nmo, nocc, kconserv)
[docs]
def amplitudes_to_vector(self, r1, r2, kshift, kconserv=None):
if kconserv is None: kconserv = self.kconserv
return amplitudes_to_vector_ip(r1, r2, kshift, kconserv)
[docs]
def vector_size(self):
nocca, noccb = self.nocc
nmoa, nmob = self.nmo
nvira, nvirb = nmoa - nocca, nmob - noccb
nkpts = self.nkpts
return (nocca + noccb +
nkpts*nocca*(nkpts*nocca-1)*nvira//2 +
nkpts**2*noccb*nocca*nvira +
nkpts**2*nocca*noccb*nvirb +
nkpts*noccb*(nkpts*noccb-1)*nvirb//2)
[docs]
def make_imds(self, eris=None, t1=None, t2=None):
imds = _IMDS(self._cc, eris, t1, t2)
imds.make_ip()
return imds
########################################
# EOM-EA-CCSD
########################################
[docs]
def amplitudes_to_vector_ea(r1, r2, kshift, kconserv):
r1a, r1b = r1
r2a, r2aba, r2bab, r2b = r2
nkpts = r2a.shape[0]
nocca, noccb = r2a.shape[2], r2b.shape[2]
nvira, nvirb = r2a.shape[3], r2b.shape[3]
# From symmetry for aaa and bbb terms, only store lower
# triangular part (ka,a) < (kb,b)
r2aaa = np.zeros((nocca*nkpts*nvira*(nkpts*nvira-1))//2, dtype=r2a.dtype)
r2bbb = np.zeros((noccb*nkpts*nvirb*(nkpts*nvirb-1))//2, dtype=r2b.dtype)
index = 0
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift,ka,kj]
if ka < kb: # Take diagonal part
idxa, idya = np.tril_indices(nvira, 0)
else: # Don't take diagonal (equal to zero)
idxa, idya = np.tril_indices(nvira, -1)
r2aaa[index:index + nocca*len(idya)] = r2a[kj,ka,:,idxa,idya].reshape(-1)
index = index + nocca*len(idya)
index = 0
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift,ka,kj]
if ka < kb: # Take diagonal part
idxb, idyb = np.tril_indices(nvirb, 0)
else:
idxb, idyb = np.tril_indices(nvirb, -1)
r2bbb[index:index + noccb*len(idyb)] = r2b[kj,ka,:,idxb,idyb].reshape(-1)
index = index + noccb*len(idyb)
return np.hstack((r1a, r1b, r2aaa.ravel(),
r2aba.ravel(), r2bab.ravel(),
r2bbb.ravel()))
[docs]
def vector_to_amplitudes_ea(vector, kshift, nkpts, nmo, nocc, kconserv):
nocca, noccb = nocc
nmoa, nmob = nmo
nvira, nvirb = nmoa-nocca, nmob-noccb
sizes = (nvira, nvirb, nkpts*nocca*(nkpts*nvira-1)*nvira//2,
nkpts**2*nocca*nvirb*nvira, nkpts**2*noccb*nvira*nvirb,
nkpts*noccb*(nkpts*nvirb-1)*nvirb//2)
sections = np.cumsum(sizes[:-1])
r1a, r1b, r2a, r2aba, r2bab, r2b = np.split(vector, sections)
r2aaa = np.zeros((nkpts,nkpts,nocca,nvira,nvira), dtype=r2a.dtype)
r2aba = r2aba.reshape(nkpts,nkpts,nocca,nvirb,nvira).copy()
r2bab = r2bab.reshape(nkpts,nkpts,noccb,nvira,nvirb).copy()
r2bbb = np.zeros((nkpts,nkpts,noccb,nvirb,nvirb), dtype=r2b.dtype)
index = 0
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift,ka,kj]
if ka < kb: # Take diagonal part
idxa, idya = np.tril_indices(nvira, 0)
else:
idxa, idya = np.tril_indices(nvira, -1)
tmp = r2a[index:index + nocca*len(idya)].reshape(-1,nocca)
r2aaa[kj,ka,:,idxa,idya] = tmp
r2aaa[kj,kb,:,idya,idxa] = -tmp
index = index + nocca*len(idya)
index = 0
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift,ka,kj]
if ka < kb: # Take diagonal part
idxb, idyb = np.tril_indices(nvirb, 0)
else:
idxb, idyb = np.tril_indices(nvirb, -1)
tmp = r2b[index:index + noccb*len(idyb)].reshape(-1,noccb)
r2bbb[kj,ka,:,idxb,idyb] = tmp
r2bbb[kj,kb,:,idyb,idxb] = -tmp
index = index + noccb*len(idyb)
r1 = (r1a.copy(), r1b.copy())
r2 = (r2aaa, r2aba, r2bab, r2bbb)
return r1, r2
[docs]
def eaccsd_matvec(eom, vector, kshift, imds=None, diag=None):
'''2ph operators are of the form s_{ j}^{ab}, i.e. 'jb' indices are coupled'''
if imds is None: imds = eom.make_imds()
t1, t2= imds.t1, imds.t2
t1a, t1b = t1
t2aa, t2ab, t2bb = t2
nocca, noccb, nvira, nvirb = t2ab.shape[3:]
nmoa, nmob = nocca + nvira, noccb + nvirb
kconserv = imds.kconserv
nkpts = eom.nkpts
r1, r2 = eom.vector_to_amplitudes(vector, kshift, nkpts, (nmoa, nmob), (nocca, noccb), kconserv)
r1a, r1b = r1
r2aaa, r2aba, r2bab, r2bbb = r2
# BEGINNING OF MATVEC CONTRACTIONS: ref - Nooijen 1995 EOM-CC for EA
# Fvv terms
# (\bar{H}S)^a = \sum_{kc,c} U_{ac} s^c
Hr1a = einsum('ac,c->a', imds.Fvv[kshift], r1a)
Hr1b = einsum('AC,C->A', imds.FVV[kshift], r1b)
# Fov terms
# (\bar{H}S)^a = \sum_{kL,kD, L, D} U_{kL,kD,L,D} s^{a,kD,D}_{kL,L} + \sum_{kl,kd,l,d} U_{kl, d}^{a,kd,d}_{kl,l}
for kl in range(nkpts):
Hr1a += einsum('ld,lad->a', imds.Fov[kl], r2aaa[kl,kshift])
Hr1a += einsum('LD,LaD->a', imds.FOV[kl], r2bab[kl,kshift])
Hr1b += einsum('ld,lAd->A', imds.Fov[kl], r2aba[kl,kshift])
Hr1b += einsum('LD,LAD->A', imds.FOV[kl], r2bbb[kl,kshift])
# Wvovv
# (\bar{H}S)^a = \sum_{kc,kL,kD,c,L,D} W_{kL,kc,kD,a,l,c,D} s_{kL,L}^{kc,kD,c,D}
# + \sum_{kc,kd,kl,c,d,l} W_{ka,kl,kc,kd,a,l,c,d} s_{kl,l}^{kc,kd,c,d}
for kc, kl in itertools.product(range(nkpts), repeat=2):
Hr1a += 0.5*lib.einsum('acld,lcd->a', imds.Wvvov[kshift,kc,kl], r2aaa[kl,kc])
Hr1a += lib.einsum('acLD,LcD->a', imds.WvvOV[kshift,kc,kl], r2bab[kl,kc])
Hr1b += 0.5*lib.einsum('ACLD,LCD->A', imds.WVVOV[kshift,kc,kl], r2bbb[kl,kc])
Hr1b += lib.einsum('ACld,lCd->A', imds.WVVov[kshift,kc,kl], r2aba[kl,kc])
dtype = np.result_type(Hr1a, *r2)
Hr2aaa = np.zeros((nkpts, nkpts, nocca, nvira, nvira), dtype=dtype)
Hr2aba = np.zeros((nkpts, nkpts, nocca, nvirb, nvira), dtype=dtype)
Hr2bab = np.zeros((nkpts, nkpts, noccb, nvira, nvirb), dtype=dtype)
Hr2bbb = np.zeros((nkpts, nkpts, noccb, nvirb, nvirb), dtype=dtype)
# Wvvvv
# \sum_{kc,kd,c,d} W_{ka,kb,kc,kd,a,b,c,d} s_{kj,j}^{kc,kd,c,d} = (\bar{H}S)^{kb, a, b}_{kj,j}
# \sum_{kc,kD,c,D} W{ka,kB,kc,kD,a,B,c,D} s_{kJ,kc,kD,J,c,D} = (\bar{H}S)^{kB, a, B}_{kJ,J}
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift,ka,kj]
for kc in range(nkpts):
kd = kconserv[ka, kc, kb]
Wvvvv, WvvVV, WVVVV = imds.get_Wvvvv(ka, kb, kc)
Hr2aaa[kj,ka] += .5 * lib.einsum('acbd,jcd->jab', Wvvvv, r2aaa[kj,kc])
Hr2aba[kj,kb] += lib.einsum('bcad,jdc->jab', WvvVV, r2aba[kj,kd])
Hr2bab[kj,ka] += lib.einsum('acbd,jcd->jab', WvvVV, r2bab[kj,kc])
Hr2bbb[kj,ka] += .5 * lib.einsum('acbd,jcd->jab', WVVVV, r2bbb[kj,kc])
#Wvvvo
# \sum_{kc,ka,kj,c,a,j} W_{kb,kc,kj,a,b,c,j} s^{kc,c} = (\bar{H}S)^{kb, a, b}_{kj,j}
# \sum_{kc,ka,kJ,c,a,J} W_{kB,kc,kJ,a,B,c,J} s^{kc,c} = (\bar{H}S)^{kB, a, B}_{kJ,J}
for ka, kj, in itertools.product(range(nkpts),repeat=2):
kb = kconserv[kshift,ka,kj]
kc = kshift
Hr2aaa[kj,ka] += einsum('acbj,c->jab', imds.Wvvvo[ka,kc,kb], r1a)
Hr2bbb[kj,ka] += einsum('ACBJ,C->JAB', imds.WVVVO[ka,kc,kb], r1b)
Hr2bab[kj,ka] += einsum('acBJ,c->JaB', imds.WvvVO[ka,kc,kb], r1a)
Hr2aba[kj,ka] += einsum('ACbj,C->jAb', imds.WVVvo[ka,kc,kb], r1b)
#Fvv Terms
# sum_{kc,ka,kj,c,a,j} s_{kj,j}^{kc,kb,c,b} U_{ka,kc,a,c} = (\bar{H}S)^{kb, a, b}_{kj,j}
# sum_{kd,ka,kj,d,b,j} s_{kj,j}^{ka,kd,a,d} U_{kb,kd,b,d} = (\bar{H}S)^{kb, a, b}_{kj,j}
# sum_{kc,ka,kJ,c,a,J} U_{ka,kc,a,c} s_{kJ,J}^{kc,kB,c,B} = (\bar{H}S)^{kB, a, B}_{kJ,J}
# sum_{kD,ka,kj,D,a,j} U_{kb,kd,b,d} s_{kj,j}^{ka,kd,a,d} = (\bar{H}S)^{kB, a, B}_{kJ,J}
for ka, kj in itertools.product(range(nkpts), repeat=2):
# kb = kshift - ka + kj
kb = kconserv[kshift, ka, kj]
tmpa = lib.einsum('ac,jcb->jab', imds.Fvv[ka], r2aaa[kj,ka])
tmpb = lib.einsum('bc,jca->jab', imds.Fvv[kb], r2aaa[kj,kb])
Hr2aaa[kj,ka] += tmpa - tmpb
Hr2aba[kj,ka] += lib.einsum('AC,jCb->jAb', imds.FVV[ka], r2aba[kj,ka])
Hr2bab[kj,ka] += lib.einsum('ac,JcB->JaB', imds.Fvv[ka], r2bab[kj,ka])
Hr2aba[kj,ka] += lib.einsum('bc, jAc -> jAb', imds.Fvv[kb], r2aba[kj,ka])
Hr2bab[kj,ka] += lib.einsum('BC, JaC -> JaB', imds.FVV[kb], r2bab[kj,ka])
tmpb = lib.einsum('AC,JCB->JAB', imds.FVV[ka], r2bbb[kj,ka])
tmpa = lib.einsum('BC,JCA->JAB', imds.FVV[kb], r2bbb[kj,kb])
Hr2bbb[kj,ka] += tmpb - tmpa
#Foo Term
# \sum_{ka,kl,l} U_{kl,l,kj,j} s^{ka,a,kb,b}^{kl,l} = (\bar{H}S)^{kb, a, b}_{kj,j}
# \sum_{ka,kL,L} s^{ka,a,kB,B}_{kL,L} U_{kL,L,kJ,J} = (\bar{H}S)^{kB, a, B}_{kJ,J}
for kl, ka in itertools.product(range(nkpts), repeat=2):
Hr2aaa[kl,ka] -= lib.einsum('lj,lab->jab', imds.Foo[kl], r2aaa[kl,ka])
Hr2bbb[kl,ka] -= lib.einsum('LJ,LAB->JAB', imds.FOO[kl], r2bbb[kl,ka])
Hr2bab[kl,ka] -= lib.einsum('LJ,LaB->JaB', imds.FOO[kl], r2bab[kl,ka])
Hr2aba[kl,ka] -= lib.einsum('lj,lAb->jAb', imds.Foo[kl], r2aba[kl,ka])
# Woovv term
# - \sum{kk,k} t_{kk,kj,k,j}^{ka,kb,a,b} [\sum_{kc,kD,kL,c,D,L} W_{kL,kk,kD,kc,L,k,D,c} s_{kL,L}^{kc,kD,c,D}
# + \sum{kc,kd,kl,c,d,l} W_{kk,kl,kc,kd,k,l,c,d} s_{kl,l}^{kc,kd,c,d} ] = (\bar{H}S)^{kb, a, b}_{kj,j}
#
# - \sum_{kk,k} t_{kk,kJ,k,J}^{ka,kB,a,B} [ \sum{kc,kD,kL,c,D,L} W_{kk,kL,kc,kD,k,L,c,D} s_{kL,L}^{kc,kD,c,D}
# + \sum_{kc,kd,kl,c,d,l} W_{kk,kl,kc,kd,k,l,c,d} s_{kl,l}^{kc,kd,c,d} ] = (\bar{H}S)^{kB, a, B}_{kJ,J}
tmp_aaa = lib.einsum('xykcld, yxlcd->k', imds.Wovov[kshift,:,:], r2aaa)
tmp_bbb = lib.einsum('xyKCLD, yxLCD->K', imds.WOVOV[kshift,:,:], r2bbb)
tmp_bab = lib.einsum('xykcLD, yxLcD->k', imds.WovOV[kshift], r2bab)
tmp_aba = np.zeros(tmp_bbb.shape, dtype = tmp_bbb.dtype)
for kl, kc in itertools.product(range(nkpts), repeat=2):
kd = kconserv[kl,kc,kshift]
tmp_aba += lib.einsum('ldKC, lCd->K', imds.WovOV[kl,kd,kshift], r2aba[kl,kc])
Hr2aaa -= 0.5 * lib.einsum('k, xykjab->xyjab', tmp_aaa, t2aa[kshift])
Hr2bab -= 0.5 * lib.einsum('k, xykJaB->xyJaB', tmp_aaa, t2ab[kshift])
Hr2aaa -= lib.einsum('k, xykjab->xyjab', tmp_bab, t2aa[kshift])
Hr2bbb -= 0.5 * lib.einsum('K, xyKJAB->xyJAB', tmp_bbb, t2bb[kshift])
Hr2bbb -= lib.einsum('K, xyKJAB->xyJAB', tmp_aba, t2bb[kshift])
Hr2bab -= lib.einsum('k, xykJaB->xyJaB', tmp_bab, t2ab[kshift])
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift, ka, kj]
Hr2aba[kj, ka] -= lib.einsum('K, jKbA->jAb', tmp_aba, t2ab[kj, kshift, kb])
Hr2aba[kj, ka] -= 0.5 * einsum('K, jKbA->jAb', tmp_bbb, t2ab[kj, kshift, kb])
# j \/ b | a
# --- |
# /\ |
# l \/ d|
# -------
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift, ka, kj]
for kd in range(nkpts):
kl = kconserv[ka, kshift, kd]
# \sum_{kL,kD,L,D} W_{kL,kb,kD,kj,L,b,D,j} s_{kL,L}^{ka,kD,a,D} = (\bar{H}S)^{kb, a, b}_{kj,j}
# \sum_{kl,kd,l,d} W_{kl,kb,kd,kj,l,b,d,j} s_{kl,l}^{ka,kd,a,d} = (\bar{H}S)^{kb, a, b}_{kj,j}
Hr2aaa[kj, ka] += lib.einsum('ldbj,lad->jab', imds.Wovvo[kl,kd,kb],
r2aaa[kl,ka])
Hr2aaa[kj, ka] += lib.einsum('LDbj,LaD->jab', imds.WOVvo[kl,kd,kb],
r2bab[kl,ka])
# P(ab)
kl = kconserv[kb, kshift, kd]
Hr2aaa[kj, ka] -= lib.einsum('ldaj,lbd->jab', imds.Wovvo[kl,kd,ka],
r2aaa[kl,kb])
Hr2aaa[kj, ka] -= lib.einsum('LDaj,LbD->jab', imds.WOVvo[kl,kd,ka],
r2bab[kl,kb])
kl = kconserv[ka, kshift, kd]
# \sum_{kL,kD,L,D} W_{kL,kB,kD,kJ,L,B,D,J} s_{kL,L}^{ka,kD,a,D} = (\bar{H}S)^{kB, a, B}_{kJ,J}
# \sum_{kl,kd,l,d} W_{kl,kB,kd,kJ,l,B,d,J} s_{kl,l}^{ka,kd,a,d} = (\bar{H}S)^{kB, a, B}_{kJ,J}
# - \sum_{kc,kL,c,L} W_{ka,kL,kc,kJ,a,L,c,J} s_{kL,L}^{kc,kB,c,B} = (\bar{H}S)^{kB, a, B}_{kJ,J}
Hr2bab[kj, ka] += lib.einsum('ldBJ,lad->JaB', imds.WovVO[kl,kd,kb],
r2aaa[kl,ka])
Hr2bab[kj, ka] += lib.einsum('LDBJ,LaD->JaB', imds.WOVVO[kl,kd,kb],
r2bab[kl,ka])
kl = kconserv[kb, kshift, kd]
Hr2bab[kj, ka] -= lib.einsum('LJad,LdB->JaB', imds.WOOvv[kl,kj,ka],
r2bab[kl,kd])
kl = kconserv[ka, kshift, kd]
Hr2aba[kj, ka] += lib.einsum('LDbj,LAD->jAb', imds.WOVvo[kl,kd,kb],
r2bbb[kl,ka])
Hr2aba[kj, ka] += lib.einsum('ldbj,lAd->jAb', imds.Wovvo[kl,kd,kb],
r2aba[kl,ka])
kl = kconserv[kb, kshift, kd]
Hr2aba[kj, ka] -= lib.einsum('ljAD,lDb->jAb', imds.WooVV[kl,kj,ka],
r2aba[kl,kd])
kl = kconserv[ka, kshift, kd]
Hr2bbb[kj, ka] += lib.einsum('LDBJ,LAD->JAB', imds.WOVVO[kl,kd,kb],
r2bbb[kl,ka])
Hr2bbb[kj, ka] += lib.einsum('ldBJ,lAd->JAB', imds.WovVO[kl,kd,kb],
r2aba[kl,ka])
# P(ab)
kl = kconserv[kb, kshift, kd]
Hr2bbb[kj, ka] -= lib.einsum('LDAJ,LBD->JAB', imds.WOVVO[kl,kd,ka],
r2bbb[kl,kb])
Hr2bbb[kj, ka] -= lib.einsum('ldAJ,lBd->JAB', imds.WovVO[kl,kd,ka],
r2aba[kl,kb])
vector = amplitudes_to_vector_ea([Hr1a, Hr1b], [Hr2aaa, Hr2aba, Hr2bab, Hr2bbb], kshift, kconserv)
return vector
[docs]
def eaccsd_diag(eom, kshift, imds=None):
if imds is None: imds = eom.make_imds()
t1, t2 = imds.t1, imds.t2
t1a, t1b = t1
t2aa, t2ab, t2bb = t2
nkpts, nocca, nvira = t1a.shape
nkpts, noccb, nvirb = t1b.shape
kconserv = imds.kconserv
#Hr1a = np.zeros((nvira), dtype=t1a.dtype)
#Hr1b = np.zeros((nvirb), dtype=t1b.dtype)
Hr2aaa = np.zeros((nkpts,nkpts,nocca,nvira,nvira), dtype=t1a.dtype)
Hr2aba = np.zeros((nkpts,nkpts,nocca,nvirb,nvira), dtype=t1a.dtype)
Hr2bab = np.zeros((nkpts,nkpts,noccb,nvira,nvirb), dtype=t1a.dtype)
Hr2bbb = np.zeros((nkpts,nkpts,noccb,nvirb,nvirb), dtype=t1b.dtype)
Hr1a = np.diag(imds.Fvv[kshift])
Hr1b = np.diag(imds.FVV[kshift])
if eom.partition == 'mp':
raise Exception("MP diag is not tested") # remove this to use untested code
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift, ka, kj]
Hr2aaa[kj,ka] -= imds.Foo[kj,:,None,None]
Hr2aaa[kj,ka] += imds.Fvv[ka,None,:,None]
Hr2aaa[kj,ka] += imds.Fvv[kb,None,None,:]
Hr2aba[kj,ka] -= imds.Foo[kj,:,None,None]
Hr2aba[kj,ka] += imds.FVV[ka,None,:,None]
Hr2aba[kj,ka] += imds.Fvv[kb,None,None,:]
Hr2bab[kj,ka] -= imds.FOO[kj,:,None,None]
Hr2bab[kj,ka] += imds.Fvv[ka,None,:,None]
Hr2bab[kj,ka] += imds.FVV[kb,None,None,:]
Hr2bbb[kj,ka] -= imds.FOO[kj,:,None,None]
Hr2bbb[kj,ka] += imds.FVV[ka,None,:,None]
Hr2bbb[kj,ka] += imds.FVV[kb,None,None,:]
else:
for kj, ka in itertools.product(range(nkpts), repeat=2):
kb = kconserv[kshift, ka, kj]
# Fvv
Hr2aaa[kj,ka] += imds.Fvv[ka].diagonal()[None,:,None]
Hr2aaa[kj,ka] += imds.Fvv[kb].diagonal()[None,None,:]
Hr2aba[kj,ka] += imds.FVV[ka].diagonal()[None,:,None]
Hr2aba[kj,ka] += imds.Fvv[kb].diagonal()[None,None,:]
Hr2bab[kj,ka] += imds.Fvv[ka].diagonal()[None,:,None]
Hr2bab[kj,ka] += imds.FVV[kb].diagonal()[None,None,:]
Hr2bbb[kj,ka] += imds.FVV[ka].diagonal()[None,:,None]
Hr2bbb[kj,ka] += imds.FVV[kb].diagonal()[None,None,:]
# Foo
Hr2aaa[kj,ka] -= imds.Foo[kj].diagonal()[:,None,None]
Hr2bbb[kj,ka] -= imds.FOO[kj].diagonal()[:,None,None]
Hr2bab[kj,ka] -= imds.FOO[kj].diagonal()[:,None,None]
Hr2aba[kj,ka] -= imds.Foo[kj].diagonal()[:,None,None]
# Wvvvv
Wvvvv, WvvVV, WVVVV = imds.get_Wvvvv(ka, kb, ka)
# FIXME: Do Wvvvv and WVVVV have a factor 0.5?
Hr2aaa[kj,ka] += lib.einsum('aabb->ab', Wvvvv)[None,:,:]
Hr2aba[kj,kb] += lib.einsum('bbAA->Ab', WvvVV)[None,:,:]
Hr2bab[kj,ka] += lib.einsum('aaBB->aB', WvvVV)[None,:,:]
Hr2bbb[kj,ka] += lib.einsum('AABB->AB', WVVVV)[None,:,:]
# Wovov term (physicist's Woovv)
Hr2aaa[kj,ka] -= lib.einsum('kajb, kjab->jab', imds.Wovov[kshift,ka,kj], t2aa[kshift,kj,ka])
Hr2aba[kj,ka] -= lib.einsum('jbKA, jKbA->jAb', imds.WovOV[kj,kb,kshift], t2ab[kj,kshift,kb])
Hr2bab[kj,ka] -= lib.einsum('kaJB, kJaB->JaB', imds.WovOV[kshift,ka,kj], t2ab[kshift,kj,ka])
Hr2bbb[kj,ka] -= lib.einsum('kajb, kjab->jab', imds.WOVOV[kshift,ka,kj], t2bb[kshift,kj,ka])
# Wovvo term
Hr2aaa[kj, ka] += lib.einsum('jbbj->jb', imds.Wovvo[kj,kb,kb])[:,None,:]
Hr2aaa[kj, ka] += lib.einsum('jaaj->ja', imds.Wovvo[kj,ka,ka])[:,:,None]
Hr2aba[kj, ka] += lib.einsum('jbbj->jb', imds.Wovvo[kj,kb,kb])[:,None,:]
Hr2aba[kj, ka] -= lib.einsum('jjAA->jA', imds.WooVV[kj,kj,ka])[:,:,None]
Hr2bab[kj, ka] += lib.einsum('JBBJ->JB', imds.WOVVO[kj,kb,kb])[:,None,:]
Hr2bab[kj, ka] -= lib.einsum('JJaa->Ja', imds.WOOvv[kj,kj,ka])[:,:,None]
Hr2bbb[kj, ka] += lib.einsum('JBBJ->JB', imds.WOVVO[kj,kb,kb])[:,None,:]
Hr2bbb[kj, ka] += lib.einsum('JAAJ->JA', imds.WOVVO[kj,ka,ka])[:,:,None]
vector = amplitudes_to_vector_ea([Hr1a,Hr1b], [Hr2aaa,Hr2aba,Hr2bab,Hr2bbb], kshift, kconserv)
return vector
[docs]
def mask_frozen_ea(eom, vector, kshift, const=LARGE_DENOM):
'''Replaces all frozen orbital indices of `vector` with the value `const`.'''
nkpts = eom.nkpts
nocca, noccb = eom.nocc
nmoa, nmob = eom.nmo
kconserv = eom.kconserv
r1, r2 = eom.vector_to_amplitudes(vector, kshift, nkpts, (nmoa, nmob), (nocca, noccb), kconserv)
r1a, r1b = r1
r2aaa, r2aba, r2bab, r2bbb = r2
# Get location of padded elements in occupied and virtual space
nonzero_opadding, nonzero_vpadding = eom.nonzero_opadding, eom.nonzero_vpadding
nonzero_opadding_a, nonzero_opadding_b = nonzero_opadding
nonzero_vpadding_a, nonzero_vpadding_b = nonzero_vpadding
new_r1a = const * np.ones_like(r1a)
new_r1b = const * np.ones_like(r1b)
new_r2aaa = const * np.ones_like(r2aaa)
new_r2aba = const * np.ones_like(r2aba)
new_r2bab = const * np.ones_like(r2bab)
new_r2bbb = const * np.ones_like(r2bbb)
# r1a/b case
new_r1a[nonzero_vpadding_a[kshift]] = r1a[nonzero_vpadding_a[kshift]]
new_r1b[nonzero_vpadding_b[kshift]] = r1b[nonzero_vpadding_b[kshift]]
# r2aaa case
for kj in range(nkpts):
for ka in range(nkpts):
kb = kconserv[kshift, ka, kj]
idx = np.ix_([kj], [ka], nonzero_opadding_a[kj], nonzero_vpadding_a[ka], nonzero_vpadding_a[kb])
new_r2aaa[idx] = r2aaa[idx]
# r2aba case
for kj in range(nkpts):
for ka in range(nkpts):
kb = kconserv[kshift, ka, kj]
idx = np.ix_([kj], [ka], nonzero_opadding_a[kj], nonzero_vpadding_b[ka], nonzero_vpadding_a[kb])
new_r2aba[idx] = r2aba[idx]
# r2bab case
for kj in range(nkpts):
for ka in range(nkpts):
kb = kconserv[kshift, ka, kj]
idx = np.ix_([kj], [ka], nonzero_opadding_b[kj], nonzero_vpadding_a[ka], nonzero_vpadding_b[kb])
new_r2bab[idx] = r2bab[idx]
# r2bbb case
for kj in range(nkpts):
for ka in range(nkpts):
kb = kconserv[kshift, ka, kj]
idx = np.ix_([kj], [ka], nonzero_opadding_b[kj], nonzero_vpadding_b[ka], nonzero_vpadding_b[kb])
new_r2bbb[idx] = r2bbb[idx]
return eom.amplitudes_to_vector((new_r1a,new_r1b), (new_r2aaa,new_r2aba,new_r2bab,new_r2bbb), kshift)
[docs]
class EOMEA(eom_kgccsd.EOMEA):
def __init__(self, cc):
#if not isinstance(cc, kccsd.GCCSD):
# raise TypeError
self.kpts = cc.kpts
eom_kgccsd.EOMEA.__init__(self, cc)
get_diag = eaccsd_diag
matvec = eaccsd_matvec
get_padding_k_idx = get_padding_k_idx
mask_frozen = mask_frozen_ea
[docs]
def get_init_guess(self, kshift, nroots=1, koopmans=False, diag=None):
size = self.vector_size()
dtype = getattr(diag, 'dtype', np.complex128)
nroots = min(nroots, size)
nocca, noccb = self.nocc
nmoa, nmob = self.nmo
nvira = nmoa-nocca
guess = []
if koopmans:
idx = np.zeros(nroots, dtype=int)
tmp_valpha, tmp_vbeta = self.nonzero_vpadding[kshift]
tmp_valpha = list(tmp_valpha)
tmp_vbeta = list(tmp_vbeta)
if len(tmp_vbeta) + len(tmp_valpha) < nroots:
raise ValueError("Max number of roots for k-point (idx=%3d) for koopmans "
"is %3d.\nRequested %3d." %
(kshift, len(tmp_vbeta)+len(tmp_valpha), nroots))
total_count = 0
while (total_count < nroots):
if total_count % 2 == 0 and len(tmp_valpha) > 0:
idx[total_count] = tmp_valpha.pop(0)
else:
# Careful! index depends on how we create vector
# (here the first elements are r1a, then r1b)
idx[total_count] = nvira + tmp_vbeta.pop(0)
total_count += 1
else:
idx = diag.argsort()
for i in idx[:nroots]:
g = np.zeros(size, dtype)
g[i] = 1.0
g = self.mask_frozen(g, kshift, const=0.0)
guess.append(g)
return guess
[docs]
def vector_to_amplitudes(self, vector, kshift, nkpts=None, nmo=None, nocc=None, kconserv=None):
if nmo is None: nmo = self.nmo
if nocc is None: nocc = self.nocc
if nkpts is None: nkpts = self.nkpts
if kconserv is None: kconserv = self.kconserv
return vector_to_amplitudes_ea(vector, kshift, nkpts, nmo, nocc, kconserv)
[docs]
def amplitudes_to_vector(self, r1, r2, kshift, kconserv=None):
if kconserv is None: kconserv = self.kconserv
return amplitudes_to_vector_ea(r1, r2, kshift, kconserv)
[docs]
def vector_size(self):
nocca, noccb = self.nocc
nmoa, nmob = self.nmo
nvira, nvirb = nmoa - nocca, nmob - noccb
nkpts = self.nkpts
#return (nvira + nvirb +
# nocca*nkpts*nvira*nkpts*nvira +
# nkpts**2*nocca*nvirb*nvira +
# nkpts**2*noccb*nvira*nvirb +
# noccb*nkpts*nvirb*nkpts*nvirb)
return (nvira + nvirb +
nocca*nkpts*nvira*(nkpts*nvira-1)//2 +
nkpts**2*nocca*nvirb*nvira +
nkpts**2*noccb*nvira*nvirb +
noccb*nkpts*nvirb*(nkpts*nvirb-1)//2)
[docs]
def make_imds(self, eris=None, t1=None, t2=None):
imds = _IMDS(self._cc, eris, t1, t2)
imds.make_ea()
return imds
class _IMDS:
def __init__(self, cc, eris=None, t1=None, t2=None):
self._cc = cc
self.verbose = cc.verbose
self.kconserv = kpts_helper.get_kconserv(cc._scf.cell, cc.kpts)
self.stdout = cc.stdout
if t1 is None:
t1 = cc.t1
self.t1 = t1
if t2 is None:
t2 = cc.t2
self.t2 = t2
if eris is None:
eris = cc.ao2mo()
self.eris = eris
self._made_shared = False
self.made_ip_imds = False
self.made_ea_imds = False
self.made_ee_imds = False
def _make_shared(self):
cput0 = (logger.process_clock(), logger.perf_counter())
t1, t2, eris = self.t1, self.t2, self.eris
self.Foo, self.FOO = kintermediates_uhf.Foo(self._cc, t1, t2, eris)
self.Fvv, self.FVV = kintermediates_uhf.Fvv(self._cc, t1, t2, eris)
self.Fov, self.FOV = kintermediates_uhf.Fov(self._cc, t1, t2, eris)
# 2 virtuals
self.Wovvo, self.WovVO, self.WOVvo, self.WOVVO = kintermediates_uhf.Wovvo(self._cc, t1, t2, eris)
self.Woovv, self.WooVV, self.WOOvv, self.WOOVV = kintermediates_uhf.Woovv(self._cc, t1, t2, eris)
self.Wovov = eris.ovov - np.asarray(eris.ovov).transpose(2,1,0,5,4,3,6)
self.WOVOV = eris.OVOV - np.asarray(eris.OVOV).transpose(2,1,0,5,4,3,6)
self.WovOV = eris.ovOV
self.WOVov = None
self._made_shared = True
logger.timer_debug1(self, 'EOM-KCCSD shared intermediates', *cput0)
return self
def make_ip(self):
if not self._made_shared:
self._make_shared()
kconserv = self.kconserv
cput0 = (logger.process_clock(), logger.perf_counter())
t1, t2, eris = self.t1, self.t2, self.eris
# 0 or 1 virtuals
self.Woooo, self.WooOO, _ , self.WOOOO = kintermediates_uhf.Woooo(self._cc, t1, t2, eris) # noqa: E501
self.Wooov, self.WooOV, self.WOOov, self.WOOOV = kintermediates_uhf.Wooov(self._cc, t1, t2, eris, kconserv) # noqa: E501
self.Woovo, self.WooVO, self.WOOvo, self.WOOVO = kintermediates_uhf.Woovo(self._cc, t1, t2, eris) # noqa: E501
self.made_ip_imds = True
logger.timer_debug1(self, 'EOM-KUCCSD IP intermediates', *cput0)
return self
def make_ea(self):
if not self._made_shared:
self._make_shared()
cput0 = (logger.process_clock(), logger.perf_counter())
t1, t2, eris = self.t1, self.t2, self.eris
# 3 or 4 virtuals
#self.Wvovv, self.WvoVV, self.WVOvv, self.WVOVV = kintermediates_uhf.Wvovv(self._cc, t1, t2, eris)
self.Wvvov, self.WvvOV, self.WVVov, self.WVVOV = kintermediates_uhf.Wvvov(self._cc, t1, t2, eris)
if eris.vvvv is not None:
self.Wvvvv, self.WvvVV, self.WVVVV = kintermediates_uhf.Wvvvv(self._cc, t1, t2, eris)
else:
self.Wvvvv = self.WvvVV = self.WVVVV = None
self.Wvvvo, self.WvvVO, self.WVVvo, self.WVVVO = kintermediates_uhf.Wvvvo(self._cc, t1, t2, eris)
self.made_ea_imds = True
logger.timer_debug1(self, 'EOM-KUCCSD EA intermediates', *cput0)
return self
def make_ee(self):
raise NotImplementedError
def get_Wvvvv(self, ka, kb, kc):
if not self.made_ea_imds:
self.make_ea()
if self.Wvvvv is None:
return kintermediates_uhf.get_Wvvvv(self._cc, self.t1, self.t2, self.eris,
ka, kb, kc)
else:
return self.Wvvvv[ka,kc,kb], self.WvvVV[ka,kc,kb], self.WVVVV[ka,kc,kb]
if __name__ == '__main__':
from pyscf.pbc import gto
from pyscf.pbc import scf
from pyscf import lo
cell = gto.Cell()
cell.atom='''
He 0.000000000000 0.000000000000 0.000000000000
He 1.685068664391 1.685068664391 1.685068664391
'''
#cell.basis = [[0, (1., 1.)], [1, (.5, 1.)]]
cell.basis = [[0, (1., 1.)], [0, (.5, 1.)]]
cell.a = '''
0.000000000, 3.370137329, 3.370137329
3.370137329, 0.000000000, 3.370137329
3.370137329, 3.370137329, 0.000000000'''
cell.unit = 'B'
cell.mesh = [5, 5, 5]
cell.build()
np.random.seed(1)
# Running HF and CCSD with 1x1x2 Monkhorst-Pack k-point mesh
kmf = scf.KUHF(cell, kpts=cell.make_kpts([1,1,3]), exxdiv=None)
nmo = cell.nao_nr()
kmf.mo_occ = np.zeros((2,3,nmo))
kmf.mo_occ[0,:,:3] = 1
kmf.mo_occ[1,:,:1] = 1
kmf.mo_energy = np.arange(nmo) + np.random.random((2,3,nmo)) * .3
kmf.mo_energy[kmf.mo_occ == 0] += 2
mo = (np.random.random((2,3,nmo,nmo)) +
np.random.random((2,3,nmo,nmo))*1j - .5-.5j)
s = kmf.get_ovlp()
kmf.mo_coeff = np.empty_like(mo)
nkpts = len(kmf.kpts)
for k in range(nkpts):
kmf.mo_coeff[0,k] = lo.orth.vec_lowdin(mo[0,k], s[k])
kmf.mo_coeff[1,k] = lo.orth.vec_lowdin(mo[1,k], s[k])
def rand_t1_t2(mycc):
nkpts = mycc.nkpts
nocca, noccb = mycc.nocc
nmoa, nmob = mycc.nmo
nvira, nvirb = nmoa - nocca, nmob - noccb
np.random.seed(1)
t1a = (np.random.random((nkpts,nocca,nvira)) +
np.random.random((nkpts,nocca,nvira))*1j - .5-.5j)
t1b = (np.random.random((nkpts,noccb,nvirb)) +
np.random.random((nkpts,noccb,nvirb))*1j - .5-.5j)
t2aa = (np.random.random((nkpts,nkpts,nkpts,nocca,nocca,nvira,nvira)) +
np.random.random((nkpts,nkpts,nkpts,nocca,nocca,nvira,nvira))*1j - .5-.5j)
kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
t2aa = t2aa - t2aa.transpose(1,0,2,4,3,5,6)
tmp = t2aa.copy()
for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
kl = kconserv[ki, kk, kj]
t2aa[ki,kj,kk] = t2aa[ki,kj,kk] - tmp[ki,kj,kl].transpose(0,1,3,2)
t2ab = (np.random.random((nkpts,nkpts,nkpts,nocca,noccb,nvira,nvirb)) +
np.random.random((nkpts,nkpts,nkpts,nocca,noccb,nvira,nvirb))*1j - .5-.5j)
t2bb = (np.random.random((nkpts,nkpts,nkpts,noccb,noccb,nvirb,nvirb)) +
np.random.random((nkpts,nkpts,nkpts,noccb,noccb,nvirb,nvirb))*1j - .5-.5j)
t2bb = t2bb - t2bb.transpose(1,0,2,4,3,5,6)
tmp = t2bb.copy()
for ki, kj, kk in kpts_helper.loop_kkk(nkpts):
kl = kconserv[ki, kk, kj]
t2bb[ki,kj,kk] = t2bb[ki,kj,kk] - tmp[ki,kj,kl].transpose(0,1,3,2)
t1 = (t1a, t1b)
t2 = (t2aa, t2ab, t2bb)
return t1, t2
from pyscf.pbc.cc import kccsd_uhf
mycc = kccsd_uhf.KUCCSD(kmf)
eris = mycc.ao2mo()
t1, t2 = rand_t1_t2(mycc)
mycc.t1 = t1
mycc.t2 = t2
kconserv = kpts_helper.get_kconserv(kmf.cell, kmf.kpts)
kgcc = kccsd.GCCSD(scf.addons.convert_to_ghf(kmf))
kccsd_eris = kccsd._make_eris_incore(kgcc, kgcc._scf.mo_coeff)
orbspin = kccsd_eris.orbspin
nkpts = mycc.nkpts
nocca, noccb = mycc.nocc
nmoa, nmob = mycc.nmo
nvira, nvirb = nmoa - nocca, nmob - noccb
kshift = 0 # excitation out of 0th k-point
nmo = nmoa + nmob
nocc = nocca + noccb
nvir = nmo - nocc
np.random.seed(0)
# IP version
myeom = EOMIP(mycc)
imds = myeom.make_imds()
imds.make_ip()
spin_r1_ip = (np.random.rand(nocc)*1j +
np.random.rand(nocc) - 0.5 - 0.5*1j)
spin_r2_ip = (np.random.rand(nkpts**2 * nocc**2 * nvir) +
np.random.rand(nkpts**2 * nocc**2 * nvir)*1j - 0.5 - 0.5*1j)
spin_r2_ip = spin_r2_ip.reshape(nkpts, nkpts, nocc, nocc, nvir)
spin_r2_ip = eom_kgccsd.enforce_2p_spin_ip_doublet(spin_r2_ip, kconserv, kshift, orbspin)
r1, r2 = eom_kgccsd.spin2spatial_ip_doublet(spin_r1_ip, spin_r2_ip, kconserv, kshift, orbspin)
vector = myeom.amplitudes_to_vector(r1, r2, kshift)
vector = myeom.matvec(vector, kshift=kshift, imds=imds)
Hr1, Hr2 = myeom.vector_to_amplitudes(vector, 0, nkpts, (nmoa, nmob), (nocca, noccb))
Hr1a, Hr1b = Hr1
Hr2aaa, Hr2baa, Hr2abb, Hr2bbb = Hr2
print('ip Hr1a', abs(lib.fp(Hr1a) - (-0.34462696543560045-1.6104596956729178j)))
print('ip Hr1b', abs(lib.fp(Hr1b) - (-0.055793611517250929+0.22169994342782473j)))
print('ip Hr2aaa', abs(lib.fp(Hr2aaa) - (0.692705827672665420-1.958639508839846943j)))
print('ip Hr2baa', abs(lib.fp(Hr2baa) - (2.892194153603884654+2.039530776282815872j)))
print('ip Hr2abb', abs(lib.fp(Hr2abb) - (1.618257685489421727-5.489218743953674817j)))
print('ip Hr2bbb', abs(lib.fp(Hr2bbb) - (0.479835513829048044+0.108406393138471210j)))
# EA version
myeom = EOMEA(mycc)
imds = myeom.make_imds()
imds.make_ea()
spin_r1_ea = (np.random.rand(nvir)*1j +
np.random.rand(nvir) - 0.5 - 0.5*1j)
spin_r2_ea = (np.random.rand(nkpts**2 * nocc * nvir**2) +
np.random.rand(nkpts**2 * nocc * nvir**2)*1j - 0.5 - 0.5*1j)
spin_r2_ea = spin_r2_ea.reshape(nkpts, nkpts, nocc, nvir, nvir)
spin_r2_ea = eom_kgccsd.enforce_2p_spin_ea_doublet(spin_r2_ea, kconserv, kshift, orbspin)
r1, r2 = eom_kgccsd.spin2spatial_ea_doublet(spin_r1_ea, spin_r2_ea, kconserv, kshift, orbspin)
vector = myeom.amplitudes_to_vector(r1, r2, kshift)
vector = myeom.matvec(vector, kshift=kshift, imds=imds)
Hr1, Hr2 = myeom.vector_to_amplitudes(vector, 0, nkpts, (nmoa, nmob), (nocca, noccb))
Hr1a, Hr1b = Hr1
Hr2aaa, Hr2aba, Hr2bab, Hr2bbb = Hr2
print('ea Hr1a', abs(lib.fp(Hr1a) - (-0.081373075311041126-0.51422895644026023j)))
print('ea Hr1b', abs(lib.fp(Hr1b) - (-0.39518588661294807-1.3063424820239824j)) )
print('ea Hr2aaa',abs(lib.fp(Hr2aaa) - (-2.6502079691200251-0.61302655915003545j)) )
print('ea Hr2aba',abs(lib.fp(Hr2aba) - (5.5723208649566036-5.4202659143496286j)) )
print('ea Hr2bab',abs(lib.fp(Hr2bab) - (-1.2822293707887937+0.3026476580141586j)) )
print('ea Hr2bbb',abs(lib.fp(Hr2bbb) - (-4.0202809577487253-0.46985725132191702j)) )