def build_Wmbje(self): Wmbje = -1.0 * (self.get_MO('ovov').copy()) Wmbje -= ndot('jf,mbfe->mbje', self.t1, self.get_MO('ovvv')) Wmbje += ndot('nb,mnje->mbje', self.t1, self.get_MO('ooov')) tmp = (0.5 * self.t2) tmp += np.einsum('jf,nb->jnfb', self.t1, self.t1) Wmbje += ndot('jnfb,mnfe->mbje', tmp, self.get_MO('oovv')) return Wmbje
def build_Hoo(self): """ <m|Hbar|i> = F_mi + 0.5 * t_ie F_me = f_mi + t_ie f_me + t_ne <mn||ie> + tau_inef <mn||ef> """ self.Hoo = self.get_F('oo').copy() self.Hoo += ndot('ie,me->mi', self.t1, self.get_F('ov')) self.Hoo += ndot('ne,mnie->mi', self.t1, self.Looov) self.Hoo += ndot('inef,mnef->mi', self.build_tau(), self.Loovv) return self.Hoo
def build_Hvv(self): """ <a|Hbar|e> = F_ae - 0.5 * t_ma F_me = f_ae - t_ma f_me + t_mf <am||ef> - tau_mnfa <mn||fe> """ self.Hvv = self.get_F('vv').copy() self.Hvv -= ndot('ma,me->ae', self.t1, self.get_F('ov')) self.Hvv += ndot('mf,amef->ae', self.t1, self.Lvovv) self.Hvv -= ndot('mnfa,mnfe->ae', self.build_tau(), self.Loovv) return self.Hvv
def build_Hoooo(self): """ <mn|Hbar|ij> = W_mnij + 0.25 * tau_ijef <mn||ef> = <mn||ij> + P(ij) t_je <mn||ie> + 0.5 * tau_ijef <mn||ef> """ self.Hoooo = self.get_MO('oooo').copy() self.Hoooo += ndot('je,mnie->mnij', self.t1, self.get_MO('ooov')) self.Hoooo += ndot('ie,mnej->mnij', self.t1, self.get_MO('oovo')) self.Hoooo += ndot('ijef,mnef->mnij', self.build_tau(), self.get_MO('oovv')) return self.Hoooo
def build_Hvvvv(self): """ <ab|Hbar|ef> = W_abef + 0.25 * tau_mnab <mn||ef> = <ab||ef> - P(ab) t_mb <am||ef> + 0.5 * tau_mnab <mn||ef> """ self.Hvvvv = self.get_MO('vvvv').copy() self.Hvvvv -= ndot('mb,amef->abef', self.t1, self.get_MO('vovv')) self.Hvvvv -= ndot('ma,bmfe->abef', self.t1, self.get_MO('vovv')) self.Hvvvv += ndot('mnab,mnef->abef', self.build_tau(), self.get_MO('oovv')) return self.Hvvvv
def build_Hovov(self): """ <mb|Hbar|je> = - <mb|Hbar|ej> = <mb||je> + t_jf <bm||ef> - t_nb <mn||je> - (t_jnfb + t_jf t_nb) <nm||ef> """ self.Hovov = self.get_MO('ovov').copy() self.Hovov += ndot('jf,bmef->mbje', self.t1, self.get_MO('vovv')) self.Hovov -= ndot('nb,mnje->mbje', self.t1, self.get_MO('ooov')) self.Hovov -= ndot('jnfb,nmef->mbje', self.build_tau(), self.get_MO('oovv')) return self.Hovov
def build_Hovvo(self): """ <mb|Hbar|ej> = W_mbej - 0.5 * t_jnfb <mn||ef> = <mb||ej> + t_jf <mb||ef> - t_nb <mn||ej> - (t_jnfb + t_jf t_nb) <nm||fe> """ self.Hovvo = self.get_MO('ovvo').copy() self.Hovvo += ndot('jf,mbef->mbej', self.t1, self.get_MO('ovvv')) self.Hovvo -= ndot('nb,mnej->mbej', self.t1, self.get_MO('oovo')) self.Hovvo -= ndot('jnfb,nmfe->mbej', self.build_tau(), self.get_MO('oovv')) self.Hovvo += ndot('jnbf,nmfe->mbej', self.t2, self.Loovv) return self.Hovvo
def build_Wmbej(self): Wmbej = self.get_MO('ovvo').copy() Wmbej += ndot('jf,mbef->mbej', self.t1, self.get_MO('ovvv')) Wmbej -= ndot('nb,mnej->mbej', self.t1, self.get_MO('oovo')) tmp = (0.5 * self.t2) tmp += np.einsum('jf,nb->jnfb', self.t1, self.t1) Wmbej -= ndot('jnfb,mnef->mbej', tmp, self.get_MO('oovv')) Wmbej += ndot( 'njfb,mnef->mbej', self.t2, self.get_MO('oovv'), prefactor=1.0) Wmbej += ndot( 'njfb,mnfe->mbej', self.t2, self.get_MO('oovv'), prefactor=-0.5) return Wmbej
def build_Wmnij(self): Wmnij = self.get_MO('oooo').copy() Wmnij += ndot('je,mnie->mnij', self.t1, self.get_MO('ooov')) Wmnij += ndot('ie,mnej->mnij', self.t1, self.get_MO('oovo')) # prefactor of 1 instead of 0.5 below to fold the last term of # 0.5 * tau_ijef Wabef in Wmnij contraction: 0.5 * tau_mnab Wmnij_mnij Wmnij += ndot( 'ijef,mnef->mnij', self.build_tau(), self.get_MO('oovv'), prefactor=1.0) return Wmnij
def pseudoresponse(self, hand): polar1 = 0 polar2 = 0 if hand == 'right': z1 = self.x1 ; z2 = self.x2 else: z1 = self.y1 ; z2 = self.y2 # To match the pseudoresponse values with PSI4 polar1 += ndot('ia,ai->', z1, self.build_Avo(), prefactor=2.0) tmp = self.pertbar_ijab + self.pertbar_ijab.swapaxes(0,1).swapaxes(2,3) polar2 += ndot('ijab,ijab->', z2, tmp, prefactor=2.0) polar2 += ndot('ijba,ijab->', z2, tmp, prefactor=-1.0) return -2.0 * (polar1 + polar2)
def build_Fmi(self): Fmi = self.get_F('oo').copy() Fmi += ndot('ie,me->mi', self.t1, self.get_F('ov'), prefactor=0.5) Fmi += ndot('ne,mnie->mi', self.t1, self.get_MO('ooov'), prefactor=2.0) Fmi += ndot( 'ne,mnei->mi', self.t1, self.get_MO('oovo'), prefactor=-1.0) Fmi += ndot( 'inef,mnef->mi', self.build_tilde_tau(), self.get_MO('oovv'), prefactor=2.0) Fmi += ndot( 'inef,mnfe->mi', self.build_tilde_tau(), self.get_MO('oovv'), prefactor=-1.0) return Fmi
def build_Fae(self): Fae = self.get_F('vv').copy() Fae -= ndot('me,ma->ae', self.get_F('ov'), self.t1, prefactor=0.5) Fae += ndot('mf,mafe->ae', self.t1, self.get_MO('ovvv'), prefactor=2.0) Fae += ndot( 'mf,maef->ae', self.t1, self.get_MO('ovvv'), prefactor=-1.0) Fae -= ndot( 'mnaf,mnef->ae', self.build_tilde_tau(), self.get_MO('oovv'), prefactor=2.0) Fae -= ndot( 'mnaf,mnfe->ae', self.build_tilde_tau(), self.get_MO('oovv'), prefactor=-1.0) return Fae
def build_sigma1(self, B1, B2): """ Compute the contributions to <ia|Hbar*B|0> Parameters ---------- B1: array like, shape(ndocc, nvir) The first nsingles elements of a guess vector reshaped to (o,v) B2: array like, shape(ndocc,ndocc,nvir,nvir) The last ndoubles elements of a guess vector reshaped to (o,o,v,v) Returns ------- S1: ndarray shape(ndocc, nvir) Examples -------- >>> # Get some vectors as cols of a 2D numpy array and orthogonalize them >>> c = np.random.rand(eom.nsingles + eom.ndoubles, 2) >>> c, = np.linalg.qr(c) >>> # Slice out the singles, doubles blocks of the first vector and reshape >>> B1 = c[:,:nsingles].reshape(eom.ndocc, eom.nvir) >>> B2 = c[:,nsingles:].reshape(eom.ndocc, eom.ndocc, eom.nvir, eom.nvir) >>> S1 = eom.build_sigma1(B1, B2) """ S1 = ndot('ie,ae->ia', B1, self.Hvv) S1 -= ndot('mi,ma->ia', self.Hoo, B1) S1 += ndot('maei,me->ia', self.Hovvo, B1, prefactor=2.0) S1 += ndot('maie,me->ia', self.Hovov, B1, prefactor=-1.0) S1 += ndot('miea,me->ia', B2, self.Hov, prefactor=2.0) S1 += ndot('imea,me->ia', B2, self.Hov, prefactor=-1.0) S1 += ndot('imef,amef->ia', B2, self.Hvovv, prefactor=2.0) S1 += ndot('imef,amfe->ia', B2, self.Hvovv, prefactor=-1.0) S1 -= ndot('mnie,mnae->ia', self.Hooov, B2, prefactor=2.0) S1 -= ndot('nmie,mnae->ia', self.Hooov, B2, prefactor=-1.0) return S1
def build_Avo(self): Avo = self.get_pert('vo').copy() Avo += ndot('ae,ie->ai', self.get_pert('vv'), self.t1) Avo -= ndot('ma,mi->ai', self.t1, self.get_pert('oo')) Avo += ndot('miea,me->ai', self.t2, self.get_pert('ov'), prefactor=2.0) Avo += ndot('imea,me->ai', self.t2, self.get_pert('ov'), prefactor=-1.0) tmp = ndot('ie,ma->imea', self.t1, self.t1) Avo -= ndot('imea,me->ai', tmp, self.get_pert('ov')) return Avo
def r_l1(self, F, ERI, L, t1, t2, l1, l2): if self.precision == "mixed": Hvv = np.float32(self.build_Hvv(F, L, t1, t2)) Hoo = np.float32(self.build_Hoo(F, ERI, L, t1, t2)) Hovvo = np.float32(self.build_Hovvo(ERI, L, t1, t2)) Hovov = np.float32(self.build_Hovov(ERI, t1, t2)) Hvvvo = np.float32(self.build_Hvvvo(F, ERI, L, t1, t2)) Hovoo = np.float32(self.build_Hovoo(F, ERI, L, t1, t2)) Hvovv = np.float32(self.build_Hvovv(ERI, t1)) Hooov = np.float32(self.build_Hooov(ERI, t1)) else: Hvv = self.build_Hvv(F, L, t1, t2) Hoo = self.build_Hoo(F, ERI, L, t1, t2) Hovvo = self.build_Hovvo(ERI, L, t1, t2) Hovov = self.build_Hovov(ERI, t1, t2) Hvvvo = self.build_Hvvvo(F, ERI, L, t1, t2) Hovoo = self.build_Hovoo(F, ERI, L, t1, t2) Hvovv = self.build_Hvovv(ERI, t1) Hooov = self.build_Hooov(ERI, t1) terms = [] terms.append(2.0 * self.build_Hov(F, L, t1).copy()) terms.append(ndot('ie,ea->ia', l1, Hvv)) terms.append(ndot('im,ma->ia', Hoo, l1, prefactor=-1.0)) Hovvo_spinad = 2.0 * Hovvo - Hovov.swapaxes(2, 3) terms.append(ndot('ieam,me->ia', Hovvo_spinad, l1)) terms.append(ndot('imef,efam->ia', l2, Hvvvo)) terms.append(ndot('iemn,mnae->ia', Hovoo, l2, prefactor=-1.0)) Hvovv_spinad = 2.0 * Hvovv - Hvovv.swapaxes(2, 3) terms.append( ndot('eifa,ef->ia', Hvovv_spinad, self.build_Gvv(t2, l2), prefactor=-1.0)) Hooov_spinad = 2.0 * Hooov - Hooov.swapaxes(0, 1) terms.append( ndot('mina,mn->ia', Hooov_spinad, self.build_Goo(t2, l2), prefactor=-1.0)) r_l1 = careful_sum(terms, self.precision) return r_l1
def r_T1(self, F, ERI, L, t1, t2, Fae, Fme, Fmi): terms = [] terms.append(self.get_F(F, 'ov').copy()) terms.append(ndot('ie,ae->ia', t1, Fae)) terms.append(ndot('ma,mi->ia', t1, Fmi, prefactor=-1.0)) t2_spinad = 2.0 * t2 - t2.swapaxes(2, 3) terms.append(ndot('imae,me->ia', t2_spinad, Fme)) terms.append(ndot('nf,nafi->ia', t1, self.get_ERI(L, 'ovvo'))) terms.append( ndot('mief,maef->ia', t2_spinad, self.get_ERI(ERI, 'ovvv'))) terms.append( ndot('mnae,nmei->ia', t2, self.get_ERI(L, 'oovo'), prefactor=-1.0)) r_T1 = careful_sum(terms, self.precision) return r_T1
def build_sigma2(self, B1, B2): """ Compute the contributions to <ijab|Hbar*B|0>: Parameters ---------- B1: array like, shape(ndocc, nvir) The first nsingles elements of a guess vector reshaped to (o,v) B2: array like, shape(ndocc,ndocc,nvir,nvir) The last ndoubles elements of a guess vector reshaped to (o,o,v,v) Returns ------- S2: ndarray shape(ndocc, ndocc, nvir, nvir) Examples -------- >>> # Get some vectors as cols of a 2D numpy array and orthogonalize them >>> c = np.random.rand(eom.nsingles + eom.ndoubles, 2) >>> c, = np.linalg.qr(c) >>> # Slice out the singles, doubles blocks of the first vector and reshape >>> B1 = c[:,:nsingles].reshape(eom.ndocc, eom.nvir) >>> B2 = c[:,nsingles:].reshape(eom.ndocc, eom.ndocc, eom.nvir, eom.nvir) >>> S2 = eom.build_sigma2(B1, B2) """ S_2 = ndot('ie,abej->ijab', B1, self.Hvvvo) S_2 -= ndot('mbij,ma->ijab', self.Hovoo, B1) Zvv = ndot("amef,mf->ae", self.Hvovv, B1, prefactor=2.0) Zvv += ndot("amfe,mf->ae", self.Hvovv, B1, prefactor=-1.0) Zvv -= ndot('nmaf,nmef->ae', B2, self.Loovv) S_2 += ndot('ijeb,ae->ijab', self.t2, Zvv) Zoo = ndot('mnie,ne->mi', self.Hooov, B1, prefactor=-2.0) Zoo -= ndot('nmie,ne->mi', self.Hooov, B1, prefactor=-1.0) Zoo -= ndot('mnef,inef->mi', self.Loovv, B2) S_2 += ndot('mi,mjab->ijab', Zoo, self.t2) S_2 += ndot('ijeb,ae->ijab', B2, self.Hvv) S_2 -= ndot('mi,mjab->ijab', self.Hoo, B2) S_2 += ndot('mnij,mnab->ijab', self.Hoooo, B2, prefactor=0.5) S_2 += ndot('ijef,abef->ijab', B2, self.Hvvvv, prefactor=0.5) S_2 -= ndot('imeb,maje->ijab', B2, self.Hovov) S_2 -= ndot('imea,mbej->ijab', B2, self.Hovvo) S_2 += ndot('miea,mbej->ijab', B2, self.Hovvo, prefactor=2.0) S_2 += ndot('miea,mbje->ijab', B2, self.Hovov, prefactor=-1.0) return S_2 + S_2.swapaxes(0, 1).swapaxes(2, 3)
def build_Aoo(self): Aoo = self.get_pert('oo').copy() Aoo += ndot('ie,me->mi', self.t1, self.get_pert('ov')) return Aoo
def build_Goo(self): self.Goo = 0 self.Goo += ndot('mjab,ijab->mi', self.t2, self.l2) return self.Goo
def inhomogenous_y1(self): # Inhomogenous terms appearing in Y1 equations # <O|A_bar|phi^a_i> r_y1 = 2.0 * self.build_Aov().copy() # <O|L1(0)|A_bar|phi^a_i> r_y1 -= ndot('im,ma->ia', self.build_Aoo(), self.l1) r_y1 += ndot('ie,ea->ia', self.l1, self.build_Avv()) # <O|L2(0)|A_bar|phi^a_i> r_y1 += ndot('imfe,feam->ia', self.l2, self.build_Avvvo()) r_y1 -= ndot('ienm,mnea->ia', self.build_Aovoo(), self.l2, prefactor=0.5) r_y1 -= ndot('iemn,mnae->ia', self.build_Aovoo(), self.l2, prefactor=0.5) # <O|[Hbar(0), X1]|phi^a_i> r_y1 += ndot('imae,me->ia', self.Loovv, self.x1, prefactor=2.0) # <O|L1(0)|[Hbar(0), X1]|phi^a_i> tmp = ndot('ma,ie->miae', self.Hov, self.l1, prefactor=-1.0) tmp -= ndot('ma,ie->miae', self.l1, self.Hov) tmp -= ndot('mina,ne->miae', self.Hooov, self.l1, prefactor=2.0) tmp -= ndot('imna,ne->miae', self.Hooov, self.l1, prefactor=-1.0) tmp -= ndot('imne,na->miae', self.Hooov, self.l1, prefactor=2.0) tmp -= ndot('mine,na->miae', self.Hooov, self.l1, prefactor=-1.0) tmp += ndot('fmae,if->miae', self.Hvovv, self.l1, prefactor=2.0) tmp += ndot('fmea,if->miae', self.Hvovv, self.l1, prefactor=-1.0) tmp += ndot('fiea,mf->miae', self.Hvovv, self.l1, prefactor=2.0) tmp += ndot('fiae,mf->miae', self.Hvovv, self.l1, prefactor=-1.0) r_y1 += ndot('miae,me->ia', tmp, self.x1) # <O|L1(0)|[Hbar(0), X2]|phi^a_i> tmp = ndot('mnef,nf->me', self.x2, self.l1, prefactor=2.0) tmp += ndot('mnfe,nf->me', self.x2, self.l1, prefactor=-1.0) r_y1 += ndot('imae,me->ia', self.Loovv, tmp) r_y1 -= ndot('ni,na->ia', self.build_Goo(self.x2, self.Loovv), self.l1) r_y1 += ndot('ie,ea->ia', self.l1, self.build_Gvv(self.x2, self.Loovv)) # <O|L2(0)|[Hbar(0), X1]|phi^a_i> tmp = ndot('nief,mfna->iema', self.l2, self.Hovov, prefactor=-1.0) tmp -= ndot('ifne,nmaf->iema', self.Hovov, self.l2) tmp -= ndot('inef,mfan->iema', self.l2, self.Hovvo) tmp -= ndot('ifen,nmfa->iema', self.Hovvo, self.l2) tmp += ndot('imfg,fgae->iema', self.l2, self.Hvvvv, prefactor=0.5) tmp += ndot('imgf,fgea->iema', self.l2, self.Hvvvv, prefactor=0.5) tmp += ndot('imno,onea->iema', self.Hoooo, self.l2, prefactor=0.5) tmp += ndot('mino,noea->iema', self.Hoooo, self.l2, prefactor=0.5) r_y1 += ndot('iema,me->ia', tmp, self.x1) tmp = ndot('nb,fb->nf', self.x1, self.build_Gvv(self.t2, self.l2)) r_y1 += ndot('inaf,nf->ia', self.Loovv, tmp) tmp = ndot('me,fa->mefa', self.x1, self.build_Gvv(self.t2, self.l2)) r_y1 += ndot('mief,mefa->ia', self.Loovv, tmp) tmp = ndot('me,ni->meni', self.x1, self.build_Goo(self.t2, self.l2)) r_y1 -= ndot('meni,mnea->ia', tmp, self.Loovv) tmp = ndot('jf,nj->fn', self.x1, self.build_Goo(self.t2, self.l2)) r_y1 -= ndot('inaf,fn->ia', self.Loovv, tmp) # <O|L2(0)|[Hbar(0), X2]|phi^a_i> r_y1 -= ndot('mi,ma->ia', self.build_Goo(self.x2, self.l2), self.Hov) r_y1 += ndot('ie,ea->ia', self.Hov, self.build_Gvv(self.x2, self.l2)) tmp = ndot('imfg,mnef->igne',self.l2, self.x2) r_y1 -= ndot('igne,gnea->ia', tmp, self.Hvovv) tmp = ndot('mifg,mnef->igne',self.l2, self.x2) r_y1 -= ndot('igne,gnae->ia', tmp, self.Hvovv) tmp = ndot('mnga,mnef->gaef',self.l2, self.x2) r_y1 -= ndot('gief,gaef->ia', self.Hvovv, tmp) tmp = ndot('gmae,mnef->ganf',self.Hvovv, self.x2, prefactor=2.0) tmp += ndot('gmea,mnef->ganf',self.Hvovv, self.x2, prefactor=-1.0) r_y1 += ndot('nifg,ganf->ia', self.l2, tmp) r_y1 -= ndot('giea,ge->ia', self.Hvovv, self.build_Gvv(self.l2, self.x2), prefactor=2.0) r_y1 -= ndot('giae,ge->ia', self.Hvovv, self.build_Gvv(self.l2, self.x2), prefactor=-1.0) tmp = ndot('oief,mnef->oimn', self.l2, self.x2) r_y1 += ndot('oimn,mnoa->ia', tmp, self.Hooov) tmp = ndot('mofa,mnef->oane', self.l2, self.x2) r_y1 += ndot('inoe,oane->ia', self.Hooov, tmp) tmp = ndot('onea,mnef->oamf', self.l2, self.x2) r_y1 += ndot('miof,oamf->ia', self.Hooov, tmp) r_y1 -= ndot('mioa,mo->ia', self.Hooov, self.build_Goo(self.x2, self.l2), prefactor=2.0) r_y1 -= ndot('imoa,mo->ia', self.Hooov, self.build_Goo(self.x2, self.l2), prefactor=-1.0) tmp = ndot('imoe,mnef->ionf', self.Hooov, self.x2, prefactor=-2.0) tmp -= ndot('mioe,mnef->ionf', self.Hooov, self.x2, prefactor=-1.0) r_y1 += ndot('ionf,nofa->ia', tmp, self.l2) return r_y1
def build_Hvovv(self, t1): """ <am|Hbar|ef> = <am||ef> - t_na <nm||ef> """ Hvovv = self.get_MO_sp('vovv').copy() Hvovv -= ndot('na,nmef->amef', t1, self.get_MO_sp('oovv')) return Hvovv
def update_X(self): # X1 and X2 amplitudes are the Fourier analogues of first order perturbed T1 and T2 amplitudes, # (eq. 65, reference 1). For a given perturbation, these amplitudes are frequency dependent and # can be obtained by solving a linear system of equations, (Hbar(0) - omgea * I)X = Hbar(1) # Refer to eq 70 of reference 1. Writing t_mu^(1)(omega) as X_mu and Hbar^(1)(omega) as A_bar, # X1 equations: # omega * X_ia = <phi^a_i|A_bar|O> + <phi^a_i|Hbar^(0)|phi^c_k> * X_kc + <phi^a_i|Hbar^(0)|phi^cd_kl> * X_klcd # X2 equations: # omega * X_ijab = <phi^ab_ij|A_bar|O> + <phi^ab_ij|Hbar^(0)|phi^c_k> * X_kc + <phi^ab_ij|Hbar^(0)|phi^cd_kl> * X_klcd # Note that the RHS terms have exactly the same structure as EOM-CCSD sigma equations. # Spin Orbital expressions (Einstein summation): # X1 equations: # -omega * X_ia + A_bar_ai + X_ie * Hvv_ae - X_ma * Hoo_mi + X_me * Hovvo_maei + X_miea * Hov_me # + 0.5 * X_imef * Hvovv_amef - 0.5 * X_mnae * Hooov_mnie = 0 # X2 equations: # -omega * X_ijab + A_bar_abij + P(ij) X_ie * Hvvvo_abej - P(ab) X_ma * Hovoo_mbij # + P(ab) X_mf * Hvovv_amef * t_ijeb - P(ij) X_ne * Hooov_mnie * t_mjab # + P(ab) X_ijeb * Hvv_ae - P(ij) X_mjab * Hov_mi + 0.5 * X_mnab * Hoooo_mnij + 0.5 * X_ijef * Hvvvv_abef # + P(ij) P(ab) X_miea * Hovvo_mbej - 0.5 * P(ab) X_mnaf * Hoovv_mnef * t_ijeb # - 0.5 * P(ij) X_inef * Hoovv_mnef * t_mjab # It should be noted that in order to avoid construction of 3-body Hbar terms appearing in X2 equations like, # Hvvooov_bamjif = Hvovv_amef * t_ijeb, # Hvvooov_banjie = Hooov_mnie * t_mjab, # Hvoooov_bmnjif = Hoovv_mnef * t_ijeb, # Hvvoovv_banjef = Hoovv_mnef * t_mjab, # we make use of Z intermediates: # Zvv_ae = - Hooov_amef * X_mf - 0.5 * X_mnaf * Hoovv_mnef, # Zoo_mi = - X_ne * Hooov_mnie - 0.5 * Hoovv_mnef * X_inef, # And then contract Z with T2 amplitudes. # X1 equations r_x1 = self.build_Avo().swapaxes(0,1).copy() r_x1 -= self.omega * self.x1.copy() r_x1 += ndot('ie,ae->ia', self.x1, self.Hvv) r_x1 -= ndot('mi,ma->ia', self.Hoo, self.x1) r_x1 += ndot('maei,me->ia', self.Hovvo, self.x1, prefactor=2.0) r_x1 += ndot('maie,me->ia', self.Hovov, self.x1, prefactor=-1.0) r_x1 += ndot('miea,me->ia', self.x2, self.Hov, prefactor=2.0) r_x1 += ndot('imea,me->ia', self.x2, self.Hov, prefactor=-1.0) r_x1 += ndot('imef,amef->ia', self.x2, self.Hvovv, prefactor=2.0) r_x1 += ndot('imef,amfe->ia', self.x2, self.Hvovv, prefactor=-1.0) r_x1 -= ndot('mnie,mnae->ia', self.Hooov, self.x2, prefactor=2.0) r_x1 -= ndot('nmie,mnae->ia', self.Hooov, self.x2, prefactor=-1.0) # X1 equations over! # X2 equations # Final r_x2_ijab = r_x2_ijab + r_x2_jiba r_x2 = self.build_Avvoo().swapaxes(0,2).swapaxes(1,3).copy() # a factor of 0.5 because of the comment just above # and due to the fact that X2_ijab = X2_jiba r_x2 -= 0.5 * self.omega * self.x2 r_x2 += ndot('ie,abej->ijab', self.x1, self.Hvvvo) r_x2 -= ndot('mbij,ma->ijab', self.Hovoo, self.x1) r_x2 += ndot('ijeb,ae->ijab', self.x2, self.Hvv) r_x2 -= ndot('mi,mjab->ijab', self.Hoo, self.x2) r_x2 += ndot('mnij,mnab->ijab', self.Hoooo, self.x2, prefactor=0.5) r_x2 += ndot('ijef,abef->ijab', self.x2, self.Hvvvv, prefactor=0.5) r_x2 += ndot('miea,mbej->ijab', self.x2, self.Hovvo, prefactor=2.0) r_x2 += ndot('miea,mbje->ijab', self.x2, self.Hovov, prefactor=-1.0) r_x2 -= ndot('imeb,maje->ijab', self.x2, self.Hovov) r_x2 -= ndot('imea,mbej->ijab', self.x2, self.Hovvo) r_x2 += ndot('mi,mjab->ijab', self.build_Zoo(), self.t2) r_x2 += ndot('ijeb,ae->ijab', self.t2, self.build_Zvv()) # X2 equations over! old_x2 = self.x2.copy() old_x1 = self.x1.copy() # update X1 and X2 self.x1 += r_x1/self.Dia # Final r_x2_ijab = r_x2_ijab + r_x2_jiba tmp = r_x2/self.Dijab self.x2 += tmp + tmp.swapaxes(0,1).swapaxes(2,3) # Calcuate rms with the residual rms = 0 rms += np.einsum('ia,ia->', old_x1 - self.x1, old_x1 - self.x1) rms += np.einsum('ijab,ijab->', old_x2 - self.x2, old_x2 - self.x2) return np.sqrt(rms)
def build_Avvvo(self): Avvvo = 0 Avvvo -= ndot('miab,me->abei', self.t2, self.get_pert('ov')) return Avvvo
def build_Zvv(self): Zvv = 0 Zvv += ndot('amef,mf->ae', self.Hvovv, self.x1, prefactor=2.0) Zvv += ndot('amfe,mf->ae', self.Hvovv, self.x1, prefactor=-1.0) Zvv -= ndot('mnaf,mnef->ae', self.x2, self.Loovv) return Zvv
def r_l2(self, F, t1, t2, l1, l2): r_l2 = np.float64(self.build_Loovv().copy()) tmp = ndot('ia,jb->ijab', l1, self.build_Hov(F, t1), prefactor=2.0) tmp -= ndot('ja,ib->ijab', l1, self.build_Hov(F, t1)) r_l2 += np.float64(tmp) r_l2 += np.float64(ndot('ijeb,ea->ijab', l2, self.build_Hvv(F, t1, t2))) r_l2 -= np.float64(ndot('im,mjab->ijab', self.build_Hoo(F, t1, t2), l2)) r_l2 += np.float64( ndot('ijmn,mnab->ijab', self.build_Hoooo(t1, t2), l2, prefactor=0.5)) r_l2 += np.float64( ndot('ijef,efab->ijab', l2, self.build_Hvvvv(t1, t2), prefactor=0.5)) tmp = ndot('ie,ejab->ijab', l1, self.build_Hvovv(t1), prefactor=2.0) tmp += ndot('ie,ejba->ijab', l1, self.build_Hvovv(t1), prefactor=-1.0) r_l2 += np.float64(tmp) tmp = ndot('mb,jima->ijab', l1, self.build_Hooov(t1), prefactor=2.0) tmp += ndot('mb,ijma->ijab', l1, self.build_Hooov(t1), prefactor=-1.0) r_l2 -= np.float64(tmp) tmp = ndot('ieam,mjeb->ijab', self.build_Hovvo(t1, t2), l2, prefactor=2.0) tmp += ndot('iema,mjeb->ijab', self.build_Hovov(t1, t2), l2, prefactor=-1.0) r_l2 += np.float64(tmp) r_l2 -= np.float64( ndot('mibe,jema->ijab', l2, self.build_Hovov(t1, t2))) r_l2 -= np.float64( ndot('mieb,jeam->ijab', l2, self.build_Hovvo(t1, t2))) r_l2 += np.float64( ndot('ijeb,ae->ijab', self.build_Loovv(), self.build_Gvv(t2, l2))) r_l2 -= np.float64( ndot('mi,mjab->ijab', self.build_Goo(t2, l2), self.build_Loovv())) return r_l2
def update(self): """ l1 and l2 equations can be obtained by taking the derivative of the CCSD Lagrangian wrt. t1 and t2 amplitudes respectively. (Einstein summation): l1: <o|Hbar|phi^a_i> + l_kc * <phi^c_k|Hbar|phi^a_i> + l_klcd * <phi^cd_kl|Hbar|phi^a_i> = 0 l2: <o|Hbar|phi^ab_ij> + l_kc * <phi^c_k|Hbar|phi^ab_ij> + l_klcd * <phi^cd_kl|Hbar|phi^ab_ij> = 0 In Spin orbitals: l1: Hov_ia + l_ie * Hvv_ae - l_ma * Hoo_im + l_me * Hovvo_ieam + 0.5 * l_imef * Hvvvo_efam - 0.5 * l_mnae Hovoo_iemn - Gvv_ef * Hvovv_eifa - Goo_mn * Hooov_mina = 0 where, Goo_mn = 0.5 * t_mjab * l_njab, Gvv_ef = - 0.5 * l_ijeb * t_ijfb Intermediates Goo and Gvv have been built to bypass the construction of 3-body Hbar terms like, l1 <-- Hvvooov_beilka * l_lkbe l1 <-- Hvvooov_cbijna * l_jncb l2: <ij||ab> + P(ab) l_ijae * Hov_eb - P(ij) l_imab * Hoo_jm + 0.5 * l_mnab * Hoooo_ijmn + 0.5 * Hvvvv_efab l_ijef + P(ij) l_ie * Hvovv_ejab - P(ab) l_ma * Hooov_ijmb + P(ij)P(ab) l_imae * Hovvo_jebm + P(ij)P(ab) l_ia * Hov_jb + P(ab) <ij||ae> * Gvv_be - P(ij) <im||ab> * Goo_mj Here we are using the unitary group approach (UGA) to derive spin adapted equations, please refer to chapter 13 of reference 2 and notes in the current folder for more details. Lambda equations derived using UGA differ from the regular spin factorizd equations (PSI4) as follows: l_ia(UGA) = 2.0 * l_ia(PSI4) l_ijab(UGA) = 2.0 * (2.0 * l_ijab - l_ijba) The residual equations (without the preconditioner) follow the same relations as above. Ex. the inhomogenous terms in l1 and l2 equations in UGA are 2 * Hov_ia and 2.0 * (2.0 * <ij|ab> - <ij|ba>) respectively as opposed to Hov_ia and <ij|ab> in PSI4. """ # l1 equations r_l1 = 2.0 * self.Hov.copy() r_l1 += ndot('ie,ea->ia', self.l1, self.Hvv) r_l1 -= ndot('im,ma->ia', self.Hoo, self.l1) r_l1 += ndot('ieam,me->ia', self.Hovvo, self.l1, prefactor=2.0) r_l1 += ndot('iema,me->ia', self.Hovov, self.l1, prefactor=-1.0) r_l1 += ndot('imef,efam->ia', self.l2, self.Hvvvo) r_l1 -= ndot('iemn,mnae->ia', self.Hovoo, self.l2) r_l1 -= ndot( 'eifa,ef->ia', self.Hvovv, self.build_Gvv(), prefactor=2.0) r_l1 -= ndot( 'eiaf,ef->ia', self.Hvovv, self.build_Gvv(), prefactor=-1.0) r_l1 -= ndot( 'mina,mn->ia', self.Hooov, self.build_Goo(), prefactor=2.0) r_l1 -= ndot( 'imna,mn->ia', self.Hooov, self.build_Goo(), prefactor=-1.0) # l2 equations # Final r_l2_ijab = r_l2_ijab + r_l2_jiba r_l2 = self.Loovv.copy() r_l2 += ndot('ia,jb->ijab', self.l1, self.Hov, prefactor=2.0) r_l2 -= ndot('ja,ib->ijab', self.l1, self.Hov) r_l2 += ndot('ijeb,ea->ijab', self.l2, self.Hvv) r_l2 -= ndot('im,mjab->ijab', self.Hoo, self.l2) r_l2 += ndot('ijmn,mnab->ijab', self.Hoooo, self.l2, prefactor=0.5) r_l2 += ndot('ijef,efab->ijab', self.l2, self.Hvvvv, prefactor=0.5) r_l2 += ndot('ie,ejab->ijab', self.l1, self.Hvovv, prefactor=2.0) r_l2 += ndot('ie,ejba->ijab', self.l1, self.Hvovv, prefactor=-1.0) r_l2 -= ndot('mb,jima->ijab', self.l1, self.Hooov, prefactor=2.0) r_l2 -= ndot('mb,ijma->ijab', self.l1, self.Hooov, prefactor=-1.0) r_l2 += ndot('ieam,mjeb->ijab', self.Hovvo, self.l2, prefactor=2.0) r_l2 += ndot('iema,mjeb->ijab', self.Hovov, self.l2, prefactor=-1.0) r_l2 -= ndot('mibe,jema->ijab', self.l2, self.Hovov) r_l2 -= ndot('mieb,jeam->ijab', self.l2, self.Hovvo) r_l2 += ndot('ijeb,ae->ijab', self.Loovv, self.build_Gvv()) r_l2 -= ndot('mi,mjab->ijab', self.build_Goo(), self.Loovv) old_l2 = self.l2.copy() old_l1 = self.l1.copy() # update l1 and l2 amplitudes self.l1 += r_l1 / self.Dia # Final r_l2_ijab = r_l2_ijab + r_l2_jiba tmp = r_l2 / self.Dijab self.l2 += tmp + tmp.swapaxes(0, 1).swapaxes(2, 3) # calculate rms from the residual rms = 2.0 * np.einsum('ia,ia->', old_l1 - self.l1, old_l1 - self.l1) rms += np.einsum('ijab,ijab->', old_l2 - self.l2, old_l2 - self.l2) return np.sqrt(rms)
def build_Hovoo(self, F, t1, t2): """<mb|Hbar|ij> = <mb||ij> - Fme t_ijbe - t_nb Wmnij + 0.5 * tau_ijef <mb||ef> + P(ij) t_jnbe <mn||ie> + P(ij) t_ie {<mb||ej> - t_njbf <mn||ef>}""" # <mb||ij> Hovoo = self.get_MO_sp('ovoo').copy() # - Fme t_ijbe Hovoo += ndot('me,ijeb->mbij', self.get_F(F, 'ov'), t2) Loovv = self.build_Loovv() tmp = ndot('mnef,nf->me', Loovv, t1) Hovoo += ndot('me,ijeb->mbij', tmp, t2) # - t_nb Wmnij Hovoo -= ndot('nb,mnij->mbij', t1, self.get_MO_sp('oooo')) tmp = ndot('ie,nb->ineb', t1, t1) Hovoo -= ndot('ineb,mnej->mbij', tmp, self.get_MO_sp('oovo')) Hovoo -= ndot('jneb,mnie->mbij', tmp, self.get_MO_sp('ooov')) tmp = ndot('nb,mnef->mefb', t1, self.get_MO_sp('oovv')) Hovoo -= ndot('ijef,mefb->mbij', t2, tmp) tmp = ndot('ie,jf->ijef', t1, t1) tmp1 = ndot('nb,mnef->mbef', t1, self.get_MO_sp('oovv')) Hovoo -= ndot('mbef,ijef->mbij', tmp1, tmp) # 0.5 * tau_ijef <mb||ef> Hovoo += ndot('ijef,mbef->mbij', self.build_tau(t1, t2), self.get_MO_sp('ovvv')) # P(ij) t_jnbe <mn||ie> Hovoo -= ndot('ineb,mnej->mbij', t2, self.get_MO_sp('oovo')) Hovoo -= ndot('jneb,mnie->mbij', t2, self.get_MO_sp('ooov')) Looov = self.build_Looov() Hovoo += ndot('jnbe,mnie->mbij', t2, Looov) # P(ij) t_ie <mb||ej> Hovoo += ndot('je,mbie->mbij', t1, self.get_MO_sp('ovov')) Hovoo += ndot('ie,mbej->mbij', t1, self.get_MO_sp('ovvo')) # - P(ij) t_ie * t_njbf <mn||ef> tmp = ndot('ie,mnef->mnif', t1, self.get_MO_sp('oovv')) Hovoo -= ndot('jnfb,mnif->mbij', t2, tmp) tmp = ndot('mnef,njfb->mejb', Loovv, t2) Hovoo += ndot('mejb,ie->mbij', tmp, t1) tmp = ndot('je,mnfe->mnfj', t1, self.get_MO_sp('oovv')) Hovoo -= ndot('infb,mnfj->mbij', t2, tmp) return Hovoo
def build_Hvvvo(self, F, t1, t2): """<ab|Hbar|ei> = <ab||ei> - F_me t_miab + t_if Wabef + 0.5 * tau_mnab <mn||ei>- P(ab) t_miaf <mb||ef> - P(ab) t_ma {<mb||ei> - t_nibf <mn||ef>}""" # <ab||ei> Hvvvo = self.get_MO_sp('vvvo').copy() # - Fme t_miab Hvvvo -= ndot('me,miab->abei', self.get_F(F, 'ov'), t2) Loovv = self.build_Loovv() tmp = ndot('mnfe,mf->ne', Loovv, t1) Hvvvo -= ndot('niab,ne->abei', t2, tmp) # t_if Wabef Hvvvo += ndot('if,abef->abei', t1, self.get_MO_sp('vvvv')) tmp = ndot('if,ma->imfa', t1, t1) Hvvvo -= ndot('imfa,mbef->abei', tmp, self.get_MO_sp('ovvv')) Hvvvo -= ndot('imfb,amef->abei', tmp, self.get_MO_sp('vovv')) tmp = ndot('mnef,if->mnei', self.get_MO_sp('oovv'), t1) Hvvvo += ndot('mnab,mnei->abei', t2, tmp) tmp = ndot('if,ma->imfa', t1, t1) tmp1 = ndot('mnef,nb->mbef', self.get_MO_sp('oovv'), t1) Hvvvo += ndot('imfa,mbef->abei', tmp, tmp1) # 0.5 * tau_mnab <mn||ei> Hvvvo += ndot('mnab,mnei->abei', self.build_tau(t1, t2), self.get_MO_sp('oovo')) # - P(ab) t_miaf <mb||ef> Hvvvo -= ndot('imfa,mbef->abei', t2, self.get_MO_sp('ovvv')) Hvvvo -= ndot('imfb,amef->abei', t2, self.get_MO_sp('vovv')) Lvovv = self.build_Lvovv() Hvvvo += ndot('mifb,amef->abei', t2, Lvovv) # - P(ab) t_ma <mb||ei> Hvvvo -= ndot('mb,amei->abei', t1, self.get_MO_sp('vovo')) Hvvvo -= ndot('ma,bmie->abei', t1, self.get_MO_sp('voov')) # P(ab) t_ma * t_nibf <mn||ef> tmp = ndot('mnef,ma->anef', self.get_MO_sp('oovv'), t1) Hvvvo += ndot('infb,anef->abei', t2, tmp) Loovv = self.build_Loovv() tmp = ndot('mnef,ma->nafe', Loovv, t1) Hvvvo -= ndot('nifb,nafe->abei', t2, tmp) tmp = ndot('nmef,mb->nefb', self.get_MO_sp('oovv'), t1) Hvvvo += ndot('niaf,nefb->abei', t2, tmp) return Hvvvo
def build_Hooov(self, t1): """ <mn|Hbar|ie> = <mn||ie> + t_if <mn||fe> """ Hooov = self.get_MO_sp('ooov').copy() Hooov += ndot('if,mnfe->mnie', t1, self.get_MO_sp('oovv')) return Hooov
def build_Avv(self): Avv = self.get_pert('vv').copy() Avv -= ndot('ma,me->ae', self.t1, self.get_pert('ov')) return Avv
def build_Goo(self, t2, y2): Goo = 0 Goo += ndot('mjab,ijab->mi', t2, y2) return Goo
def build_Aovoo(self): Aovoo = 0 Aovoo += ndot('ijeb,me->mbij', self.t2, self.get_pert('ov')) return Aovoo
def build_Hov(self, F, t1): """ <m|Hbar|e> = F_me = f_me + t_nf <mn||ef> """ Hov = self.get_F(F, 'ov').copy() Loovv = self.build_Loovv() Hov += ndot('nf,mnef->me', t1, Loovv) return Hov
def build_Avvoo(self): Avvoo = 0 Avvoo += ndot('ijeb,ae->abij', self.t2, self.build_Avv()) Avvoo -= ndot('mjab,mi->abij', self.t2, self.build_Aoo()) return Avvoo
def build_Gvv(self): self.Gvv = 0 self.Gvv -= ndot('ijab,ijeb->ae', self.l2, self.t2) return self.Gvv
def build_Zoo(self): Zoo = 0 Zoo -= ndot('mnie,ne->mi', self.Hooov, self.x1, prefactor=2.0) Zoo -= ndot('nmie,ne->mi', self.Hooov, self.x1, prefactor=-1.0) Zoo -= ndot('mnef,inef->mi', self.Loovv, self.x2) return Zoo
def build_Hovoo(self): """ <mb|Hbar|ij> = <mb||ij> - Fme t_ijbe - t_nb Wmnij + 0.5 * tau_ijef <mb||ef> + P(ij) t_jnbe <mn||ie> + P(ij) t_ie {<mb||ej> - t_njbf <mn||ef>} """ # <mb||ij> self.Hovoo = self.get_MO('ovoo').copy() # - Fme t_ijbe self.Hovoo += ndot('me,ijeb->mbij', self.get_F('ov'), self.t2) tmp = ndot('mnef,nf->me', self.Loovv, self.t1) self.Hovoo += ndot('me,ijeb->mbij', tmp, self.t2) # - t_nb Wmnij self.Hovoo -= ndot('nb,mnij->mbij', self.t1, self.get_MO('oooo')) tmp = ndot('ie,nb->ineb', self.t1, self.t1) self.Hovoo -= ndot('ineb,mnej->mbij', tmp, self.get_MO('oovo')) self.Hovoo -= ndot('jneb,mnie->mbij', tmp, self.get_MO('ooov')) tmp = ndot('nb,mnef->mefb', self.t1, self.get_MO('oovv')) self.Hovoo -= ndot('ijef,mefb->mbij', self.t2, tmp) tmp = ndot('ie,jf->ijef', self.t1, self.t1) tmp1 = ndot('nb,mnef->mbef', self.t1, self.get_MO('oovv')) self.Hovoo -= ndot('mbef,ijef->mbij', tmp1, tmp) # 0.5 * tau_ijef <mb||ef> self.Hovoo += ndot('ijef,mbef->mbij', self.build_tau(), self.get_MO('ovvv')) # P(ij) t_jnbe <mn||ie> self.Hovoo -= ndot('ineb,mnej->mbij', self.t2, self.get_MO('oovo')) self.Hovoo -= ndot('jneb,mnie->mbij', self.t2, self.get_MO('ooov')) self.Hovoo += ndot('jnbe,mnie->mbij', self.t2, self.Looov) # P(ij) t_ie <mb||ej> self.Hovoo += ndot('je,mbie->mbij', self.t1, self.get_MO('ovov')) self.Hovoo += ndot('ie,mbej->mbij', self.t1, self.get_MO('ovvo')) # - P(ij) t_ie * t_njbf <mn||ef> tmp = ndot('ie,mnef->mnif', self.t1, self.get_MO('oovv')) self.Hovoo -= ndot('jnfb,mnif->mbij', self.t2, tmp) tmp = ndot('mnef,njfb->mejb', self.Loovv, self.t2) self.Hovoo += ndot('mejb,ie->mbij', tmp, self.t1) tmp = ndot('je,mnfe->mnfj', self.t1, self.get_MO('oovv')) self.Hovoo -= ndot('infb,mnfj->mbij', self.t2, tmp) return self.Hovoo
def build_Gvv(self, y2, t2): Gvv = 0 Gvv -= ndot('ijab,ijeb->ae', y2, t2) return Gvv
def build_Hooov(self): """ <mn|Hbar|ie> = <mn||ie> + t_if <mn||fe> """ self.Hooov = self.get_MO('ooov').copy() self.Hooov += ndot('if,mnfe->mnie', self.t1, self.get_MO('oovv')) return self.Hooov
def inhomogenous_y2(self): # Inhomogenous terms appearing in Y2 equations # <O|L1(0)|A_bar|phi^ab_ij> r_y2 = ndot('ia,jb->ijab', self.l1, self.build_Aov(), prefactor=2.0) r_y2 -= ndot('ja,ib->ijab', self.l1, self.build_Aov()) # <O|L2(0)|A_bar|phi^ab_ij> r_y2 += ndot('ijeb,ea->ijab', self.l2, self.build_Avv()) r_y2 -= ndot('im,mjab->ijab', self.build_Aoo(), self.l2) # <O|L1(0)|[Hbar(0), X1]|phi^ab_ij> tmp = ndot('me,ja->meja', self.x1, self.l1) r_y2 -= ndot('mieb,meja->ijab', self.Loovv, tmp) tmp = ndot('me,mb->eb', self.x1, self.l1) r_y2 -= ndot('ijae,eb->ijab', self.Loovv, tmp) tmp = ndot('me,ie->mi', self.x1, self.l1) r_y2 -= ndot('mi,jmba->ijab', tmp, self.Loovv) tmp = ndot('me,jb->mejb', self.x1, self.l1, prefactor=2.0) r_y2 += ndot('imae,mejb->ijab', self.Loovv, tmp) # <O|L2(0)|[Hbar(0), X1]|phi^ab_ij> tmp = ndot('me,ma->ea', self.x1, self.Hov) r_y2 -= ndot('ijeb,ea->ijab', self.l2, tmp) tmp = ndot('me,ie->mi', self.x1, self.Hov) r_y2 -= ndot('mi,jmba->ijab', tmp, self.l2) tmp = ndot('me,ijef->mijf', self.x1, self.l2) r_y2 -= ndot('mijf,fmba->ijab', tmp, self.Hvovv) tmp = ndot('me,imbf->eibf', self.x1, self.l2) r_y2 -= ndot('eibf,fjea->ijab', tmp, self.Hvovv) tmp = ndot('me,jmfa->ejfa', self.x1, self.l2) r_y2 -= ndot('fibe,ejfa->ijab', self.Hvovv, tmp) tmp = ndot('me,fmae->fa', self.x1, self.Hvovv, prefactor=2.0) tmp -= ndot('me,fmea->fa', self.x1, self.Hvovv) r_y2 += ndot('ijfb,fa->ijab', self.l2, tmp) tmp = ndot('me,fiea->mfia', self.x1, self.Hvovv, prefactor=2.0) tmp -= ndot('me,fiae->mfia', self.x1, self.Hvovv) r_y2 += ndot('mfia,jmbf->ijab', tmp, self.l2) tmp = ndot('me,jmna->ejna', self.x1, self.Hooov) r_y2 += ndot('ineb,ejna->ijab', self.l2, tmp) tmp = ndot('me,mjna->ejna', self.x1, self.Hooov) r_y2 += ndot('nieb,ejna->ijab', self.l2, tmp) tmp = ndot('me,nmba->enba', self.x1, self.l2) r_y2 += ndot('jine,enba->ijab', self.Hooov, tmp) tmp = ndot('me,mina->eina', self.x1, self.Hooov, prefactor=2.0) tmp -= ndot('me,imna->eina', self.x1, self.Hooov) r_y2 -= ndot('eina,njeb->ijab', tmp, self.l2) tmp = ndot('me,imne->in', self.x1, self.Hooov, prefactor=2.0) tmp -= ndot('me,mine->in', self.x1, self.Hooov) r_y2 -= ndot('in,jnba->ijab', tmp, self.l2) # <O|L2(0)|[Hbar(0), X2]|phi^ab_ij> tmp = ndot('ijef,mnef->ijmn', self.l2, self.x2, prefactor=0.5) r_y2 += ndot('ijmn,mnab->ijab', tmp, self.get_MO('oovv')) tmp = ndot('ijfe,mnef->ijmn', self.get_MO('oovv'), self.x2, prefactor=0.5) r_y2 += ndot('ijmn,mnba->ijab', tmp, self.l2) tmp = ndot('mifb,mnef->ibne', self.l2, self.x2) r_y2 += ndot('ibne,jnae->ijab', tmp, self.get_MO('oovv')) tmp = ndot('imfb,mnef->ibne', self.l2, self.x2) r_y2 += ndot('ibne,njae->ijab', tmp, self.get_MO('oovv')) tmp = ndot('mjfb,mnef->jbne', self.l2, self.x2) r_y2 -= ndot('jbne,inae->ijab', tmp, self.Loovv) r_y2 -= ndot('in,jnba->ijab', self.build_Goo(self.Loovv, self.x2), self.l2) r_y2 += ndot('ijfb,af->ijab', self.l2, self.build_Gvv(self.Loovv, self.x2)) r_y2 += ndot('ijae,be->ijab', self.Loovv, self.build_Gvv(self.l2, self.x2)) r_y2 -= ndot('imab,jm->ijab', self.Loovv, self.build_Goo(self.l2, self.x2)) tmp = ndot('nifb,mnef->ibme', self.l2, self.x2) r_y2 -= ndot('ibme,mjea->ijab', tmp, self.Loovv) tmp = ndot('njfb,mnef->jbme', self.l2, self.x2, prefactor=2.0) r_y2 += ndot('imae,jbme->ijab', self.Loovv, tmp) return r_y2
def build_Hvvvo(self): """ <ab|Hbar|ei> = <ab||ei> - F_me t_miab + t_if Wabef + 0.5 * tau_mnab <mn||ei> - P(ab) t_miaf <mb||ef> - P(ab) t_ma {<mb||ei> - t_nibf <mn||ef>} """ # <ab||ei> self.Hvvvo = self.get_MO('vvvo').copy() # - Fme t_miab self.Hvvvo -= ndot('me,miab->abei', self.get_F('ov'), self.t2) tmp = ndot('mnfe,mf->ne', self.Loovv, self.t1) self.Hvvvo -= ndot('niab,ne->abei', self.t2, tmp) # t_if Wabef self.Hvvvo += ndot('if,abef->abei', self.t1, self.get_MO('vvvv')) tmp = ndot('if,ma->imfa', self.t1, self.t1) self.Hvvvo -= ndot('imfa,mbef->abei', tmp, self.get_MO('ovvv')) self.Hvvvo -= ndot('imfb,amef->abei', tmp, self.get_MO('vovv')) tmp = ndot('mnef,if->mnei', self.get_MO('oovv'), self.t1) self.Hvvvo += ndot('mnab,mnei->abei', self.t2, tmp) tmp = ndot('if,ma->imfa', self.t1, self.t1) tmp1 = ndot('mnef,nb->mbef', self.get_MO('oovv'), self.t1) self.Hvvvo += ndot('imfa,mbef->abei', tmp, tmp1) # 0.5 * tau_mnab <mn||ei> self.Hvvvo += ndot('mnab,mnei->abei', self.build_tau(), self.get_MO('oovo')) # - P(ab) t_miaf <mb||ef> self.Hvvvo -= ndot('imfa,mbef->abei', self.t2, self.get_MO('ovvv')) self.Hvvvo -= ndot('imfb,amef->abei', self.t2, self.get_MO('vovv')) self.Hvvvo += ndot('mifb,amef->abei', self.t2, self.Lvovv) # - P(ab) t_ma <mb||ei> self.Hvvvo -= ndot('mb,amei->abei', self.t1, self.get_MO('vovo')) self.Hvvvo -= ndot('ma,bmie->abei', self.t1, self.get_MO('voov')) # P(ab) t_ma * t_nibf <mn||ef> tmp = ndot('mnef,ma->anef', self.get_MO('oovv'), self.t1) self.Hvvvo += ndot('infb,anef->abei', self.t2, tmp) tmp = ndot('mnef,ma->nafe', self.Loovv, self.t1) self.Hvvvo -= ndot('nifb,nafe->abei', self.t2, tmp) tmp = ndot('nmef,mb->nefb', self.get_MO('oovv'), self.t1) self.Hvvvo += ndot('niaf,nefb->abei', self.t2, tmp) return self.Hvvvo
def update_Y(self): # Y1 and Y2 amplitudes are the Fourier analogues of first order perturbed L1 and L2 amplitudes, # While X amplitudes are referred to as right hand perturbed amplitudes, Y amplitudes are the # left hand perturbed amplitudes. Just like X1 and X2, they can be obtained by solving a linear # sytem of equations. Refer to eq 73 of reference 1. for Writing l_mu^(1)(omega) as Y_mu, # Y1 equations: # omega * Y_ia + Y_kc * <phi^c_k|Hbar(0)|phi^a_i> + Y_klcd * <phi^cd_kl|Hbar(0)|phi^a_i> # + <O|(1 + L(0))|Hbar_bar(1)(omega)|phi^a_i> = 0 # Y2 equations: # omega * Y_ijab + Y_kc * <phi^c_k|Hbar(0)|phi^ab_ij> + Y_klcd * <phi^cd_kl|Hbar(0)|phi^ab_ij> # + <O|(1 + L(0))|Hbar_bar(1)(omega)|phi^ab_ij> = 0 # where Hbar_bar(1)(omega) = Hbar(1) + [Hbar(0), T(1)] = A_bar + [Hbar(0), X] # Note that the homogenous terms of Y1 and Y2 equations except the omega term are exactly identical in # structure to the L1 and L2 equations and just like lambdas, the equations for these Y amplitudes have # been derived using the unitray group approach. Please refer to helper_cclambda file for a complete # decsription. # Y1 equations # Inhomogenous terms r_y1 = self.im_y1.copy() # Homogenous terms now! r_y1 += self.omega * self.y1 r_y1 += ndot('ie,ea->ia', self.y1, self.Hvv) r_y1 -= ndot('im,ma->ia', self.Hoo, self.y1) r_y1 += ndot('ieam,me->ia', self.Hovvo, self.y1, prefactor=2.0) r_y1 += ndot('iema,me->ia', self.Hovov, self.y1, prefactor=-1.0) r_y1 += ndot('imef,efam->ia', self.y2, self.Hvvvo) r_y1 -= ndot('iemn,mnae->ia', self.Hovoo, self.y2) r_y1 -= ndot('eifa,ef->ia', self.Hvovv, self.build_Gvv(self.y2, self.t2), prefactor=2.0) r_y1 -= ndot('eiaf,ef->ia', self.Hvovv, self.build_Gvv(self.y2, self.t2), prefactor=-1.0) r_y1 -= ndot('mina,mn->ia', self.Hooov, self.build_Goo(self.t2, self.y2), prefactor=2.0) r_y1 -= ndot('imna,mn->ia', self.Hooov, self.build_Goo(self.t2, self.y2), prefactor=-1.0) # Y1 equations over! # Y2 equations # Final r_y2_ijab = r_y2_ijab + r_y2_jiba # Inhomogenous terms r_y2 = self.im_y2.copy() # Homogenous terms now! # a factor of 0.5 because of the relation/comment just above # and due to the fact that Y2_ijab = Y2_jiba r_y2 += 0.5 * self.omega * self.y2.copy() r_y2 += ndot('ia,jb->ijab', self.y1, self.Hov, prefactor=2.0) r_y2 -= ndot('ja,ib->ijab', self.y1, self.Hov) r_y2 += ndot('ijeb,ea->ijab', self.y2, self.Hvv) r_y2 -= ndot('im,mjab->ijab', self.Hoo, self.y2) r_y2 += ndot('ijmn,mnab->ijab', self.Hoooo, self.y2, prefactor=0.5) r_y2 += ndot('ijef,efab->ijab', self.y2, self.Hvvvv, prefactor=0.5) r_y2 += ndot('ie,ejab->ijab', self.y1, self.Hvovv, prefactor=2.0) r_y2 += ndot('ie,ejba->ijab', self.y1, self.Hvovv, prefactor=-1.0) r_y2 -= ndot('mb,jima->ijab', self.y1, self.Hooov, prefactor=2.0) r_y2 -= ndot('mb,ijma->ijab', self.y1, self.Hooov, prefactor=-1.0) r_y2 += ndot('ieam,mjeb->ijab', self.Hovvo, self.y2, prefactor=2.0) r_y2 += ndot('iema,mjeb->ijab', self.Hovov, self.y2, prefactor=-1.0) r_y2 -= ndot('mibe,jema->ijab', self.y2, self.Hovov) r_y2 -= ndot('mieb,jeam->ijab', self.y2, self.Hovvo) r_y2 += ndot('ijeb,ae->ijab', self.Loovv, self.build_Gvv(self.y2, self.t2)) r_y2 -= ndot('mi,mjab->ijab', self.build_Goo(self.t2, self.y2), self.Loovv) # Y2 equations over! old_y1 = self.y1.copy() old_y2 = self.y2.copy() # update Y1 and Y2 self.y1 += r_y1/self.Dia # Final r_y2_ijab = r_y2_ijab + r_y2_jiba tmp = r_y2/self.Dijab self.y2 += tmp + tmp.swapaxes(0,1).swapaxes(2,3) # Calcuate rms from the residual rms = np.einsum('ia,ia->', r_y1/self.Dia, r_y1/self.Dia) rms += np.einsum('ijab,ijab->', old_y2 - self.y2, old_y2 - self.y2) return np.sqrt(rms)
def linresp(self): # Please refer to equation 78 of reference 1. # Writing H(1)(omega) = B, T(1)(omega) = X, L(1)(omega) = Y # <<A;B>> = <0|Y(B) * A_bar|0> + <0|(1+L(0))[A_bar, X(B)]|0> # polar1 polar2 self.polar1 = 0 self.polar2 = 0 # <0|Y1(B) * A_bar|0> self.polar1 += ndot("ai,ia->", self.ccpert_A.build_Avo(), self.y1_B) # <0|Y2(B) * A_bar|0> self.polar1 += ndot("abij,ijab->", self.ccpert_A.build_Avvoo(), self.y2_B, prefactor=0.5) self.polar1 += ndot("baji,ijab->", self.ccpert_A.build_Avvoo(), self.y2_B, prefactor=0.5) # <0|[A_bar, X(B)]|0> self.polar2 += ndot("ia,ia->", self.ccpert_A.build_Aov(), self.x1_B, prefactor=2.0) # <0|L1(0)[A_bar, X1(B)]|0> tmp = ndot('ia,ic->ac', self.l1, self.x1_B) self.polar2 += ndot('ac,ac->', tmp, self.ccpert_A.build_Avv()) tmp = ndot('ia,ka->ik', self.l1, self.x1_B) self.polar2 -= ndot('ik,ki->', tmp, self.ccpert_A.build_Aoo()) # <0|L1(0)[A_bar, X2(B)]|0> tmp = ndot('ia,jb->ijab', self.l1, self.ccpert_A.build_Aov()) self.polar2 += ndot('ijab,ijab->', tmp, self.x2_B, prefactor=2.0) self.polar2 += ndot('ijab,ijba->', tmp, self.x2_B, prefactor=-1.0) # <0|L2(0)[A_bar, X1(B)]|0> tmp = ndot('ijbc,bcaj->ia', self.l2, self.ccpert_A.build_Avvvo()) self.polar2 += ndot('ia,ia->', tmp, self.x1_B) tmp = ndot('ijab,kbij->ak', self.l2, self.ccpert_A.build_Aovoo()) self.polar2 -= ndot('ak,ka->', tmp, self.x1_B, prefactor=0.5) tmp = ndot('ijab,kaji->bk', self.l2, self.ccpert_A.build_Aovoo()) self.polar2 -= ndot('bk,kb->', tmp, self.x1_B, prefactor=0.5) # <0|L2(0)[A_bar, X1(B)]|0> tmp = ndot('ijab,kjab->ik', self.l2, self.x2_B) self.polar2 -= ndot('ik,ki->', tmp, self.ccpert_A.build_Aoo(), prefactor=0.5) tmp = ndot('ijab,kiba->jk', self.l2, self.x2_B,) self.polar2 -= ndot('jk,kj->', tmp, self.ccpert_A.build_Aoo(), prefactor=0.5) tmp = ndot('ijab,ijac->bc', self.l2, self.x2_B,) self.polar2 += ndot('bc,bc->', tmp, self.ccpert_A.build_Avv(), prefactor=0.5) tmp = ndot('ijab,ijcb->ac', self.l2, self.x2_B,) self.polar2 += ndot('ac,ac->', tmp, self.ccpert_A.build_Avv(), prefactor=0.5) return -1.0*(self.polar1 + self.polar2)
def pseudoenergy(self): pseudoenergy = 0 pseudoenergy += ndot( 'ijab,ijab->', self.get_MO('oovv'), self.l2, prefactor=0.5) return pseudoenergy