def make_ea(self, cc): # cc = self.cc t1, t2, eris = cc.t1, cc.t2, cc.eris self.Lvv = imdk.Lvv(cc, t1, t2, eris) self.Loo = imdk.Loo(cc, t1, t2, eris) self.Fov = imdk.cc_Fov(cc, t1, t2, eris) self.Wvovv = imdk.Wvovv(cc, t1, t2, eris) self.Wvvvo = imdk.Wvvvo(cc, t1, t2, eris) self.Wovvo = imdk.Wovvo(cc, t1, t2, eris) self.Wvvvv = imdk.Wvvvv(cc, t1, t2, eris) self.Woovv = eris.oovv self.Wovov = imdk.Wovov(cc, t1, t2, eris)
def update_amps(cc, t1, t2, eris): time0 = time1 = time.clock(), time.time() log = logger.Logger(cc.stdout, cc.verbose) nkpts, nocc, nvir = t1.shape fock = eris.fock mo_e_o = [e[:nocc] for e in eris.mo_energy] mo_e_v = [e[nocc:] + cc.level_shift for e in eris.mo_energy] # Get location of padded elements in occupied and virtual space nonzero_opadding, nonzero_vpadding = padding_k_idx(cc, kind="split") fov = fock[:, :nocc, nocc:] foo = fock[:, :nocc, :nocc] fvv = fock[:, nocc:, nocc:] kconserv = cc.khelper.kconserv Foo = imdk.cc_Foo(t1, t2, eris, kconserv) Fvv = imdk.cc_Fvv(t1, t2, eris, kconserv) Fov = imdk.cc_Fov(t1, t2, eris, kconserv) Loo = imdk.Loo(t1, t2, eris, kconserv) Lvv = imdk.Lvv(t1, t2, eris, kconserv) # Move energy terms to the other side for k in range(nkpts): Foo[k][np.diag_indices(nocc)] -= mo_e_o[k] Fvv[k][np.diag_indices(nvir)] -= mo_e_v[k] Loo[k][np.diag_indices(nocc)] -= mo_e_o[k] Lvv[k][np.diag_indices(nvir)] -= mo_e_v[k] time1 = log.timer_debug1('intermediates', *time1) # T1 equation t1new = np.array(fov).astype(t1.dtype).conj() for ka in range(nkpts): ki = ka # kc == ki; kk == ka t1new[ka] += -2. * einsum('kc,ka,ic->ia', fov[ki], t1[ka], t1[ki]) t1new[ka] += einsum('ac,ic->ia', Fvv[ka], t1[ki]) t1new[ka] += -einsum('ki,ka->ia', Foo[ki], t1[ka]) tau_term = np.empty((nkpts, nocc, nocc, nvir, nvir), dtype=t1.dtype) for kk in range(nkpts): tau_term[kk] = 2 * t2[kk, ki, kk] - t2[ki, kk, kk].transpose(1, 0, 2, 3) tau_term[ka] += einsum('ic,ka->kica', t1[ki], t1[ka]) for kk in range(nkpts): kc = kk t1new[ka] += einsum('kc,kica->ia', Fov[kc], tau_term[kk]) t1new[ka] += einsum('akic,kc->ia', 2 * eris.voov[ka, kk, ki], t1[kc]) t1new[ka] += einsum('kaic,kc->ia', -eris.ovov[kk, ka, ki], t1[kc]) for kc in range(nkpts): kd = kconserv[ka, kc, kk] Svovv = 2 * eris.vovv[ka, kk, kc] - eris.vovv[ka, kk, kd].transpose(0, 1, 3, 2) tau_term_1 = t2[ki, kk, kc].copy() if ki == kc and kk == kd: tau_term_1 += einsum('ic,kd->ikcd', t1[ki], t1[kk]) t1new[ka] += einsum('akcd,ikcd->ia', Svovv, tau_term_1) # kk - ki + kl = kc # => kl = ki - kk + kc kl = kconserv[ki, kk, kc] Sooov = 2 * eris.ooov[kk, kl, ki] - eris.ooov[kl, kk, ki].transpose(1, 0, 2, 3) tau_term_1 = t2[kk, kl, ka].copy() if kk == ka and kl == kc: tau_term_1 += einsum('ka,lc->klac', t1[ka], t1[kc]) t1new[ka] += -einsum('klic,klac->ia', Sooov, tau_term_1) time1 = log.timer_debug1('t1', *time1) # T2 equation t2new = np.empty_like(t2) for ki, kj, ka in kpts_helper.loop_kkk(nkpts): t2new[ki, kj, ka] = eris.oovv[ki, kj, ka].conj() mem_now = lib.current_memory()[0] if (nocc ** 4 * nkpts ** 3) * 16 / 1e6 + mem_now < cc.max_memory * .9: Woooo = imdk.cc_Woooo(t1, t2, eris, kconserv) else: fimd = lib.H5TmpFile() Woooo = fimd.create_dataset('oooo', (nkpts, nkpts, nkpts, nocc, nocc, nocc, nocc), t1.dtype.char) Woooo = imdk.cc_Woooo(t1, t2, eris, kconserv, Woooo) for ki, kj, ka in kpts_helper.loop_kkk(nkpts): # Chemist's notation for momentum conserving t2(ki,kj,ka,kb) kb = kconserv[ki, ka, kj] t2new_tmp = np.zeros((nocc, nocc, nvir, nvir), dtype=t2.dtype) for kl in range(nkpts): kk = kconserv[kj, kl, ki] tau_term = t2[kk, kl, ka].copy() if kl == kb and kk == ka: tau_term += einsum('ic,jd->ijcd', t1[ka], t1[kb]) t2new_tmp += 0.5 * einsum('klij,klab->ijab', Woooo[kk, kl, ki], tau_term) t2new[ki, kj, ka] += t2new_tmp t2new[kj, ki, kb] += t2new_tmp.transpose(1, 0, 3, 2) Woooo = None fimd = None time1 = log.timer_debug1('t2 oooo', *time1) # einsum('abcd,ijcd->ijab', Wvvvv, tau) add_vvvv_(cc, t2new, t1, t2, eris) time1 = log.timer_debug1('t2 vvvv', *time1) for ki, kj, ka in kpts_helper.loop_kkk(nkpts): kb = kconserv[ki, ka, kj] t2new_tmp = einsum('ac,ijcb->ijab', Lvv[ka], t2[ki, kj, ka]) t2new_tmp += einsum('ki,kjab->ijab', -Loo[ki], t2[ki, kj, ka]) kc = kconserv[ka, ki, kb] tmp2 = np.asarray(eris.vovv[kc, ki, kb]).transpose(3, 2, 1, 0).conj() \ - einsum('kbic,ka->abic', eris.ovov[ka, kb, ki], t1[ka]) t2new_tmp += einsum('abic,jc->ijab', tmp2, t1[kj]) kk = kconserv[ki, ka, kj] tmp2 = np.asarray(eris.ooov[kj, ki, kk]).transpose(3, 2, 1, 0).conj() \ + einsum('akic,jc->akij', eris.voov[ka, kk, ki], t1[kj]) t2new_tmp -= einsum('akij,kb->ijab', tmp2, t1[kb]) t2new[ki, kj, ka] += t2new_tmp t2new[kj, ki, kb] += t2new_tmp.transpose(1, 0, 3, 2) mem_now = lib.current_memory()[0] if (nocc ** 2 * nvir ** 2 * nkpts ** 3) * 16 / 1e6 * 2 + mem_now < cc.max_memory * .9: Wvoov = imdk.cc_Wvoov(t1, t2, eris, kconserv) Wvovo = imdk.cc_Wvovo(t1, t2, eris, kconserv) else: fimd = lib.H5TmpFile() Wvoov = fimd.create_dataset('voov', (nkpts, nkpts, nkpts, nvir, nocc, nocc, nvir), t1.dtype.char) Wvovo = fimd.create_dataset('vovo', (nkpts, nkpts, nkpts, nvir, nocc, nvir, nocc), t1.dtype.char) Wvoov = imdk.cc_Wvoov(t1, t2, eris, kconserv, Wvoov) Wvovo = imdk.cc_Wvovo(t1, t2, eris, kconserv, Wvovo) for ki, kj, ka in kpts_helper.loop_kkk(nkpts): kb = kconserv[ki, ka, kj] t2new_tmp = np.zeros((nocc, nocc, nvir, nvir), dtype=t2.dtype) for kk in range(nkpts): kc = kconserv[ka, ki, kk] tmp_voov = 2. * Wvoov[ka, kk, ki] - Wvovo[ka, kk, kc].transpose(0, 1, 3, 2) t2new_tmp += einsum('akic,kjcb->ijab', tmp_voov, t2[kk, kj, kc]) kc = kconserv[ka, ki, kk] t2new_tmp -= einsum('akic,kjbc->ijab', Wvoov[ka, kk, ki], t2[kk, kj, kb]) kc = kconserv[kk, ka, kj] t2new_tmp -= einsum('bkci,kjac->ijab', Wvovo[kb, kk, kc], t2[kk, kj, ka]) t2new[ki, kj, ka] += t2new_tmp t2new[kj, ki, kb] += t2new_tmp.transpose(1, 0, 3, 2) Wvoov = Wvovo = None fimd = None time1 = log.timer_debug1('t2 voov', *time1) for ki in range(nkpts): ka = ki # Remove zero/padded elements from denominator eia = LARGE_DENOM * np.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype) n0_ovp_ia = np.ix_(nonzero_opadding[ki], nonzero_vpadding[ka]) eia[n0_ovp_ia] = (mo_e_o[ki][:,None] - mo_e_v[ka])[n0_ovp_ia] t1new[ki] /= eia for ki, kj, ka in kpts_helper.loop_kkk(nkpts): kb = kconserv[ki, ka, kj] # For LARGE_DENOM, see t1new update above eia = LARGE_DENOM * np.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype) n0_ovp_ia = np.ix_(nonzero_opadding[ki], nonzero_vpadding[ka]) eia[n0_ovp_ia] = (mo_e_o[ki][:,None] - mo_e_v[ka])[n0_ovp_ia] ejb = LARGE_DENOM * np.ones((nocc, nvir), dtype=eris.mo_energy[0].dtype) n0_ovp_jb = np.ix_(nonzero_opadding[kj], nonzero_vpadding[kb]) ejb[n0_ovp_jb] = (mo_e_o[kj][:,None] - mo_e_v[kb])[n0_ovp_jb] eijab = eia[:, None, :, None] + ejb[:, None, :] t2new[ki, kj, ka] /= eijab time0 = log.timer_debug1('update t1 t2', *time0) return t1new, t2new
def update_amps(cc, t1, t2, eris, max_memory=2000): time0 = time.clock(), time.time() log = logger.Logger(cc.stdout, cc.verbose) nkpts, nocc, nvir = t1.shape fock = eris.fock fov = fock[:, :nocc, nocc:] foo = fock[:, :nocc, :nocc] fvv = fock[:, nocc:, nocc:] # mo_e = eris.fock.diagonal() # eia = mo_e[:nocc,None] - mo_e[None,nocc:] # eijab = lib.direct_sum('ia,jb->ijab',eia,eia) Foo = imdk.cc_Foo(cc, t1, t2, eris) Fvv = imdk.cc_Fvv(cc, t1, t2, eris) Fov = imdk.cc_Fov(cc, t1, t2, eris) Loo = imdk.Loo(cc, t1, t2, eris) Lvv = imdk.Lvv(cc, t1, t2, eris) Woooo = imdk.cc_Woooo(cc, t1, t2, eris) Wvvvv = imdk.cc_Wvvvv(cc, t1, t2, eris) Wvoov = imdk.cc_Wvoov(cc, t1, t2, eris) Wvovo = imdk.cc_Wvovo(cc, t1, t2, eris) # Move energy terms to the other side Foo -= foo Fvv -= fvv Loo -= foo Lvv -= fvv kconserv = cc.kconserv # T1 equation # TODO: Check this conj(). Hirata and Bartlett has # f_{vo}(a,i), which should be equal to f_{ov}^*(i,a) t1new = np.empty((nkpts, nocc, nvir), dtype=t1.dtype) t1new[:] = fov[:].conj().copy() for ka in range(nkpts): ki = ka # kc == ki; kk == ka t1new[ka] += -2.0 * einsum("kc,ka,ic->ia", fov[ki], t1[ka], t1[ki]) t1new[ka] += einsum("ac,ic->ia", Fvv[ka], t1[ki]) t1new[ka] += -einsum("ki,ka->ia", Foo[ki], t1[ka]) tau_term = np.empty((nkpts, nocc, nocc, nvir, nvir), dtype=t1.dtype) for kk in range(nkpts): tau_term[kk] = 2 * t2[kk, ki, kk] - t2[ki, kk, kk].transpose(1, 0, 2, 3) tau_term[ka] += einsum("ic,ka->kica", t1[ki], t1[ka]) for kk in range(nkpts): kc = kk t1new[ka] += einsum("kc,kica->ia", Fov[kc], tau_term[kk]) t1new[ka] += einsum("akic,kc->ia", 2 * eris.voov[ka, kk, ki], t1[kc]) t1new[ka] += einsum("akci,kc->ia", -eris.vovo[ka, kk, kc], t1[kc]) for kc in range(nkpts): kd = kconserv[ka, kc, kk] Svovv = 2 * eris.vovv[ka, kk, kc] - eris.vovv[ka, kk, kd].transpose(0, 1, 3, 2) tau_term_1 = t2[ki, kk, kc].copy() if ki == kc and kk == kd: tau_term_1 += einsum("ic,kd->ikcd", t1[ki], t1[kk]) t1new[ka] += einsum("akcd,ikcd->ia", Svovv, tau_term_1) # kk - ki + kl = kc # => kl = ki - kk + kc kl = kconserv[ki, kk, kc] Sooov = 2 * eris.ooov[kk, kl, ki] - eris.ooov[kl, kk, ki].transpose(1, 0, 2, 3) tau_term_1 = t2[kk, kl, ka].copy() if kk == ka and kl == kc: tau_term_1 += einsum("ka,lc->klac", t1[ka], t1[kc]) t1new[ka] += -einsum("klic,klac->ia", Sooov, tau_term_1) # T2 equation # For conj(), see Hirata and Bartlett, Eq. (36) t2new = np.array(eris.oovv, copy=True).conj() for ki in range(nkpts): for kj in range(nkpts): for ka in range(nkpts): # Chemist's notation for momentum conserving t2(ki,kj,ka,kb) kb = kconserv[ki, ka, kj] for kl in range(nkpts): # kk - ki + kl = kj # => kk = kj - kl + ki kk = kconserv[kj, kl, ki] t2new[ki, kj, ka] += einsum("klij,klab->ijab", Woooo[kk, kl, ki], t2[kk, kl, ka]) if kl == kb and kk == ka: t2new[ki, kj, ka] += einsum("klij,ka,lb->ijab", Woooo[ka, kb, ki], t1[ka], t1[kb]) for kc in range(nkpts): kd = kconserv[ka, kc, kb] tau_term = t2[ki, kj, kc].copy() if ki == kc and kj == kd: tau_term += einsum("ic,jd->ijcd", t1[ki], t1[kj]) t2new[ki, kj, ka] += einsum("abcd,ijcd->ijab", Wvvvv[ka, kb, kc], tau_term) t2new[ki, kj, ka] += einsum("ac,ijcb->ijab", Lvv[ka], t2[ki, kj, ka]) # P(ij)P(ab) t2new[ki, kj, ka] += einsum("bc,jica->ijab", Lvv[kb], t2[kj, ki, kb]) t2new[ki, kj, ka] += einsum("ki,kjab->ijab", -Loo[ki], t2[ki, kj, ka]) # P(ij)P(ab) t2new[ki, kj, ka] += einsum("kj,kiba->ijab", -Loo[kj], t2[kj, ki, kb]) tmp2 = eris.vvov[ka, kb, ki] - einsum("kbic,ka->abic", eris.ovov[ka, kb, ki], t1[ka]) tmp = einsum("abic,jc->ijab", tmp2, t1[kj]) t2new[ki, kj, ka] += tmp # P(ij)P(ab) tmp2 = eris.vvov[kb, ka, kj] - einsum("kajc,kb->bajc", eris.ovov[kb, ka, kj], t1[kb]) tmp = einsum("bajc,ic->ijab", tmp2, t1[ki]) t2new[ki, kj, ka] += tmp # ka - ki + kk = kj # => kk = ki - ka + kj kk = kconserv[ki, ka, kj] tmp2 = eris.vooo[ka, kk, ki] + einsum("akic,jc->akij", eris.voov[ka, kk, ki], t1[kj]) tmp = einsum("akij,kb->ijab", tmp2, t1[kb]) t2new[ki, kj, ka] -= tmp # P(ij)P(ab) kk = kconserv[kj, kb, ki] tmp2 = eris.vooo[kb, kk, kj] + einsum("bkjc,ic->bkji", eris.voov[kb, kk, kj], t1[ki]) tmp = einsum("bkji,ka->ijab", tmp2, t1[ka]) t2new[ki, kj, ka] -= tmp for kk in range(nkpts): kc = kconserv[ka, ki, kk] tmp_voov = 2.0 * Wvoov[ka, kk, ki] - Wvovo[ka, kk, kc].transpose(0, 1, 3, 2) tmp = einsum("akic,kjcb->ijab", tmp_voov, t2[kk, kj, kc]) # tmp = 2*einsum('akic,kjcb->ijab',Wvoov[ka,kk,ki],t2[kk,kj,kc]) - \ # einsum('akci,kjcb->ijab',Wvovo[ka,kk,kc],t2[kk,kj,kc]) t2new[ki, kj, ka] += tmp # P(ij)P(ab) kc = kconserv[kb, kj, kk] tmp_voov = 2.0 * Wvoov[kb, kk, kj] - Wvovo[kb, kk, kc].transpose(0, 1, 3, 2) tmp = einsum("bkjc,kica->ijab", tmp_voov, t2[kk, ki, kc]) # tmp = 2*einsum('bkjc,kica->ijab',Wvoov[kb,kk,kj],t2[kk,ki,kc]) - \ # einsum('bkcj,kica->ijab',Wvovo[kb,kk,kc],t2[kk,ki,kc]) t2new[ki, kj, ka] += tmp kc = kconserv[ka, ki, kk] tmp = einsum("akic,kjbc->ijab", Wvoov[ka, kk, ki], t2[kk, kj, kb]) t2new[ki, kj, ka] -= tmp # P(ij)P(ab) kc = kconserv[kb, kj, kk] tmp = einsum("bkjc,kiac->ijab", Wvoov[kb, kk, kj], t2[kk, ki, ka]) t2new[ki, kj, ka] -= tmp kc = kconserv[kk, ka, kj] tmp = einsum("bkci,kjac->ijab", Wvovo[kb, kk, kc], t2[kk, kj, ka]) t2new[ki, kj, ka] -= tmp # P(ij)P(ab) kc = kconserv[kk, kb, ki] tmp = einsum("akcj,kibc->ijab", Wvovo[ka, kk, kc], t2[kk, ki, kb]) t2new[ki, kj, ka] -= tmp eia = numpy.zeros(shape=t1new.shape, dtype=t1new.dtype) for ki in range(nkpts): for i in range(nocc): for a in range(nvir): eia[ki, i, a] = foo[ki, i, i] - fvv[ki, a, a] t1new[ki] /= eia[ki] for ki in range(nkpts): for kj in range(nkpts): for ka in range(nkpts): kb = kconserv[ki, ka, kj] eia = np.diagonal(foo[ki]).reshape(-1, 1) - np.diagonal(fvv[ka]) ejb = np.diagonal(foo[kj]).reshape(-1, 1) - np.diagonal(fvv[kb]) eijab = lib.direct_sum("ia,jb->ijab", eia, ejb) t2new[ki, kj, ka] /= eijab time0 = log.timer_debug1("update t1 t2", *time0) # sys.exit("exiting for testing...") return t1new, t2new