def eaccsd_diag(eom, imds=None): if imds is None: imds = eom.make_imds() t1, t2 = imds.t1, imds.t2 nocc, nvir = t1.shape foo = imds.eris.foo fvv = imds.eris.fvv Hr1 = imds.Lvv.diagonal() Hr1 = tensor(Hr1) if eom.partition == 'mp': jab = fvv.diagonal()[None, :, None] jab = jab + fvv.diagonal()[None, None, :] jab = jab - foo.diagonal()[:, None, None] Hr2 = tensor(jab) else: jab = imds.Lvv.diagonal().reshape(1, nvir, 1) jab = jab + imds.Lvv.diagonal().reshape(1, 1, nvir) jab = jab - imds.Loo.diagonal().reshape(nocc, 1, 1) wab = np.einsum("abab->ab", imds.Wvvvv.array) wjb = np.einsum('jbjb->jb', imds.Wovov.array) wjb2 = np.einsum('jbbj->jb', imds.Wovvo.array) wja = np.einsum('jaja->ja', imds.Wovov.array) jab = jab + wab.reshape(1, nvir, nvir) jab = jab - wjb.reshape(nocc, 1, nvir) jab = jab + 2 * wjb2.reshape(nocc, 1, nvir) jab -= np.einsum('jb,ab->jab', wjb2, np.eye(nvir)) jab = jab - wja.reshape(nocc, nvir, 1) Hr2 = tensor(jab) Hr2 -= 2 * lib.einsum('ijab,ijab->jab', t2, imds.Woovv) Hr2 += lib.einsum('ijab,ijba->jab', t2, imds.Woovv) vector = eom.amplitudes_to_vector(Hr1, Hr2) return vector
def ipccsd_diag(eom, imds=None): if imds is None: imds = eom.make_imds() t1, t2 = imds.t1, imds.t2 nocc, nvir = t1.shape foo = imds.eris.foo fvv = imds.eris.fvv Hr1 = -imds.Loo.diagonal() Hr1 = tensor(Hr1) if eom.partition == 'mp': ijb = -foo.diagonal().reshape(nocc, 1, 1) ijb = ijb - foo.diagonal().reshape(1, nocc, 1) ijb = ijb + fvv.diagonal().reshape(1, 1, nvir) Hr2 = tensor(ijb) else: wij = np.einsum('ijij->ij', imds.Woooo.array) wjb = np.einsum('jbjb->jb', imds.Wovov.array) wjb2 = np.einsum('jbbj->jb', imds.Wovvo.array) wib = np.einsum('ibib->ib', imds.Wovov.array) ijb = imds.Lvv.diagonal().reshape(1, 1, nvir) ijb = ijb - imds.Loo.diagonal().reshape(nocc, 1, 1) ijb = ijb - imds.Loo.diagonal().reshape(1, nocc, 1) #print(ijb.shape, wjb.shape) ijb = ijb + wij.reshape(nocc, nocc, 1) ijb = ijb - wjb.reshape(1, nocc, nvir) ijb = ijb + 2 * wjb2.reshape(1, nocc, nvir) ijb = ijb - np.einsum('ij,jb->ijb', np.eye(nocc), wjb2) ijb = ijb - wib.reshape(nocc, 1, nvir) Hr2 = tensor(ijb) Hr2 -= 2. * lib.einsum('ijcb,jibc->ijb', t2, imds.Woovv) Hr2 += lib.einsum('ijcb,ijbc->ijb', t2, imds.Woovv) vector = eom.amplitudes_to_vector(Hr1, Hr2) return vector
def get_range_symten(A,split,l,q=2): ''' Compute a range that approximates the range of tensor A Reference: Algorithm 4.4 of https://arxiv.org/abs/0909.4061 args: A: symtensor The symtensor whose range we are finding split: int The index along which the svd will be done l: int The number of vectors to be used (output will be size m x l) kwargs: q: int The number of iterations to perform (default = 2) returns: Q: symtensor An orthonormal tensor whose range approximates the range of the input tensor A ''' # Get tensor dimensions ndiml = split ndimr = A.ndim-split # Generate Random Gaussian Matrix Omega = make_omega(A,split,l) # Initial Setup einstr = STR[:ndiml+ndimr]+','\ +STR[ndiml:ndiml+ndimr+1]+'->'\ +STR[:ndiml]+STR[ndiml+ndimr:ndiml+ndimr+1] Y = einsum(einstr,A,Omega) Q = orthonormal_ten(Y,ndiml) #Q = orthonormal_ten_slow(Y,ndiml) # Loop through iterations for i in range(q): # First step einstr = STR[:ndiml+ndimr]+','\ +STR[:ndiml]+STR[ndiml+ndimr:ndiml+ndimr+1]+'->'\ +STR[ndiml:ndiml+ndimr+1] Y = einsum(einstr,A,Q) Q = orthonormal_ten(Y,ndimr) # Second Step einstr = STR[:ndiml+ndimr]+','\ +STR[ndiml:ndiml+ndimr+1]+'->'\ +STR[:ndiml]+STR[ndiml+ndimr:ndiml+ndimr+1] Y = einsum(einstr,A,Q) Q = orthonormal_ten(Y,ndiml) # Return Result return Q
def energy(cc, t1, t2, eris): log = Logger(cc.stdout, cc.verbose) nkpts = len(cc.kpts) e = 2 * lib.einsum('ia,ia', eris.fov, t1) tau = lib.einsum('ia,jb->ijab', t1, t1) tau += t2 e += 2 * lib.einsum('ijab,iajb', tau, eris.ovov) e += -lib.einsum('ijab,ibja', tau, eris.ovov) if abs(e.imag) > 1e-4: log.warn('Non-zero imaginary part found in KRCCSD energy %s', e) return e.real / nkpts
def init_amps(self, eris): time0 = time.clock(), time.time() log = Logger(self.stdout, self.verbose) nocc = self.nocc nvir = self.nmo - nocc kpts = self.kpts nkpts = self.nkpts gvec = self._scf.cell.reciprocal_vectors() sym1 = ['+-', [ kpts, ] * 2, None, gvec] t1 = lib.zeros([nocc, nvir], eris.dtype, sym1) t2 = eris.ovov.transpose(0, 2, 1, 3).conj() / eris.eijab self.emp2 = 2 * lib.einsum('ijab,iajb', t2, eris.ovov) self.emp2 -= lib.einsum('ijab,ibja', t2, eris.ovov) self.emp2 = self.emp2.real / nkpts log.info('Init t2, MP2 energy (with fock eigenvalue shift) = %.15g', self.emp2) log.timer('init mp2', *time0) return self.emp2, t1, t2
def rsvd_symten(A,split,k,q=2,nover=2): ''' Compute the svd of a tensor using the randomized svd algorithm detailed in https://arxiv.org/abs/0909.4061. Here, we use algorithm 4.4 for step A and algorithm 5.1 for step B args: A: symtensor The matrix whose range we are finding split: int The index along which the svd will be done l: int The number of vectors to be used (output will be size m x l) kwargs: q: int The number of iterations to perform (default = 2) nover: int The number of extra vectors to be used (will be truncated off at the end) returns: Q: symtensor The resulting unitary U tensor from SVD R: symtensor The resulting S*V tensor from SVD ''' # Do Step A Q = get_range_symten(A,split,k+nover,q=q) # Do Step B ndiml = split ndimr = A.ndim-split einstr = STR[:ndiml+1] + ','\ +STR[:ndiml] + STR[ndiml+1:ndiml+ndimr+1] + '->'\ +STR[ndiml:ndiml+ndimr+1] B = einsum(einstr,Q,A) # Truncate from l to k Q = truncate(Q,Q.ndim-1,k) B = truncate(B,0,k) # Return Result return Q,B
def eaccsd_matvec(eom, vector, kshift, imds=None, diag=None): # Ref: Nooijen and Bartlett, J. Chem. Phys. 102, 3629 (1994) Eqs.(30)-(31) if imds is None: imds = eom.make_imds() r1, r2 = eom.vector_to_amplitudes(vector, kshift) # Eq. (30) # 1p-1p block Hr1 = lib.einsum('ac,c->a', imds.Lvv, r1) # 1p-2p1h block Hr1 += lib.einsum('ld,lad->a', 2. * imds.Fov, r2) Hr1 += lib.einsum('ld,lda->a', -imds.Fov, r2) Hr1 += 2 * lib.einsum('alcd,lcd->a', imds.Wvovv, r2) Hr1 += -lib.einsum('aldc,lcd->a', imds.Wvovv, r2) # Eq. (31) # 2p1h-1p block Hr2 = lib.einsum('abcj,c->jab', imds.Wvvvo, r1) # 2p1h-2p1h block if eom.partition == 'mp': foo = imds.eris.foo fvv = imds.eris.fvv Hr2 += lib.einsum('ac,jcb->jab', fvv, r2) Hr2 += lib.einsum('bd,jad->jab', fvv, r2) Hr2 += -lib.einsum('lj,lab->jab', foo, r2) elif eom.partition == 'full': Hr2 += eom._eaccsd_diag_matrix2 * r2 else: Hr2 += lib.einsum('ac,jcb->jab', imds.Lvv, r2) Hr2 += lib.einsum('bd,jad->jab', imds.Lvv, r2) Hr2 += -lib.einsum('lj,lab->jab', imds.Loo, r2) Hr2 += 2 * lib.einsum('lbdj,lad->jab', imds.Wovvo, r2) Hr2 += -lib.einsum('lbjd,lad->jab', imds.Wovov, r2) Hr2 += -lib.einsum('lajc,lcb->jab', imds.Wovov, r2) Hr2 += -lib.einsum('lbcj,lca->jab', imds.Wovvo, r2) Hr2 += lib.einsum('abcd,jcd->jab', imds.Wvvvv, r2) tmp = (2 * lib.einsum('klcd,lcd->k', imds.Woovv, r2) - lib.einsum('kldc,lcd->k', imds.Woovv, r2)) Hr2 += -lib.einsum('k,kjab->jab', tmp, imds.t2) vector = eom.amplitudes_to_vector(Hr1, Hr2) return vector
def ipccsd_matvec(eom, vector, kshift, imds=None, diag=None): # Ref: Nooijen and Snijders, J. Chem. Phys. 102, 1681 (1995) Eqs.(8)-(9) if imds is None: imds = eom.make_imds() r1, r2 = eom.vector_to_amplitudes(vector, kshift) # 1h-1h block Hr1 = -lib.einsum('ki,k->i', imds.Loo, r1) #1h-2h1p block Hr1 += 2 * lib.einsum('ld,ild->i', imds.Fov, r2) Hr1 += -lib.einsum('kd,kid->i', imds.Fov, r2) Hr1 += -2 * lib.einsum('klid,kld->i', imds.Wooov, r2) Hr1 += lib.einsum('lkid,kld->i', imds.Wooov, r2) # 2h1p-1h block Hr2 = -lib.einsum('kbij,k->ijb', imds.Wovoo, r1) # 2h1p-2h1p block if eom.partition == 'mp': foo = self.eris.foo fvv = self.eris.fvv Hr2 += lib.einsum('bd,ijd->ijb', fvv, r2) Hr2 += -lib.einsum('ki,kjb->ijb', foo, r2) Hr2 += -lib.einsum('lj,ilb->ijb', foo, r2) elif eom.partition == 'full': Hr2 += self._ipccsd_diag_matrix2 * r2 else: Hr2 += lib.einsum('bd,ijd->ijb', imds.Lvv, r2) Hr2 += -lib.einsum('ki,kjb->ijb', imds.Loo, r2) Hr2 += -lib.einsum('lj,ilb->ijb', imds.Loo, r2) Hr2 += lib.einsum('klij,klb->ijb', imds.Woooo, r2) Hr2 += 2 * lib.einsum('lbdj,ild->ijb', imds.Wovvo, r2) Hr2 += -lib.einsum('kbdj,kid->ijb', imds.Wovvo, r2) Hr2 += -lib.einsum('lbjd,ild->ijb', imds.Wovov, r2) #typo in Ref Hr2 += -lib.einsum('kbid,kjd->ijb', imds.Wovov, r2) tmp = 2 * lib.einsum('lkdc,kld->c', imds.Woovv, r2) tmp += -lib.einsum('kldc,kld->c', imds.Woovv, r2) Hr2 += -lib.einsum('c,ijcb->ijb', tmp, imds.t2) vector = eom.amplitudes_to_vector(Hr1, Hr2) return vector
backend='numpy') # put image into symtensor A = np.array(mpl.image.imread(fname)) shape = A.shape Aog = A.copy() Aog2 = A.copy() Aog3 = A.copy() A = np.reshape(A, (-1)) nelem = np.prod(ten1.array.shape) A = A[:nelem] ten1.array = np.reshape(A, ten1.array.shape) ten1.enforce_sym() # Use existing SVD w/o trunc ----------------------------------------------- U, S, V = symsvd(ten1, [[0, 1, 2], [3, 4]]) A2 = einsum('ijkl,lmn->ijkmn', U, einsum('jk,klm->jlm', S, V)) Aog = np.reshape(Aog, (-1)) Aog[:nelem] = np.reshape(A2.array, (-1)) Aog = np.reshape(Aog, shape) f = plt.figure() plt.imshow(Aog) # Use existing SVD w/ trunc ----------------------------------------------- U, S, V = symsvd(ten1, [[0, 1, 2], [3, 4]], truncate_mbd=k) A2 = einsum('ijkl,lmn->ijkmn', U, einsum('jk,klm->jlm', S, V)) Aog2 = np.reshape(Aog2, (-1)) Aog2[:nelem] = np.reshape(A2.array, (-1)) Aog2 = np.reshape(Aog2, shape) f = plt.figure() plt.imshow(Aog2)