def init_amps(self, eris=None): time0 = time.clock(), time.time() if eris is None: eris = self.ao2mo(self.mo_coeff) nocca, noccb = self.nocc fova = eris.focka[:nocca,nocca:] fovb = eris.fockb[:noccb,noccb:] mo_ea_o = eris.mo_energy[0][:nocca] mo_ea_v = eris.mo_energy[0][nocca:] mo_eb_o = eris.mo_energy[1][:noccb] mo_eb_v = eris.mo_energy[1][noccb:] eia_a = lib.direct_sum('i-a->ia', mo_ea_o, mo_ea_v) eia_b = lib.direct_sum('i-a->ia', mo_eb_o, mo_eb_v) t1a = fova.conj() / eia_a t1b = fovb.conj() / eia_b eris_ovov = np.asarray(eris.ovov) eris_OVOV = np.asarray(eris.OVOV) eris_ovOV = np.asarray(eris.ovOV) t2aa = eris_ovov.transpose(0,2,1,3) / lib.direct_sum('ia+jb->ijab', eia_a, eia_a) t2ab = eris_ovOV.transpose(0,2,1,3) / lib.direct_sum('ia+jb->ijab', eia_a, eia_b) t2bb = eris_OVOV.transpose(0,2,1,3) / lib.direct_sum('ia+jb->ijab', eia_b, eia_b) t2aa = t2aa - t2aa.transpose(0,1,3,2) t2bb = t2bb - t2bb.transpose(0,1,3,2) e = np.einsum('iJaB,iaJB', t2ab, eris_ovOV) e += 0.25*np.einsum('ijab,iajb', t2aa, eris_ovov) e -= 0.25*np.einsum('ijab,ibja', t2aa, eris_ovov) e += 0.25*np.einsum('ijab,iajb', t2bb, eris_OVOV) e -= 0.25*np.einsum('ijab,ibja', t2bb, eris_OVOV) self.emp2 = e.real logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2) logger.timer(self, 'init mp2', *time0) return self.emp2, (t1a,t1b), (t2aa,t2ab,t2bb)
def make_intermediates(mycc, t1, t2, eris): saved = ccsd_lambda.make_intermediates(mycc, t1, t2, eris) nocc, nvir = t1.shape eris_ovvv = _cp(eris.ovvv) eris_ovvv = lib.unpack_tril(eris_ovvv.reshape(nocc*nvir,-1)) eris_ovvv = eris_ovvv.reshape(nocc,nvir,nvir,nvir) mo_e = mycc._scf.mo_energy eia = lib.direct_sum('i-a->ia',mo_e[:nocc], mo_e[nocc:]) d3 = lib.direct_sum('ia,jb,kc->ijkabc', eia, eia, eia) eris_ovoo = eris.ovoo w =(numpy.einsum('iabf,kjcf->ijkabc', eris_ovvv, t2) - numpy.einsum('iajm,mkbc->ijkabc', eris_ovoo, t2)) / d3 v = numpy.einsum('iajb,kc->ijkabc', eris.ovov, t1) / d3 * .5 w = p6_(w) v = p6_(v) rwv = r6_(w*2+v) jov = numpy.einsum('jbkc,ijkabc->ia', eris.ovov, r6_(w)) joovv = numpy.einsum('iabf,ijkabc->kjcf', eris_ovvv, rwv) joovv-= numpy.einsum('iajm,ijkabc->mkbc', eris.ovoo, rwv) joovv = joovv + joovv.transpose(1,0,3,2) saved.jov = jov saved.joovv = joovv return saved
def solve_mo1(sscobj, mo_energy=None, mo_coeff=None, mo_occ=None, h1=None, s1=None, with_cphf=None): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) if mo_energy is None: mo_energy = sscobj._scf.mo_energy if mo_coeff is None: mo_coeff = sscobj._scf.mo_coeff if mo_occ is None: mo_occ = sscobj._scf.mo_occ if with_cphf is None: with_cphf = sscobj.cphf mol = sscobj.mol if h1 is None: atmlst = sorted(set([j for i,j in sscobj.nuc_pair])) h1a, h1b = make_h1_pso(mol, sscobj._scf.mo_coeff, mo_occ, atmlst) else: h1a, h1b = h1 h1a = numpy.asarray(h1a) h1b = numpy.asarray(h1b) if with_cphf: if callable(with_cphf): vind = with_cphf else: vind = gen_vind(sscobj._scf, mo_coeff, mo_occ) mo1, mo_e1 = ucphf.solve(vind, mo_energy, mo_occ, (h1a,h1b), None, sscobj.max_cycle_cphf, sscobj.conv_tol, verbose=log) else: eai_aa = lib.direct_sum('i-a->ai', mo_energy[0][mo_occ[0]>0], mo_energy[0][mo_occ[0]==0]) eai_bb = lib.direct_sum('i-a->ai', mo_energy[1][mo_occ[1]>0], mo_energy[1][mo_occ[1]==0]) mo1 = (h1a * (1/eai_aa), h1b * (1/eai_bb)) mo_e1 = None logger.timer(sscobj, 'solving mo1 eqn', *cput1) return mo1, mo_e1
def gamma1_intermediates(mycc, t1, t2, l1, l2, eris=None): doo, dov, dvo, dvv = ccsd_rdm.gamma1_intermediates(mycc, t1, t2, l1, l2) if eris is None: eris = ccsd._ERIS(mycc) nocc, nvir = t1.shape eris_ovvv = _cp(eris.ovvv) eris_ovvv = _ccsd.unpack_tril(eris_ovvv.reshape(nocc*nvir,-1)) eris_ovvv = eris_ovvv.reshape(nocc,nvir,nvir,nvir) mo_e = mycc._scf.mo_energy eia = lib.direct_sum('i-a->ia',mo_e[:nocc], mo_e[nocc:]) d3 = lib.direct_sum('ia,jb,kc->ijkabc', eia, eia, eia) eris_ovoo = eris.ovoo w =(numpy.einsum('iabf,kjcf->ijkabc', eris_ovvv, t2) - numpy.einsum('iajm,mkbc->ijkabc', eris_ovoo, t2)) / d3 v = numpy.einsum('iajb,kc->ijkabc', eris.ovov, t1) / d3 * .5 w = p6_(w) v = p6_(v) wv = w+v rw = r6_(w) goo =-numpy.einsum('iklabc,jklabc->ij', wv, rw) * .5 gvv = numpy.einsum('ijkacd,ijkbcd->ab', wv, rw) * .5 doo += goo dvv += gvv return doo, dov, dvo, dvv
def gamma2_intermediates(mycc, t1, t2, l1, l2, eris=None): dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov = \ ccsd_rdm.gamma2_intermediates(mycc, t1, t2, l1, l2) if eris is None: eris = ccsd._ERIS(mycc) nocc, nvir = t1.shape eris_ovvv = _cp(eris.ovvv) eris_ovvv = _ccsd.unpack_tril(eris_ovvv.reshape(nocc*nvir,-1)) eris_ovvv = eris_ovvv.reshape(nocc,nvir,nvir,nvir) mo_e = mycc._scf.mo_energy eia = lib.direct_sum('i-a->ia',mo_e[:nocc], mo_e[nocc:]) d3 = lib.direct_sum('ia,jb,kc->ijkabc', eia, eia, eia) eris_ovoo = eris.ovoo w =(numpy.einsum('iabf,kjcf->ijkabc', eris_ovvv, t2) - numpy.einsum('iajm,mkbc->ijkabc', eris_ovoo, t2)) / d3 v = numpy.einsum('iajb,kc->ijkabc', eris.ovov, t1) / d3 * .5 w = p6_(w) v = p6_(v) rw = r6_(w) rwv = r6_(w*2+v) dovov += numpy.einsum('kc,ijkabc->iajb', t1, rw) * .5 dooov -= numpy.einsum('mkbc,ijkabc->jmia', t2, rwv) # Note "dovvv +=" also changes the value of dvvov dovvv += numpy.einsum('kjcf,ijkabc->iabf', t2, rwv) dvvov = dovvv.transpose(2,3,0,1) return dovov, dvvvv, doooo, doovv, dovvo, dvvov, dovvv, dooov
def kernel(mp, mo_energy, mo_coeff, nocc, ioblk=256, verbose=None): nmo = mo_coeff.shape[1] nvir = nmo - nocc auxmol = df.incore.format_aux_basis(mp.mol, mp.auxbasis) naoaux = auxmol.nao_nr() iolen = max(int(ioblk*1e6/8/(nvir*nocc)), 160) eia = lib.direct_sum('i-a->ia', mo_energy[:nocc], mo_energy[nocc:]) t2 = None emp2 = 0 with mp.ao2mo(mo_coeff, nocc) as fov: for p0, p1 in prange(0, naoaux, iolen): logger.debug(mp, 'Load cderi block %d:%d', p0, p1) qov = numpy.array(fov[p0:p1], copy=False) for i in range(nocc): buf = numpy.dot(qov[:,i*nvir:(i+1)*nvir].T, qov).reshape(nvir,nocc,nvir) gi = numpy.array(buf, copy=False) gi = gi.reshape(nvir,nocc,nvir).transpose(1,2,0) t2i = gi/lib.direct_sum('jb+a->jba', eia, eia[i]) # 2*ijab-ijba theta = gi*2 - gi.transpose(0,2,1) emp2 += numpy.einsum('jab,jab', t2i, theta) return emp2, t2
def kernel(mp, mo_energy=None, mo_coeff=None, eris=None, with_t2=WITH_T2, verbose=logger.NOTE): if mo_energy is None or mo_coeff is None: moidx = mp.get_frozen_mask() mo_coeff = None mo_energy = (mp.mo_energy[0][moidx[0]], mp.mo_energy[1][moidx[1]]) else: # For backward compatibility. In pyscf-1.4 or earlier, mp.frozen is # not supported when mo_energy or mo_coeff is given. assert(mp.frozen is 0 or mp.frozen is None) if eris is None: eris = mp.ao2mo(mo_coeff) nocca, noccb = mp.get_nocc() nmoa, nmob = mp.get_nmo() nvira, nvirb = nmoa-nocca, nmob-noccb mo_ea, mo_eb = mo_energy eia_a = mo_ea[:nocca,None] - mo_ea[None,nocca:] eia_b = mo_eb[:noccb,None] - mo_eb[None,noccb:] if with_t2: dtype = eris.ovov.dtype t2aa = numpy.empty((nocca,nocca,nvira,nvira), dtype=dtype) t2ab = numpy.empty((nocca,noccb,nvira,nvirb), dtype=dtype) t2bb = numpy.empty((noccb,noccb,nvirb,nvirb), dtype=dtype) t2 = (t2aa,t2ab,t2bb) else: t2 = None emp2 = 0.0 for i in range(nocca): eris_ovov = numpy.asarray(eris.ovov[i*nvira:(i+1)*nvira]) eris_ovov = eris_ovov.reshape(nvira,nocca,nvira).transpose(1,0,2) t2i = eris_ovov.conj()/lib.direct_sum('a+jb->jab', eia_a[i], eia_a) emp2 += numpy.einsum('jab,jab', t2i, eris_ovov) * .5 emp2 -= numpy.einsum('jab,jba', t2i, eris_ovov) * .5 if with_t2: t2aa[i] = t2i - t2i.transpose(0,2,1) eris_ovov = numpy.asarray(eris.ovOV[i*nvira:(i+1)*nvira]) eris_ovov = eris_ovov.reshape(nvira,noccb,nvirb).transpose(1,0,2) t2i = eris_ovov.conj()/lib.direct_sum('a+jb->jab', eia_a[i], eia_b) emp2 += numpy.einsum('JaB,JaB', t2i, eris_ovov) if with_t2: t2ab[i] = t2i for i in range(noccb): eris_ovov = numpy.asarray(eris.OVOV[i*nvirb:(i+1)*nvirb]) eris_ovov = eris_ovov.reshape(nvirb,noccb,nvirb).transpose(1,0,2) t2i = eris_ovov.conj()/lib.direct_sum('a+jb->jab', eia_b[i], eia_b) emp2 += numpy.einsum('jab,jab', t2i, eris_ovov) * .5 emp2 -= numpy.einsum('jab,jba', t2i, eris_ovov) * .5 if with_t2: t2bb[i] = t2i - t2i.transpose(0,2,1) return emp2.real, t2
def get_sigma_element(gw, omega, tdm_p, tdm_q, td_e, eta=None, vir_sgn=1): if eta is None: eta = gw.eta nocc = gw.nocc evi = lib.direct_sum('v-i->vi', td_e, gw._scf.mo_energy[:nocc]) eva = lib.direct_sum('v+a->va', td_e, gw._scf.mo_energy[nocc:]) sigma = np.sum( tdm_p[:,:nocc]*tdm_q[:,:nocc]/(omega + evi - 1j*eta) ) sigma += np.sum( tdm_p[:,nocc:]*tdm_q[:,nocc:]/(omega - eva + vir_sgn*1j*eta) ) return sigma
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): '''For field dependent basis. First order overlap matrix is non-zero. The first order orbitals are set to C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] Kwargs: hermi : boolean Whether the matrix defined by fvind is Hermitian or not. Returns: First order orbital coefficients (in MO basis) and first order orbital energy matrix ''' log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_a = mo_energy[viridx] e_i = mo_energy[occidx] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nvir, nocc = e_ai.shape nmo = nocc + nvir s1 = s1.reshape(-1,nmo,nocc) hs = mo1base = h1.reshape(-1,nmo,nocc) - s1*e_i mo_e1 = hs[:,occidx,:].copy() mo1base[:,viridx] *= -e_ai mo1base[:,occidx] = -s1[:,occidx] * .5 def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) v[:,viridx,:] *= e_ai v[:,occidx,:] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v1mo = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) mo1[:,viridx] = mo1base[:,viridx] - v1mo[:,viridx]*e_ai # mo_e1 has the same symmetry as the first order Fock matrix (hermitian or # anti-hermitian). mo_e1 = v1mo - s1*lib.direct_sum('i+j->ij',e_i,e_i) mo_e1 += mo1[:,occidx] * lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += v1mo[:,occidx,:] if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
def get_init_guess(self, eris=None, nroots=1, diag=None): if eris is None: eris = self.ao2mo(self.mo_coeff) nocca, noccb = self.nocc mo_ea, mo_eb = eris.mo_energy eia_a = mo_ea[:nocca,None] - mo_ea[None,nocca:] eia_b = mo_eb[:noccb,None] - mo_eb[None,noccb:] t1a = eris.focka[:nocca,nocca:].conj() / eia_a t1b = eris.fockb[:noccb,noccb:].conj() / eia_b eris_ovov = _cp(eris.ovov) eris_ovOV = _cp(eris.ovOV) eris_OVOV = _cp(eris.OVOV) t2aa = eris_ovov.transpose(0,2,1,3) - eris_ovov.transpose(0,2,3,1) t2bb = eris_OVOV.transpose(0,2,1,3) - eris_OVOV.transpose(0,2,3,1) t2ab = eris_ovOV.transpose(0,2,1,3).copy() t2aa = t2aa.conj() t2ab = t2ab.conj() t2bb = t2bb.conj() t2aa /= lib.direct_sum('ia+jb->ijab', eia_a, eia_a) t2ab /= lib.direct_sum('ia+jb->ijab', eia_a, eia_b) t2bb /= lib.direct_sum('ia+jb->ijab', eia_b, eia_b) emp2 = numpy.einsum('iajb,ijab', eris_ovov, t2aa) * .25 emp2 -= numpy.einsum('jaib,ijab', eris_ovov, t2aa) * .25 emp2 += numpy.einsum('iajb,ijab', eris_OVOV, t2bb) * .25 emp2 -= numpy.einsum('jaib,ijab', eris_OVOV, t2bb) * .25 emp2 += numpy.einsum('iajb,ijab', eris_ovOV, t2ab) self.emp2 = emp2.real logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2) if abs(emp2) < 1e-3 and (abs(t1a).sum()+abs(t1b).sum()) < 1e-3: t1a = 1e-1 / eia_a t1b = 1e-1 / eia_b ci_guess = amplitudes_to_cisdvec(1, (t1a,t1b), (t2aa,t2ab,t2bb)) if nroots > 1: civec_size = ci_guess.size ci1_size = t1a.size + t1b.size dtype = ci_guess.dtype nroots = min(ci1_size+1, nroots) if diag is None: idx = range(1, nroots) else: idx = diag[:ci1_size+1].argsort()[1:nroots] # exclude HF determinant ci_guess = [ci_guess] for i in idx: g = numpy.zeros(civec_size, dtype) g[i] = 1.0 ci_guess.append(g) return self.emp2, ci_guess
def update_amps(mycc, t1, t2, l1, l2, eris=None, saved=None): if eris is None: eris = ccsd._ERIS(mycc) if saved is None: saved = make_intermediates(mycc, t1, t2, eris) nocc, nvir = t1.shape l1, l2 = ccsd_lambda.update_amps(mycc, t1, t2, l1, l2, eris, saved) mo_e = eris.fock.diagonal() eia = lib.direct_sum('i-a->ia', mo_e[:nocc], mo_e[nocc:]) l1 += saved.jov/eia * .5 eijab = lib.direct_sum('ia+jb->ijab', eia, eia) l2 += (saved.joovv*(2./3)+saved.joovv.transpose(1,0,2,3)*(1./3)) / eijab return l1, l2
def make_intermediates(mycc, t1, t2, eris): imds = ccsd_lambda.make_intermediates(mycc, t1, t2, eris) nocc, nvir = t1.shape eris_ovvv = numpy.asarray(eris.get_ovvv()) eris_ovoo = numpy.asarray(eris.ovoo) eris_ovov = numpy.asarray(eris.ovov) mo_e = eris.mo_energy eia = lib.direct_sum('i-a->ia', mo_e[:nocc], mo_e[nocc:]) d3 = lib.direct_sum('ia,jb,kc->ijkabc', eia, eia, eia) def p6(t): t1 = t + t.transpose(0,2,1,3,5,4) return t1 + t1.transpose(1,0,2,4,3,5) + t1.transpose(1,2,0,4,5,3) def r6(w): return (4 * w + w.transpose(0,1,2,4,5,3) + w.transpose(0,1,2,5,3,4) - 2 * w.transpose(0,1,2,5,4,3) - 2 * w.transpose(0,1,2,3,5,4) - 2 * w.transpose(0,1,2,4,3,5)) w =(numpy.einsum('iafb,kjcf->ijkabc', eris_ovvv.conj(), t2) - numpy.einsum('iajm,mkbc->ijkabc', eris_ovoo.conj(), t2)) / d3 v =(numpy.einsum('iajb,kc->ijkabc', eris_ovov.conj(), t1) + numpy.einsum('ck,ijab->ijkabc', eris.fock[nocc:,:nocc], t2)) / d3 w = p6(w) v = p6(v) imds.l1_t = numpy.einsum('jbkc,ijkabc->ia', eris_ovov, r6(w)).conj() / eia * .5 def as_r6(m): # When making derivative over t2, r6 should be called on the 6-index # tensor. It gives the equation for lambda2, but not corresponding to # the lambda equation used by RCCSD-lambda code. A transformation was # applied in RCCSD-lambda equation F(lambda)_{ijab} = 0: # 2/3 * # F(lambda)_{ijab} + 1/3 * F(lambda)_{jiab} = 0 # Combining this transformation with r6 operation, leads to the # transformation code below return m * 2 - m.transpose(0,1,2,5,4,3) - m.transpose(0,1,2,3,5,4) m = as_r6(w * 2 + v * .5) joovv = numpy.einsum('kfbe,ijkaef->ijab', eris_ovvv, m.conj()) joovv-= numpy.einsum('ncmj,imnabc->ijab', eris_ovoo, m.conj()) joovv = joovv + joovv.transpose(1,0,3,2) rw = as_r6(w) joovv+= numpy.einsum('kc,ijkabc->ijab', eris.fock[:nocc,nocc:], rw.conj()) imds.l2_t = joovv / lib.direct_sum('ia+jb->ijab', eia, eia) return imds
def solve_withs1(fvind, mo_energy, mo_occ, h1, s1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): ''' C^1_{ij} = -1/2 S1 e1 = h1 - s1*e0 + (e0_j-e0_i)*c1 + vhf[c1] ''' if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) occidx = mo_occ > 0 viridx = mo_occ == 0 e_a = mo_energy[viridx] e_i = mo_energy[occidx] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nvir, nocc = e_ai.shape nmo = nocc + nvir # Do not reshape h1 because h1 may be a 2D array (nvir,nocc) s1 = s1.reshape(-1,nmo,nocc) hs = mo1base = h1.reshape(-1,nmo,nocc) - s1*e_i mo_e1 = hs[:,occidx,:].copy() mo1base[:,viridx] *= -e_ai mo1base[:,occidx] = -s1[:,occidx] * .5 def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) v[:,viridx,:] *= e_ai v[:,occidx,:] = 0 return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) mo1 = mo1.reshape(mo1base.shape) log.timer('krylov solver in CPHF', *t0) v_mo = fvind(mo1.reshape(h1.shape)).reshape(-1,nmo,nocc) mo1[:,viridx] = mo1base[:,viridx] - v_mo[:,viridx]*e_ai mo_e1 += mo1[:,occidx] * lib.direct_sum('i-j->ij', e_i, e_i) mo_e1 += v_mo[:,occidx,:] if h1.ndim == 3: return mo1, mo_e1 else: return mo1.reshape(h1.shape), mo_e1.reshape(nocc,nocc)
def kernel(myci, eris, ci0=None, max_cycle=50, tol=1e-8, verbose=logger.INFO): mol = myci.mol nmo = myci.nmo nocc = myci.nocc mo_energy = eris.fock.diagonal() diag = make_diagonal(mol, mo_energy, eris, nocc) ehf = diag[0] diag -= ehf if ci0 is None: # MP2 initial guess nvir = nmo - nocc e_i = mo_energy[:nocc] e_a = mo_energy[nocc:] ci0 = numpy.zeros(1+nocc*nvir+(nocc*nvir)**2) ci0[0] = 1 t2 = 2*eris.voov.transpose(1,2,0,3) - eris.voov.transpose(1,2,3,0) t2 /= lib.direct_sum('i+j-a-b', e_i, e_i, e_a, e_a) ci0[1+nocc*nvir:] = t2.ravel() def op(x): return contract(myci, x, eris) def precond(x, e, *args): return x / (diag - e) def cisd_dot(x1, x2): return dot(x1, x2, nocc, nvir) ecisd, ci = lib.davidson(op, ci0, precond, max_cycle=max_cycle, tol=tol, dot=cisd_dot, verbose=verbose) conv = True # It should be checked in lib.davidson function return conv, ecisd, ci
def _gamma1_intermediates(mp, t2=None, eris=None): if t2 is None: t2 = mp.t2 nmo = mp.nmo nocc = mp.nocc nvir = nmo - nocc if t2 is None: if eris is None: eris = mp.ao2mo() mo_energy = _mo_energy_without_core(mp, mp.mo_energy) eia = mo_energy[:nocc,None] - mo_energy[None,nocc:] dtype = eris.ovov.dtype else: dtype = t2.dtype dm1occ = numpy.zeros((nocc,nocc), dtype=dtype) dm1vir = numpy.zeros((nvir,nvir), dtype=dtype) for i in range(nocc): if t2 is None: gi = numpy.asarray(eris.ovov[i*nvir:(i+1)*nvir]) gi = gi.reshape(nvir,nocc,nvir).transpose(1,0,2) t2i = gi.conj()/lib.direct_sum('jb+a->jba', eia, eia[i]) else: t2i = t2[i] l2i = t2i.conj() dm1vir += numpy.einsum('jca,jcb->ba', l2i, t2i) * 2 \ - numpy.einsum('jca,jbc->ba', l2i, t2i) dm1occ += numpy.einsum('iab,jab->ij', l2i, t2i) * 2 \ - numpy.einsum('iab,jba->ij', l2i, t2i) return -dm1occ, dm1vir
def get_vind(self, zs): mol = self.mol mo_coeff = self._scf.mo_coeff mo_energy = self._scf.mo_energy nao, nmo = mo_coeff.shape nocc = (self._scf.mo_occ>0).sum() nvir = nmo - nocc orbv = mo_coeff[:,nocc:] orbo = mo_coeff[:,:nocc] eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) dai = numpy.sqrt(eai).ravel() nz = len(zs) dmvo = numpy.empty((nz,nao,nao)) for i, z in enumerate(zs): dm = reduce(numpy.dot, (orbv, (dai*z).reshape(nvir,nocc), orbo.T)) dmvo[i] = dm + dm.T # +cc for A+B and K_{ai,jb} in A == K_{ai,bj} in B mem_now = lib.current_memory()[0] max_memory = max(2000, self.max_memory*.9-mem_now) v1ao = _contract_xc_kernel(self, self._scf.xc, dmvo, singlet=self.singlet, max_memory=max_memory) if self.singlet: vj = self._scf.get_j(mol, dmvo, hermi=1) v1ao += vj * 2 v1vo = _ao2mo.nr_e2(v1ao, mo_coeff, (nocc,nmo,0,nocc)).reshape(-1,nvir*nocc) edai = eai.ravel() * dai for i, z in enumerate(zs): # numpy.sqrt(eai) * (eai*dai*z + v1vo) v1vo[i] += edai*z v1vo[i] *= dai return v1vo.reshape(nz,-1)
def gen_hop_rhf_external(mf): mol = mf.mol mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nmo = mo_coeff.shape[1] nocc = numpy.count_nonzero(mo_occ) nvir = nmo - nocc nov = nocc * nvir eri_mo = ao2mo.full(mol, mo_coeff) eri_mo = ao2mo.restore(1, eri_mo, nmo) eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) # A h = numpy.einsum('ckld->kcld', eri_mo[nocc:,:nocc,:nocc,nocc:]) * 2 h-= numpy.einsum('cdlk->kcld', eri_mo[nocc:,nocc:,:nocc,:nocc]) for a in range(nvir): for i in range(nocc): h[i,a,i,a] += eai[a,i] # B h-= numpy.einsum('ckdl->kcld', eri_mo[nocc:,:nocc,nocc:,:nocc]) * 2 h+= numpy.einsum('cldk->kcld', eri_mo[nocc:,:nocc,nocc:,:nocc]) h1 = h.transpose(1,0,3,2).reshape(nov,nov) def hop1(x): return h1.dot(x) h =-numpy.einsum('cdlk->kcld', eri_mo[nocc:,nocc:,:nocc,:nocc]) for a in range(nvir): for i in range(nocc): h[i,a,i,a] += eai[a,i] h-= numpy.einsum('cldk->kcld', eri_mo[nocc:,:nocc,nocc:,:nocc]) h2 = h.transpose(1,0,3,2).reshape(nov,nov) def hop2(x): return h2.dot(x) return hop1, hop2
def rhf_internal(mf, verbose=None): log = logger.new_logger(mf, verbose) mol = mf.mol mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nmo = mo_coeff.shape[1] nocc = numpy.count_nonzero(mo_occ) nvir = nmo - nocc eri_mo = ao2mo.full(mol, mo_coeff) eri_mo = ao2mo.restore(1, eri_mo, nmo) eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) # A h = numpy.einsum('ckld->kcld', eri_mo[nocc:,:nocc,:nocc,nocc:]) * 2 h-= numpy.einsum('cdlk->kcld', eri_mo[nocc:,nocc:,:nocc,:nocc]) for a in range(nvir): for i in range(nocc): h[i,a,i,a] += eai[a,i] # B h+= numpy.einsum('ckdl->kcld', eri_mo[nocc:,:nocc,nocc:,:nocc]) * 2 h-= numpy.einsum('cldk->kcld', eri_mo[nocc:,:nocc,nocc:,:nocc]) nov = nocc * nvir e = scipy.linalg.eigh(h.reshape(nov,nov))[0] log.debug('rhf_internal: lowest eigs = %s', e[e<=max(e[0],1e-5)]) if e[0] < -1e-5: log.log('RHF wavefunction has an internal instablity') else: log.log('RHF wavefunction is stable in the intenral stablity analysis')
def kernel(mp, mo_energy=None, mo_coeff=None, eris=None, with_t2=WITH_T2, verbose=logger.NOTE): if mo_energy is None or mo_coeff is None: mo_coeff = None mo_energy = mp.mo_energy[mp.get_frozen_mask()] else: # For backward compatibility. In pyscf-1.4 or earlier, mp.frozen is # not supported when mo_energy or mo_coeff is given. assert(mp.frozen is 0 or mp.frozen is None) if eris is None: eris = mp.ao2mo(mo_coeff) nocc = mp.nocc nvir = mp.nmo - nocc moidx = mp.get_frozen_mask() eia = mo_energy[:nocc,None] - mo_energy[None,nocc:] if with_t2: t2 = numpy.empty((nocc,nocc,nvir,nvir), dtype=eris.oovv.dtype) else: t2 = None emp2 = 0 for i in range(nocc): gi = numpy.asarray(eris.oovv[i]).reshape(nocc,nvir,nvir) t2i = gi.conj()/lib.direct_sum('jb+a->jba', eia, eia[i]) emp2 += numpy.einsum('jab,jab', t2i, gi) * .25 if with_t2: t2[i] = t2i return emp2.real, t2
def init_amps(self, eris): time0 = time.clock(), time.time() nocc = self.nocc() nvir = self.nmo() - nocc nkpts = self.nkpts t1 = numpy.zeros((nkpts, nocc, nvir), dtype=numpy.complex128) t2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir), dtype=numpy.complex128) woovv = numpy.empty((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir), dtype=numpy.complex128) self.emp2 = 0 foo = eris.fock[:, :nocc, :nocc].copy() fvv = eris.fock[:, nocc:, nocc:].copy() eris_oovv = eris.oovv.copy() eia = numpy.zeros((nocc, nvir)) eijab = numpy.zeros((nocc, nocc, nvir, nvir)) kconserv = self.kconserv 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) woovv[ki, kj, ka] = 2 * eris_oovv[ki, kj, ka] - eris_oovv[ki, kj, kb].transpose(0, 1, 3, 2) t2[ki, kj, ka] = eris_oovv[ki, kj, ka] / eijab t2 = numpy.conj(t2) self.emp2 = numpy.einsum("pqrijab,pqrijab", t2, woovv).real self.emp2 /= nkpts logger.info(self, "Init t2, MP2 energy = %.15g", self.emp2) logger.timer(self, "init mp2", *time0) return self.emp2, t1, t2
def kernel(mp, mo_energy=None, mo_coeff=None, eris=None, with_t2=WITH_T2, verbose=logger.NOTE): if mo_energy is None or mo_coeff is None: if mp.mo_energy is None or mp.mo_coeff is None: raise RuntimeError('mo_coeff, mo_energy are not initialized.\n' 'You may need to call mf.kernel() to generate them.') mo_coeff = None mo_energy = _mo_energy_without_core(mp, mp.mo_energy) else: # For backward compatibility. In pyscf-1.4 or earlier, mp.frozen is # not supported when mo_energy or mo_coeff is given. assert(mp.frozen is 0 or mp.frozen is None) if eris is None: eris = mp.ao2mo(mo_coeff) nocc = mp.nocc nvir = mp.nmo - nocc eia = mo_energy[:nocc,None] - mo_energy[None,nocc:] if with_t2: t2 = numpy.empty((nocc,nocc,nvir,nvir), dtype=eris.ovov.dtype) else: t2 = None emp2 = 0 for i in range(nocc): gi = numpy.asarray(eris.ovov[i*nvir:(i+1)*nvir]) gi = gi.reshape(nvir,nocc,nvir).transpose(1,0,2) t2i = gi.conj()/lib.direct_sum('jb+a->jba', eia, eia[i]) emp2 += numpy.einsum('jab,jab', t2i, gi) * 2 emp2 -= numpy.einsum('jab,jba', t2i, gi) if with_t2: t2[i] = t2i return emp2.real, t2
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) e_a = mo_energy[mo_occ==0] e_i = mo_energy[mo_occ>0] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nocc = e_i.size nvir = e_a.size nmo = nocc + nvir mo1base = h1 * -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) return mo1.reshape(h1.shape), None
def kernel(cc, eris, t1=None, t2=None, max_memory=2000, verbose=logger.INFO): assert(isinstance(eris, gccsd._PhysicistsERIs)) if t1 is None or t2 is None: t1, t2 = cc.t1, cc.t2 nocc, nvir = t1.shape bcei = numpy.asarray(eris.ovvv).conj().transpose(3,2,1,0) majk = numpy.asarray(eris.ooov).conj().transpose(2,3,0,1) bcjk = numpy.asarray(eris.oovv).conj().transpose(2,3,0,1) mo_e = eris.fock.diagonal().real eia = mo_e[:nocc,None] - mo_e[nocc:] d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eia, eia) t3c =(numpy.einsum('jkae,bcei->ijkabc', t2, bcei) - numpy.einsum('imbc,majk->ijkabc', t2, majk)) t3c = t3c - t3c.transpose(0,1,2,4,3,5) - t3c.transpose(0,1,2,5,4,3) t3c = t3c - t3c.transpose(1,0,2,3,4,5) - t3c.transpose(2,1,0,3,4,5) t3c /= d3 # e4 = numpy.einsum('ijkabc,ijkabc,ijkabc', t3c.conj(), d3, t3c) / 36 # sia = numpy.einsum('jkbc,ijkabc->ia', eris.oovv, t3c) * .25 # e5 = numpy.einsum('ia,ia', sia, t1.conj()) # et = e4 + e5 # return et t3d = numpy.einsum('ia,bcjk->ijkabc', t1, bcjk) t3d += numpy.einsum('ai,jkbc->ijkabc', eris.fock[nocc:,:nocc], t2) t3d = t3d - t3d.transpose(0,1,2,4,3,5) - t3d.transpose(0,1,2,5,4,3) t3d = t3d - t3d.transpose(1,0,2,3,4,5) - t3d.transpose(2,1,0,3,4,5) t3d /= d3 et = numpy.einsum('ijkabc,ijkabc,ijkabc', (t3c+t3d).conj(), d3, t3c) / 36 return et
def fupdate(t1, t2, istep, normt, de, adiis): nocc, nvir = t1.shape nov = nocc*nvir moidx = numpy.ones(mycc.mo_energy.size, dtype=numpy.bool) if isinstance(mycc.frozen, (int, numpy.integer)): moidx[:mycc.frozen] = False else: moidx[mycc.frozen] = False mo_e = mycc.mo_energy[moidx] eia = mo_e[:nocc,None] - mo_e[None,nocc:] if (istep > mycc.diis_start_cycle and abs(de) < mycc.diis_start_energy_diff): if mycc.t1 is None: mycc.t1 = t1 mycc.t2 = t2 else: tbuf = numpy.empty(nov*(nov+1)) tbuf[:nov] = ((t1-mycc.t1)*eia).ravel() pbuf = tbuf[nov:].reshape(nocc,nocc,nvir,nvir) for i in range(nocc): pbuf[i] = (t2[i]-mycc.t2[i]) * lib.direct_sum('jb,a->jba', eia, eia[i]) adiis.push_err_vec(tbuf) tbuf = numpy.empty(nov*(nov+1)) tbuf[:nov] = t1.ravel() tbuf[nov:] = t2.ravel() t1.data = tbuf.data # release memory t2.data = tbuf.data tbuf = adiis.update(tbuf) mycc.t1 = t1 = tbuf[:nov].reshape(nocc,nvir) mycc.t2 = t2 = tbuf[nov:].reshape(nocc,nocc,nvir,nvir) logger.debug(mycc, 'DIIS for step %d', istep) return t1, t2
def get_vind(self, zs): '''Compute Ax''' mo_coeff = self._scf.mo_coeff mo_energy = self._scf.mo_energy nao, nmo = mo_coeff.shape nocc = (self._scf.mo_occ>0).sum() nvir = nmo - nocc orbv = mo_coeff[:,nocc:] orbo = mo_coeff[:,:nocc] nz = len(zs) dmvo = numpy.empty((nz,nao,nao)) for i, z in enumerate(zs): dmvo[i] = reduce(numpy.dot, (orbv, z.reshape(nvir,nocc), orbo.T)) vj, vk = self._scf.get_jk(self.mol, dmvo, hermi=0) if self.singlet: vhf = vj*2 - vk else: vhf = -vk #v1vo = numpy.asarray([reduce(numpy.dot, (orbv.T, v, orbo)) for v in vhf]) v1vo = _ao2mo.nr_e2(vhf, mo_coeff, (nocc,nmo,0,nocc)).reshape(-1,nvir*nocc) eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) eai = eai.ravel() for i, z in enumerate(zs): v1vo[i] += eai * z return v1vo.reshape(nz,-1)
def kernel(mp, mo_energy=None, mo_coeff=None, eris=None, with_t2=WITH_T2, verbose=logger.NOTE): if mo_energy is None or mo_coeff is None: mo_coeff = mp2._mo_without_core(mp, mp.mo_coeff) mo_energy = mp2._mo_energy_without_core(mp, mp.mo_energy) else: # For backward compatibility. In pyscf-1.4 or earlier, mp.frozen is # not supported when mo_energy or mo_coeff is given. assert(mp.frozen is 0 or mp.frozen is None) nocc = mp.nocc nvir = mp.nmo - nocc eia = mo_energy[:nocc,None] - mo_energy[None,nocc:] t2 = None emp2 = 0 for istep, qov in enumerate(mp.loop_ao2mo(mo_coeff, nocc)): logger.debug(mp, 'Load cderi step %d', istep) for i in range(nocc): buf = numpy.dot(qov[:,i*nvir:(i+1)*nvir].T, qov).reshape(nvir,nocc,nvir) gi = numpy.array(buf, copy=False) gi = gi.reshape(nvir,nocc,nvir).transpose(1,0,2) t2i = gi/lib.direct_sum('jb+a->jba', eia, eia[i]) emp2 += numpy.einsum('jab,jab', t2i, gi) * 2 emp2 -= numpy.einsum('jab,jba', t2i, gi) return emp2, t2
def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mo_energy = sscobj._scf.mo_energy mo_coeff = sscobj._scf.mo_coeff mo_occ = sscobj._scf.mo_occ nset = len(h1) eai = 1. / lib.direct_sum('a-i->ai', mo_energy[mo_occ==0], mo_energy[mo_occ>0]) mo1 = numpy.asarray(h1) * -eai if not sscobj.cphf: return mo1 orbo = mo_coeff[:,mo_occ> 0] orbv = mo_coeff[:,mo_occ==0] nocc = orbo.shape[1] nvir = orbv.shape[1] nmo = nocc + nvir vresp = _gen_rhf_response(sscobj._scf, singlet=False, hermi=1) mo_v_o = numpy.asarray(numpy.hstack((orbv,orbo)), order='F') def vind(mo1): dm1 = _dm1_mo2ao(mo1.reshape(nset,nvir,nocc), orbv, orbo*2) # *2 for double occupancy dm1 = dm1 + dm1.transpose(0,2,1) v1 = vresp(dm1) v1 = _ao2mo.nr_e2(v1, mo_v_o, (0,nvir,nvir,nmo)).reshape(nset,nvir,nocc) v1 *= eai return v1.ravel() mo1 = lib.krylov(vind, mo1.ravel(), tol=sscobj.conv_tol, max_cycle=sscobj.max_cycle_cphf, verbose=log) log.timer('solving FC CPHF eqn', *cput1) return mo1.reshape(nset,nvir,nocc)
def _gamma1_intermediates(mycc, t1, t2, l1, l2, eris=None): doo, dov, dvo, dvv = gccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2) if eris is None: eris = mycc.ao2mo() nocc, nvir = t1.shape bcei = numpy.asarray(eris.ovvv).conj().transpose(3,2,1,0) majk = numpy.asarray(eris.ooov).conj().transpose(2,3,0,1) bcjk = numpy.asarray(eris.oovv).conj().transpose(2,3,0,1) mo_e = eris.mo_energy eia = mo_e[:nocc,None] - mo_e[nocc:] d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eia, eia) t3c =(numpy.einsum('jkae,bcei->ijkabc', t2, bcei) - numpy.einsum('imbc,majk->ijkabc', t2, majk)) t3c = t3c - t3c.transpose(0,1,2,4,3,5) - t3c.transpose(0,1,2,5,4,3) t3c = t3c - t3c.transpose(1,0,2,3,4,5) - t3c.transpose(2,1,0,3,4,5) t3c /= d3 t3d = numpy.einsum('ia,bcjk->ijkabc', t1, bcjk) t3d += numpy.einsum('ai,jkbc->ijkabc', eris.fock[nocc:,:nocc], t2) t3d = t3d - t3d.transpose(0,1,2,4,3,5) - t3d.transpose(0,1,2,5,4,3) t3d = t3d - t3d.transpose(1,0,2,3,4,5) - t3d.transpose(2,1,0,3,4,5) t3d /= d3 goo = numpy.einsum('iklabc,jklabc->ij', (t3c+t3d).conj(), t3c) * (1./12) gvv = numpy.einsum('ijkacd,ijkbcd->ab', t3c+t3d, t3c.conj()) * (1./12) doo[numpy.diag_indices(nocc)] -= goo.diagonal() dvv[numpy.diag_indices(nvir)] += gvv.diagonal() dvo += numpy.einsum('ijab,ijkabc->ck', t2.conj(), t3c) * (1./4) return doo, dov, dvo, dvv
def kernel(self, x0=None): '''TDHF diagonalization with non-Hermitian eigenvalue solver ''' self.check_sanity() mo_energy = self._scf.mo_energy nocc = (self._scf.mo_occ>0).sum() eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) nvir = eai.shape[0] if x0 is None: x0 = self.init_guess(eai, self.nstates) precond = self.get_precond(eai.ravel()) # We only need positive eigenvalues def pickeig(w, v, nroots, x0): realidx = numpy.where((abs(w.imag) < 1e-6) & (w.real > 0))[0] idx = realidx[w[realidx].real.argsort()] return w[idx].real, v[:,idx].real, idx w, x1 = lib.davidson_nosym1(self.get_vind, x0, precond, tol=self.conv_tol, nroots=self.nstates, lindep=self.lindep, max_space=self.max_space, pick=pickeig, verbose=self.verbose)[1:] self.e = w def norm_xy(z): x, y = z.reshape(2,nvir,nocc) norm = 2*(lib.norm(x)**2 - lib.norm(y)**2) norm = 1/numpy.sqrt(norm) return x*norm, y*norm self.xy = [norm_xy(z) for z in x1] return self.e, self.xy
def init_amps(mycc, eris=None): eris = getattr(mycc, '_eris', None) if eris is None: mycc.ao2mo() eris = mycc._eris time0 = time.clock(), time.time() mo_e = eris.mo_energy nocc = mycc.nocc nvir = mo_e.size - nocc eia = mo_e[:nocc,None] - mo_e[None,nocc:] t1T = eris.fock[nocc:,:nocc] / eia.T loc0, loc1 = _task_location(nvir) t2T = numpy.empty((loc1-loc0,nvir,nocc,nocc)) max_memory = mycc.max_memory - lib.current_memory()[0] blksize = int(min(nvir, max(BLKMIN, max_memory*.3e6/8/(nocc**2*nvir+1)))) emp2 = 0 for p0, p1 in lib.prange(0, loc1-loc0, blksize): eris_ovov = eris.ovov[:,p0:p1] t2T[p0:p1] = (eris_ovov.transpose(1,3,0,2) / lib.direct_sum('ia,jb->abij', eia[:,p0+loc0:p1+loc0], eia)) emp2 += 2 * numpy.einsum('abij,iajb', t2T[p0:p1], eris_ovov) emp2 -= numpy.einsum('abji,iajb', t2T[p0:p1], eris_ovov) mycc.emp2 = comm.allreduce(emp2) logger.info(mycc, 'Init t2, MP2 energy = %.15g', mycc.emp2) logger.timer(mycc, 'init mp2', *time0) return mycc.emp2, t1T.T, t2T.transpose(2,3,0,1)
def solve_nos1(fvind, mo_energy, mo_occ, h1, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(sys.stdout, verbose) t0 = (time.clock(), time.time()) e_a = mo_energy[mo_occ == 0] e_i = mo_energy[mo_occ > 0] e_ai = 1 / lib.direct_sum('a-i->ai', e_a, e_i) nocc = e_i.size nvir = e_a.size nmo = nocc + nvir mo1base = h1 * -e_ai def vind_vo(mo1): v = fvind(mo1.reshape(h1.shape)).reshape(h1.shape) v *= e_ai return v.ravel() mo1 = lib.krylov(vind_vo, mo1base.ravel(), tol=tol, max_cycle=max_cycle, hermi=hermi, verbose=log) log.timer('krylov solver in CPHF', *t0) return mo1.reshape(h1.shape), None
def my_kernel(mp, mo_energy=None, mo_coeff=None, eris=None, with_eij=True): if mo_energy is None or mo_coeff is None: if mp.mo_energy is None or mp.mo_coeff is None: raise RuntimeError( 'mo_coeff, mo_energy are not initialized.\n' 'You may need to call mf.kernel() to generate them.') mo_coeff = None mo_energy = _mo_energy_without_core(mp, mp.mo_energy) else: # For backward compatibility. In pyscf-1.4 or earlier, mp.frozen is # not supported when mo_energy or mo_coeff is given. assert (mp.frozen is 0 or mp.frozen is None) if eris is None: eris = mp.ao2mo(mo_coeff) nocc = mp.nocc nvir = mp.nmo - nocc eia = mo_energy[:nocc, None] - mo_energy[None, nocc:] if with_eij: eij = np.empty((nocc, nocc), dtype=eia.dtype) else: eij = None emp2 = 0 for i in range(nocc): gi = np.asarray(eris.ovov[i * nvir:(i + 1) * nvir]) gi = gi.reshape(nvir, nocc, nvir).transpose(1, 0, 2) t2i = gi.conj() / lib.direct_sum('jb+a->jba', eia, eia[i]) tmp_eij = 2 * np.einsum('jab,jab->j', t2i, gi) - np.einsum( 'jab,jba->j', t2i, gi) emp2 += tmp_eij.sum() if with_eij: eij[i] = tmp_eij return emp2.real, eij.real
def _gamma1_intermediates(mp, mo_coeff, mo_energy, nocc, t2=None): nmo = mo_coeff.shape[1] nvir = nmo - nocc eia = mo_energy[:nocc, None] - mo_energy[None, nocc:] if (t2 is None): t2 = [] for istep, qov in enumerate(mp.loop_ao2mo(mo_coeff, nocc)): if (istep == 0): dtype = qov.dtype dm1occ = np.zeros((nocc, nocc), dtype=dtype) dm1vir = np.zeros((nvir, nvir), dtype=dtype) for i in range(nocc): buf = np.dot(qov[:, i * nvir:(i + 1) * nvir].T, qov).reshape(nvir, nocc, nvir) gi = np.array(buf, copy=False) gi = gi.reshape(nvir, nocc, nvir).transpose(1, 0, 2) t2i = gi.conj() / lib.direct_sum('jb+a->jba', eia, eia[i]) t2.append(t2i) l2i = t2i.conj() dm1vir += np.einsum('jca,jcb->ba', l2i, t2i) * 2 \ - np.einsum('jca,jbc->ba', l2i, t2i) dm1occ += np.einsum('iab,jab->ij', l2i, t2i) * 2 \ - np.einsum('iab,jba->ij', l2i, t2i) else: dtype = t2[0].dtype dm1occ = np.zeros((nocc, nocc), dtype=dtype) dm1vir = np.zeros((nvir, nvir), dtype=dtype) for i in range(nocc): t2i = t2[i] l2i = t2i.conj() dm1vir += np.einsum('jca,jcb->ba', l2i, t2i) * 2 \ - np.einsum('jca,jbc->ba', l2i, t2i) dm1occ += np.einsum('iab,jab->ij', l2i, t2i) * 2 \ - np.einsum('iab,jba->ij', l2i, t2i) return -dm1occ, dm1vir
def kernel(mp, mo_energy=None, mo_coeff=None, eris=None, with_t2=WITH_T2, verbose=None): if mo_energy is not None or mo_coeff is not None: # For backward compatibility. In pyscf-1.4 or earlier, mp.frozen is # not supported when mo_energy or mo_coeff is given. assert (mp.frozen == 0 or mp.frozen is None) if eris is None: eris = mp.ao2mo(mo_coeff) if mo_energy is None: mo_energy = eris.mo_energy nocc = mp.nocc nvir = mp.nmo - nocc #moidx = mp.get_frozen_mask() eia = mo_energy[:nocc, None] - mo_energy[None, nocc:] if with_t2: t2 = numpy.empty((nocc, nocc, nvir, nvir), dtype=eris.oovv.dtype) else: t2 = None emp2 = 0 for i in range(nocc): gi = numpy.asarray(eris.oovv[i]).reshape(nocc, nvir, nvir) t2i = gi.conj() / lib.direct_sum('jb+a->jba', eia, eia[i]) emp2 += numpy.einsum('jab,jab', t2i, gi) * .25 if with_t2: t2[i] = t2i return emp2.real, t2
def solve_mo1_fc(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mo_energy = sscobj._scf.mo_energy mo_coeff = sscobj._scf.mo_coeff mo_occ = sscobj._scf.mo_occ nset = len(h1) eai = 1. / lib.direct_sum('a-i->ai', mo_energy[mo_occ == 0], mo_energy[mo_occ > 0]) mo1 = numpy.asarray(h1) * -eai if not sscobj.cphf: return mo1 orbo = mo_coeff[:, mo_occ > 0] orbv = mo_coeff[:, mo_occ == 0] nocc = orbo.shape[1] nvir = orbv.shape[1] nmo = nocc + nvir vresp = _gen_rhf_response(mf, singlet=False, hermi=1) mo_v_o = numpy.asarray(numpy.hstack((orbv, orbo)), order='F') def vind(mo1): dm1 = _dm1_mo2ao(mo1.reshape(nset, nvir, nocc), orbv, orbo * 2) # *2 for double occupancy dm1 = dm1 + dm1.transpose(0, 2, 1) v1 = vresp(dm1) v1 = _ao2mo.nr_e2(v1, mo_v_o, (0, nvir, nvir, nmo)).reshape(nset, nvir, nocc) v1 *= eai return v1.ravel() mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log) log.timer('solving FC CPHF eqn', *cput1) return mo1.reshape(nset, nvir, nocc)
def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, with_cphf=None): cput1 = (time.clock(), time.time()) log = logger.Logger(self.stdout, self.verbose) if mo_energy is None: mo_energy = self._scf.mo_energy if mo_occ is None: mo_occ = self._scf.mo_occ if with_cphf is None: with_cphf = self.cphf mol = self.mol mo_coeff = self._scf.mo_coeff if h1 is None: atmlst = sorted(set([j for i,j in self.nuc_pair])) h1 = numpy.asarray(make_h1_pso(mol, mo_coeff, mo_occ, atmlst)) if with_cphf: vind = self.gen_vind(self._scf, mo_coeff, mo_occ) mo1, mo_e1 = cphf.solve(vind, mo_energy, mo_occ, h1, None, self.max_cycle_cphf, self.conv_tol, verbose=log) else: e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ>0], mo_energy[mo_occ==0]) mo1 = h1 * (1 / e_ai) mo_e1 = None logger.timer(self, 'solving mo1 eqn', *cput1) return mo1, mo_e1
def update_amps(mycc, t1, t2, eris): """ Update GCCD amplitudes. """ time0 = logger.process_clock(), logger.perf_counter() log = logger.Logger(mycc.stdout, mycc.verbose) t1T = t1.T t2T = np.asarray(t2.transpose(2, 3, 0, 1), order='C') nvir_seg, nvir, nocc = t2T.shape[:3] t2 = None ntasks = mpi.pool.size vlocs = [_task_location(nvir, task_id) for task_id in range(ntasks)] vloc0, vloc1 = vlocs[rank] log.debug2('vlocs %s', vlocs) assert vloc1 - vloc0 == nvir_seg fock = eris.fock fvo = fock[nocc:, :nocc] mo_e_o = eris.mo_energy[:nocc] mo_e_v = eris.mo_energy[nocc:] + mycc.level_shift tauT_tilde = make_tauT(t1T, t2T, fac=0.5, vlocs=vlocs) Fvv = cc_Fvv(t1T, t2T, eris, tauT_tilde=tauT_tilde, vlocs=vlocs) Foo = cc_Foo(t1T, t2T, eris, tauT_tilde=tauT_tilde, vlocs=vlocs) tauT_tilde = None Fov = cc_Fov(t1T, eris, vlocs=vlocs) # Move energy terms to the other side Fvv[np.diag_indices(nvir)] -= mo_e_v Foo[np.diag_indices(nocc)] -= mo_e_o # T1 equation t1Tnew = np.zeros_like(t1T) #t1Tnew = np.dot(Fvv, t1T) #t1Tnew -= np.dot(t1T, Foo) tmp = einsum('aeim, me -> ai', t2T, Fov) #tmp -= np.einsum('fn, naif -> ai', t1T, eris.oxov, optimize=True) tmp = mpi.allgather(tmp) #tmp2 = einsum('eamn, mnie -> ai', t2T, eris.ooox) tmp2 = einsum('eamn, einm -> ai', t2T, eris.xooo) #tmp2 += einsum('efim, mafe -> ai', t2T, eris.ovvx) tmp2 += einsum('efim, efam -> ai', t2T, eris.xvvo) tmp2 *= 0.5 tmp2 = mpi.allreduce_inplace(tmp2) tmp += tmp2 tmp2 = None #t1Tnew += tmp #t1Tnew += fvo # T2 equation Ftmp = Fvv #- 0.5 * np.dot(t1T, Fov) t2Tnew = einsum('aeij, be -> abij', t2T, Ftmp) t2T_tmp = mpi.alltoall_new([t2Tnew[:, p0:p1] for p0, p1 in vlocs], split_recvbuf=True) for task_id, (p0, p1) in enumerate(vlocs): tmp = t2T_tmp[task_id].reshape(p1 - p0, nvir_seg, nocc, nocc) t2Tnew[:, p0:p1] -= tmp.transpose(1, 0, 2, 3) tmp = None t2T_tmp = None Ftmp = Foo #+ 0.5 * np.dot(Fov, t1T) tmp = einsum('abim, mj -> abij', t2T, Ftmp) t2Tnew -= tmp t2Tnew += tmp.transpose(0, 1, 3, 2) tmp = None t2Tnew += np.asarray(eris.xvoo) tauT = make_tauT(t1T, t2T, vlocs=vlocs) Woooo = cc_Woooo(t1T, t2T, eris, tauT=tauT, vlocs=vlocs) Woooo *= 0.5 t2Tnew += einsum('abmn, mnij -> abij', tauT, Woooo) Woooo = None Wvvvv = cc_Wvvvv(t1T, t2T, eris, tauT=tauT, vlocs=vlocs) for task_id, tauT_tmp, p0, p1 in _rotate_vir_block(tauT, vlocs=vlocs): tmp = einsum('abef, efij -> abij', Wvvvv[:, :, p0:p1], tauT_tmp) tmp *= 0.5 t2Tnew += tmp tmp = tauT_tmp = None Wvvvv = None tauT = None #tmp = einsum('mbje, ei -> bmij', eris.oxov, t1T) # [b]mij #tmp = mpi.allgather(tmp) # bmij #tmp = einsum('am, bmij -> abij', t1T[vloc0:vloc1], tmp) # [a]bij tmp = 0.0 Wvovo = cc_Wovvo(t1T, t2T, eris, vlocs=vlocs).transpose(2, 0, 1, 3) for task_id, w_tmp, p0, p1 in _rotate_vir_block(Wvovo, vlocs=vlocs): tmp += einsum('aeim, embj -> abij', t2T[:, p0:p1], w_tmp) w_tmp = None Wvovo = None tmp = tmp - tmp.transpose(0, 1, 3, 2) t2Tnew += tmp tmpT = mpi.alltoall_new([tmp[:, p0:p1] for p0, p1 in vlocs], split_recvbuf=True) for task_id, (p0, p1) in enumerate(vlocs): tmp = tmpT[task_id].reshape(p1 - p0, nvir_seg, nocc, nocc) t2Tnew[:, p0:p1] -= tmp.transpose(1, 0, 2, 3) tmp = None tmpT = None #tmp = einsum('ei, jeba -> abij', t1T, eris.ovvx) #t2Tnew += tmp #t2Tnew -= tmp.transpose(0, 1, 3, 2) #tmp = einsum('am, ijmb -> baij', t1T, eris.ooox.conj()) #t2Tnew += tmp #tmpT = mpi.alltoall([tmp[:, p0:p1] for p0, p1 in vlocs], # split_recvbuf=True) #for task_id, (p0, p1) in enumerate(vlocs): # tmp = tmpT[task_id].reshape(p1-p0, nvir_seg, nocc, nocc) # t2Tnew[:, p0:p1] -= tmp.transpose(1, 0, 2, 3) # tmp = None #tmpT = None eia = mo_e_o[:, None] - mo_e_v #t1Tnew /= eia.T for i in range(vloc0, vloc1): t2Tnew[i - vloc0] /= lib.direct_sum('i + jb -> bij', eia[:, i], eia) time0 = log.timer_debug1('update t1 t2', *time0) return t1Tnew.T, t2Tnew.transpose(2, 3, 0, 1)
def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None, mf_grad=None, verbose=logger.INFO): if t1 is None: t1 = mycc.t1 if t2 is None: t2 = mycc.t2 if l1 is None: l1 = mycc.l1 if l2 is None: l2 = mycc.l2 if eris is None: eris = ccsd._ERIS(mycc) if mf_grad is None: mf_grad = rhf_grad.Gradients(mycc._scf) log = logger.Logger(mycc.stdout, mycc.verbose) time0 = time.clock(), time.time() mol = mycc.mol moidx = numpy.ones(mycc.mo_coeff.shape[1], dtype=numpy.bool) if isinstance(mycc.frozen, (int, numpy.integer)): raise NotImplementedError('frozen orbital ccsd_grad') moidx[:mycc.frozen] = False else: moidx[mycc.frozen] = False mo_coeff = mycc.mo_coeff[:, moidx] #FIXME: ensure mycc.mo_coeff is canonical orbital mo_energy = eris.fock.diagonal() nocc, nvir = t1.shape nao, nmo = mo_coeff.shape nao_pair = nao * (nao + 1) // 2 log.debug('Build ccsd rdm1 intermediates') d1 = ccsd_rdm.gamma1_intermediates(mycc, t1, t2, l1, l2) doo, dov, dvo, dvv = d1 time1 = log.timer('rdm1 intermediates', *time0) log.debug('Build ccsd rdm2 intermediates') _d2tmpfile = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR) fd2intermediate = h5py.File(_d2tmpfile.name, 'w') d2 = ccsd_rdm.gamma2_outcore(mycc, t1, t2, l1, l2, fd2intermediate) time1 = log.timer('rdm2 intermediates', *time1) log.debug('Build ccsd response_rdm1') Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc, t1, t2, l1, l2, eris, d1, d2) time1 = log.timer('response_rdm1 intermediates', *time1) dm1mo = response_dm1(mycc, t1, t2, l1, l2, eris, (Ioo, Ivv, Ivo, Xvo)) dm1mo[:nocc, :nocc] = doo + doo.T dm1mo[nocc:, nocc:] = dvv + dvv.T dm1ao = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) im1 = numpy.zeros_like(dm1mo) im1[:nocc, :nocc] = Ioo im1[nocc:, nocc:] = Ivv im1[nocc:, :nocc] = Ivo im1[:nocc, nocc:] = Ivo.T im1 = reduce(numpy.dot, (mo_coeff, im1, mo_coeff.T)) time1 = log.timer('response_rdm1', *time1) log.debug('symmetrized rdm2 and MO->AO transformation') _dm2file = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR) # Basically, 4 times of dm2 is computed. *2 in _rdm2_mo2ao, *2 in _load_block_tril fdm2 = h5py.File(_dm2file.name, 'w') dm1_with_hf = dm1mo.copy() for i in range( nocc ): # HF 2pdm ~ 4(ij)(kl)-2(il)(jk), diagonal+1 because of 4*dm2 dm1_with_hf[i, i] += 1 _rdm2_mo2ao(mycc, d2, dm1_with_hf, mo_coeff, fdm2) time1 = log.timer('MO->AO transformation', *time1) for key in fd2intermediate.keys(): del (fd2intermediate[key]) fd2intermediate.close() #TODO: pass hf_grad object to compute h1 and s1 log.debug('h1 and JK1') h1 = mf_grad.get_hcore(mol) s1 = mf_grad.get_ovlp(mol) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[:nocc].reshape(-1, 1) zeta = reduce(numpy.dot, (mo_coeff, zeta * dm1mo, mo_coeff.T)) p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T) vhf4sij = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1ao + dm1ao.T), p1)) time1 = log.timer('h1 and JK1', *time1) # Hartree-Fock part contribution hf_dm1 = mycc._scf.make_rdm1(mycc._scf.mo_coeff, mycc._scf.mo_occ) dm1ao += hf_dm1 zeta += mf_grad.make_rdm1e(mycc._scf.mo_energy, mycc._scf.mo_coeff, mycc._scf.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() max_memory = mycc.max_memory - lib.current_memory()[0] blksize = max(1, int(max_memory * 1e6 / 8 / (nao**3 * 2.5))) ioblksize = fdm2['dm2/0'].shape[-1] de = numpy.zeros((len(atmlst), 3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # s[1] dot I, note matrix im1 is not hermitian de[k] = (numpy.einsum('xij,ij->x', s1[:, p0:p1], im1[p0:p1]) + numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1])) # h[1] \dot DM, *2 for +c.c., contribute to f1 h1ao = mf_grad._grad_rinv(mol, ia) h1ao[:, p0:p1] += h1[:, p0:p1] de[k] += (numpy.einsum('xij,ij->x', h1ao, dm1ao) + numpy.einsum('xji,ij->x', h1ao, dm1ao)) # -s[1]*e \dot DM, contribute to f1 de[k] -= (numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) + numpy.einsum('xji,ij->x', s1[:, p0:p1], zeta[:, p0:p1])) # -vhf[s_ij[1]], contribute to f1, *2 for s1+s1.T de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], vhf4sij[p0:p1]) * 2 # 2e AO integrals dot 2pdm ip0 = p0 for b0, b1, nf in shell_prange(mol, shl0, shl1, blksize): eri1 = mol.intor('cint2e_ip1_sph', comp=3, aosym='s2kl', shls_slice=(b0, b1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas)) eri1 = eri1.reshape(3, nf, nao, -1) dm2buf = numpy.empty((nf, nao, nao_pair)) for ic, (i0, i1) in enumerate(prange(0, nao_pair, ioblksize)): _load_block_tril(fdm2['dm2/%d' % ic], ip0, ip0 + nf, dm2buf[:, :, i0:i1]) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 eri1 = dm2buf = None ip0 += nf log.debug('grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer('grad of atom %d' % ia, *time1) log.note('CCSD gradinets') log.note('==============') log.note(' x y z') for k, ia in enumerate(atmlst): log.note('%d %s %15.9f %15.9f %15.9f', ia, mol.atom_symbol(ia), de[k, 0], de[k, 1], de[k, 2]) log.timer('CCSD gradients', *time0) for key in fdm2.keys(): del (fdm2[key]) fdm2.close() _d2tmpfile = _dm2file = None return de
eri_mo = ao2mo.kernel(mf._eri, mf.mo_coeff, compact=False) nmo = mf.mo_coeff.shape[1] eri_mo = eri_mo.reshape(nmo, nmo, nmo, nmo) dm1 = make_rdm1(mcc, t1, t2, l1, l2, eris=eris) dm2 = make_rdm2(mcc, t1, t2, l1, l2, eris=eris) h1 = reduce(numpy.dot, (mf.mo_coeff.T, mf.get_hcore(), mf.mo_coeff)) e3 = (numpy.einsum('ij,ij->', h1, dm1) + numpy.einsum('ijkl,ijkl->', eri_mo, dm2) * .5 + mf.mol.energy_nuc()) #print e3ref, e3-(mf.e_tot+ecc) nocc, nvir = t1.shape eris_ovvv = _cp(eris.ovvv) eris_ovvv = lib.unpack_tril(eris_ovvv.reshape(nocc * nvir, -1)) eris_ovvv = eris_ovvv.reshape(nocc, nvir, nvir, nvir) mo_e = mcc._scf.mo_energy eia = lib.direct_sum('i-a->ia', mo_e[:nocc], mo_e[nocc:]) d3 = lib.direct_sum('ia,jb,kc->ijkabc', eia, eia, eia) eris_ovoo = eris.ovoo w = (numpy.einsum('iabf,kjcf->ijkabc', eris_ovvv, t2) - numpy.einsum('iajm,mkbc->ijkabc', eris_ovoo, t2)) / d3 v = numpy.einsum('iajb,kc->ijkabc', eris.ovov, t1) / d3 * .5 w = ccsd_t.p6_(w) v = ccsd_t.p6_(v) rw = ccsd_t.r6_(w) rwv = ccsd_t.r6_(w * 2 + v * 0) dovov = numpy.einsum('kc,ijkabc->iajb', t1, rw) dooov = -numpy.einsum('mkbc,ijkabc->jmia', t2, rwv) dovvv = numpy.einsum('kjcf,ijkabc->iabf', t2, rwv) e3a = numpy.einsum('iajb,iajb', eris.ovov, dovov) e3a += numpy.einsum('iajm,jmia', eris.ovoo, dooov) e3a += numpy.einsum('iabf,iabf', eris_ovvv, dovvv)
def kernel(mcc, eris, t1=None, t2=None): if t1 is None or t2 is None: t1, t2 = mcc.t1, mcc.t2 def p6(t): return (t + t.transpose(1,2,0,4,5,3) + t.transpose(2,0,1,5,3,4) + t.transpose(0,2,1,3,5,4) + t.transpose(2,1,0,5,4,3) + t.transpose(1,0,2,4,3,5)) def r6(w): return (w + w.transpose(2,0,1,3,4,5) + w.transpose(1,2,0,3,4,5) - w.transpose(2,1,0,3,4,5) - w.transpose(0,2,1,3,4,5) - w.transpose(1,0,2,3,4,5)) t1a, t1b = t1 t2aa, t2ab, t2bb = t2 nocca, noccb = t2ab.shape[:2] mo_ea, mo_eb = eris.mo_energy eia = mo_ea[:nocca,None] - mo_ea[nocca:] eIA = mo_eb[:noccb,None] - mo_eb[noccb:] fvo = eris.focka[nocca:,:nocca] fVO = eris.fockb[noccb:,:noccb] # aaa d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eia, eia) w = numpy.einsum('ijae,kceb->ijkabc', t2aa, numpy.asarray(eris.get_ovvv()).conj()) w-= numpy.einsum('mkbc,iajm->ijkabc', t2aa, numpy.asarray(eris.ovoo.conj())) r = r6(w) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.ovov).conj(), t1a) v+= numpy.einsum('jkbc,ai->ijkabc', t2aa, fvo) * .5 wvd = p6(w + v) / d3 et = numpy.einsum('ijkabc,ijkabc', wvd.conj(), r) # bbb d3 = lib.direct_sum('ia+jb+kc->ijkabc', eIA, eIA, eIA) w = numpy.einsum('ijae,kceb->ijkabc', t2bb, numpy.asarray(eris.get_OVVV()).conj()) w-= numpy.einsum('imab,kcjm->ijkabc', t2bb, numpy.asarray(eris.OVOO.conj())) r = r6(w) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.OVOV).conj(), t1b) v+= numpy.einsum('jkbc,ai->ijkabc', t2bb, fVO) * .5 wvd = p6(w + v) / d3 et += numpy.einsum('ijkabc,ijkabc', wvd.conj(), r) # baa w = numpy.einsum('jIeA,kceb->IjkAbc', t2ab, numpy.asarray(eris.get_ovvv()).conj()) * 2 w += numpy.einsum('jIbE,kcEA->IjkAbc', t2ab, numpy.asarray(eris.get_ovVV()).conj()) * 2 w += numpy.einsum('jkbe,IAec->IjkAbc', t2aa, numpy.asarray(eris.get_OVvv()).conj()) w -= numpy.einsum('mIbA,kcjm->IjkAbc', t2ab, numpy.asarray(eris.ovoo).conj()) * 2 w -= numpy.einsum('jMbA,kcIM->IjkAbc', t2ab, numpy.asarray(eris.ovOO).conj()) * 2 w -= numpy.einsum('jmbc,IAkm->IjkAbc', t2aa, numpy.asarray(eris.OVoo).conj()) r = w - w.transpose(0,2,1,3,4,5) r = r + r.transpose(0,2,1,3,5,4) v = numpy.einsum('jbkc,IA->IjkAbc', numpy.asarray(eris.ovov).conj(), t1b) v += numpy.einsum('kcIA,jb->IjkAbc', numpy.asarray(eris.ovOV).conj(), t1a) v += numpy.einsum('kcIA,jb->IjkAbc', numpy.asarray(eris.ovOV).conj(), t1a) v += numpy.einsum('jkbc,AI->IjkAbc', t2aa, fVO) * .5 v += numpy.einsum('kIcA,bj->IjkAbc', t2ab, fvo) * 2 w += v d3 = lib.direct_sum('ia+jb+kc->ijkabc', eIA, eia, eia) r /= d3 et += numpy.einsum('ijkabc,ijkabc', w.conj(), r) # bba w = numpy.einsum('ijae,kceb->ijkabc', t2ab, numpy.asarray(eris.get_OVVV()).conj()) * 2 w += numpy.einsum('ijeb,kcea->ijkabc', t2ab, numpy.asarray(eris.get_OVvv()).conj()) * 2 w += numpy.einsum('jkbe,iaec->ijkabc', t2bb, numpy.asarray(eris.get_ovVV()).conj()) w -= numpy.einsum('imab,kcjm->ijkabc', t2ab, numpy.asarray(eris.OVOO).conj()) * 2 w -= numpy.einsum('mjab,kcim->ijkabc', t2ab, numpy.asarray(eris.OVoo).conj()) * 2 w -= numpy.einsum('jmbc,iakm->ijkabc', t2bb, numpy.asarray(eris.ovOO).conj()) r = w - w.transpose(0,2,1,3,4,5) r = r + r.transpose(0,2,1,3,5,4) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.OVOV).conj(), t1a) v += numpy.einsum('iakc,jb->ijkabc', numpy.asarray(eris.ovOV).conj(), t1b) v += numpy.einsum('iakc,jb->ijkabc', numpy.asarray(eris.ovOV).conj(), t1b) v += numpy.einsum('JKBC,ai->iJKaBC', t2bb, fvo) * .5 v += numpy.einsum('iKaC,BJ->iJKaBC', t2ab, fVO) * 2 w += v d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eIA, eIA) r /= d3 et += numpy.einsum('ijkabc,ijkabc', w.conj(), r) et *= .25 return et
def update_amps(cc, t1, t2, eris): time0 = time.clock(), time.time() log = logger.Logger(cc.stdout, cc.verbose) 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) tau = imd.make_tau(t2,t1,t1) Fvv = imd.cc_Fvv(t1,t2,eris) Foo = imd.cc_Foo(t1,t2,eris) Fov = imd.cc_Fov(t1,t2,eris) Woooo = imd.cc_Woooo(t1,t2,eris) Wvvvv = imd.cc_Wvvvv(t1,t2,eris) Wovvo = imd.cc_Wovvo(t1,t2,eris) # Move energy terms to the other side Fvv -= np.diag(np.diag(fvv)) Foo -= np.diag(np.diag(foo)) # T1 equation t1new = np.array(fov).conj() t1new += einsum('ie,ae->ia',t1,Fvv) t1new += -einsum('ma,mi->ia',t1,Foo) t1new += einsum('imae,me->ia',t2,Fov) t1new += -einsum('nf,naif->ia',t1,eris.ovov) t1new += -0.5*einsum('imef,maef->ia',t2,eris.ovvv) t1new += -0.5*einsum('mnae,mnie->ia',t2,eris.ooov) # T2 equation t2new = np.array(eris.oovv).conj() Ftmp = Fvv - 0.5*einsum('mb,me->be',t1,Fov) tmp = einsum('ijae,be->ijab',t2,Ftmp) t2new += (tmp - tmp.transpose(0,1,3,2)) Ftmp = Foo + 0.5*einsum('je,me->mj',t1,Fov) tmp = einsum('imab,mj->ijab',t2,Ftmp) t2new -= (tmp - tmp.transpose(1,0,2,3)) t2new += 0.5*einsum('mnab,mnij->ijab',tau,Woooo) for a in range(nvir): t2new[:,:,a,:] += 0.5*einsum('ijef,bef->ijb',tau,Wvvvv[a]) tmp = einsum('imae,mbej->ijab',t2,Wovvo) tmp -= -einsum('ie,ma,mbje->ijab',t1,t1,eris.ovov) t2new += ( tmp - tmp.transpose(0,1,3,2) - tmp.transpose(1,0,2,3) + tmp.transpose(1,0,3,2) ) tmp = einsum('ie,jeba->ijab',t1,np.array(eris.ovvv).conj()) t2new += (tmp - tmp.transpose(1,0,2,3)) tmp = einsum('ma,mbij->ijab',t1,eris.ovoo) t2new -= (tmp - tmp.transpose(0,1,3,2)) t1new /= eia t2new /= eijab time0 = log.timer_debug1('update t1 t2', *time0) return t1new, t2new
def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None, mf_grad=None, d1=None, d2=None, verbose=logger.INFO): if eris is not None: if abs(eris.fock - numpy.diag(eris.fock.diagonal())).max() > 1e-3: raise RuntimeError( 'CCSD gradients does not support NHF (non-canonical HF)') if t1 is None: t1 = mycc.t1 if t2 is None: t2 = mycc.t2 if l1 is None: l1 = mycc.l1 if l2 is None: l2 = mycc.l2 if mf_grad is None: mf_grad = mycc._scf.nuc_grad_method() log = logger.new_logger(mycc, verbose) time0 = time.clock(), time.time() log.debug('Build ccsd rdm1 intermediates') if d1 is None: d1 = ccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2) doo, dov, dvo, dvv = d1 time1 = log.timer_debug1('rdm1 intermediates', *time0) log.debug('Build ccsd rdm2 intermediates') fdm2 = lib.H5TmpFile() if d2 is None: d2 = ccsd_rdm._gamma2_outcore(mycc, t1, t2, l1, l2, fdm2, True) time1 = log.timer_debug1('rdm2 intermediates', *time1) mol = mycc.mol mo_coeff = mycc.mo_coeff mo_energy = mycc._scf.mo_energy nao, nmo = mo_coeff.shape nocc = numpy.count_nonzero(mycc.mo_occ > 0) with_frozen = not (mycc.frozen is None or mycc.frozen is 0) OA, VA, OF, VF = _index_frozen_active(mycc.get_frozen_mask(), mycc.mo_occ) log.debug('symmetrized rdm2 and MO->AO transformation') # Roughly, dm2*2 is computed in _rdm2_mo2ao mo_active = mo_coeff[:, numpy.hstack((OA, VA))] _rdm2_mo2ao(mycc, d2, mo_active, fdm2) # transform the active orbitals time1 = log.timer_debug1('MO->AO transformation', *time1) hf_dm1 = mycc._scf.make_rdm1(mycc.mo_coeff, mycc.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() diagidx = numpy.arange(nao) diagidx = diagidx * (diagidx + 1) // 2 + diagidx de = numpy.zeros((len(atmlst), 3)) Imat = numpy.zeros((nao, nao)) vhf1 = fdm2.create_dataset('vhf1', (len(atmlst), 3, nao, nao), 'f8') # 2e AO integrals dot 2pdm max_memory = max(0, mycc.max_memory - lib.current_memory()[0]) blksize = max(1, int(max_memory * .9e6 / 8 / (nao**3 * 2.5))) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] ip1 = p0 vhf = numpy.zeros((3, nao, nao)) for b0, b1, nf in _shell_prange(mol, shl0, shl1, blksize): ip0, ip1 = ip1, ip1 + nf dm2buf = _load_block_tril(fdm2['dm2'], ip0, ip1, nao) dm2buf[:, :, diagidx] *= .5 shls_slice = (b0, b1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas) eri0 = mol.intor('int2e', aosym='s2kl', shls_slice=shls_slice) Imat += lib.einsum('ipx,iqx->pq', eri0.reshape(nf, nao, -1), dm2buf) eri0 = None eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=shls_slice).reshape(3, nf, nao, -1) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 dm2buf = None # HF part for i in range(3): eri1tmp = lib.unpack_tril(eri1[i].reshape(nf * nao, -1)) eri1tmp = eri1tmp.reshape(nf, nao, nao, nao) vhf[i] += numpy.einsum('ijkl,ij->kl', eri1tmp, hf_dm1[ip0:ip1]) vhf[i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1[ip0:ip1]) * .5 vhf[i, ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1) vhf[i, ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1) * .5 eri1 = eri1tmp = None vhf1[k] = vhf log.debug('2e-part grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer_debug1('2e-part grad of atom %d' % ia, *time1) Imat = reduce(numpy.dot, (mo_coeff.T, Imat, mycc._scf.get_ovlp(), mo_coeff)) * -1 dm1mo = numpy.zeros((nmo, nmo)) if with_frozen: dco = Imat[OF[:, None], OA] / (mo_energy[OF, None] - mo_energy[OA]) dfv = Imat[VF[:, None], VA] / (mo_energy[VF, None] - mo_energy[VA]) dm1mo[OA[:, None], OA] = doo + doo.T dm1mo[OF[:, None], OA] = dco dm1mo[OA[:, None], OF] = dco.T dm1mo[VA[:, None], VA] = dvv + dvv.T dm1mo[VF[:, None], VA] = dfv dm1mo[VA[:, None], VF] = dfv.T else: dm1mo[:nocc, :nocc] = doo + doo.T dm1mo[nocc:, nocc:] = dvv + dvv.T dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) vhf = mycc._scf.get_veff(mycc.mol, dm1) * 2 Xvo = reduce(numpy.dot, (mo_coeff[:, nocc:].T, vhf, mo_coeff[:, :nocc])) Xvo += Imat[:nocc, nocc:].T - Imat[nocc:, :nocc] dm1mo += _response_dm1(mycc, Xvo, eris) time1 = log.timer_debug1('response_rdm1 intermediates', *time1) Imat[nocc:, :nocc] = Imat[:nocc, nocc:].T im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T)) time1 = log.timer_debug1('response_rdm1', *time1) log.debug('h1 and JK1') hcore_deriv = mf_grad.hcore_generator(mol) s1 = mf_grad.get_ovlp(mol) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[:nocc].reshape(-1, 1) zeta = reduce(numpy.dot, (mo_coeff, zeta * dm1mo, mo_coeff.T)) dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T) vhf_s1occ = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1 + dm1.T), p1)) time1 = log.timer_debug1('h1 and JK1', *time1) # Hartree-Fock part contribution dm1p = hf_dm1 + dm1 * 2 dm1 += hf_dm1 zeta += mf_grad.make_rdm1e(mo_energy, mo_coeff, mycc.mo_occ) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # s[1] dot I, note matrix im1 is not hermitian de[k] += numpy.einsum('xij,ij->x', s1[:, p0:p1], im1[p0:p1]) de[k] += numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1]) # h[1] \dot DM, contribute to f1 h1ao = hcore_deriv(ia) de[k] += numpy.einsum('xij,ji->x', h1ao, dm1) # -s[1]*e \dot DM, contribute to f1 de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) de[k] -= numpy.einsum('xji,ij->x', s1[:, p0:p1], zeta[:, p0:p1]) # -vhf[s_ij[1]], contribute to f1, *2 for s1+s1.T de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], vhf_s1occ[p0:p1]) * 2 de[k] -= numpy.einsum('xij,ij->x', vhf1[k], dm1p) de += mf_grad.grad_nuc(mol, atmlst) log.timer('%s gradients' % mycc.__class__.__name__, *time0) return de
def update_amps(cc, t1, t2, eris): # Ref: Hirata et al., J. Chem. Phys. 120, 2581 (2004) Eqs.(35)-(36) nocc, nvir = t1.shape fock = eris.fock fov = fock[:nocc, nocc:].copy() foo = fock[:nocc, :nocc].copy() fvv = fock[nocc:, nocc:].copy() Foo = imd.cc_Foo(t1, t2, eris) Fvv = imd.cc_Fvv(t1, t2, eris) Fov = imd.cc_Fov(t1, t2, eris) # Move energy terms to the other side Foo -= np.diag(np.diag(foo)) Fvv -= np.diag(np.diag(fvv)) # T1 equation t1new = np.asarray(fov).conj().copy() t1new += -2 * einsum('kc,ka,ic->ia', fov, t1, t1) t1new += einsum('ac,ic->ia', Fvv, t1) t1new += -einsum('ki,ka->ia', Foo, t1) t1new += 2 * einsum('kc,kica->ia', Fov, t2) t1new += -einsum('kc,ikca->ia', Fov, t2) t1new += einsum('kc,ic,ka->ia', Fov, t1, t1) t1new += 2 * einsum('kcai,kc->ia', eris.ovvo, t1) t1new += -einsum('kiac,kc->ia', eris.oovv, t1) eris_ovvv = np.asarray(eris.ovvv) t1new += 2 * einsum('kdac,ikcd->ia', eris_ovvv, t2) t1new += -einsum('kcad,ikcd->ia', eris_ovvv, t2) t1new += 2 * einsum('kdac,kd,ic->ia', eris_ovvv, t1, t1) t1new += -einsum('kcad,kd,ic->ia', eris_ovvv, t1, t1) t1new += -2 * einsum('kilc,klac->ia', eris.ooov, t2) t1new += einsum('likc,klac->ia', eris.ooov, t2) t1new += -2 * einsum('kilc,lc,ka->ia', eris.ooov, t1, t1) t1new += einsum('likc,lc,ka->ia', eris.ooov, t1, t1) # T2 equation t2new = np.asarray(eris.ovov).conj().transpose(0, 2, 1, 3).copy() if cc.cc2: Woooo2 = np.asarray(eris.oooo).transpose(0, 2, 1, 3).copy() Woooo2 += einsum('kilc,jc->klij', eris.ooov, t1) Woooo2 += einsum('ljkc,ic->klij', eris.ooov, t1) Woooo2 += einsum('kcld,ic,jd->klij', eris.ovov, t1, t1) t2new += einsum('klij,ka,lb->ijab', Woooo2, t1, t1) Wvvvv = einsum('kcbd,ka->abcd', eris_ovvv, -t1) Wvvvv = Wvvvv + Wvvvv.transpose(1, 0, 3, 2) Wvvvv += np.asarray(eris.vvvv).transpose(0, 2, 1, 3) t2new += einsum('abcd,ic,jd->ijab', Wvvvv, t1, t1) Lvv2 = fvv - einsum('kc,ka->ac', fov, t1) Lvv2 -= np.diag(np.diag(fvv)) tmp = einsum('ac,ijcb->ijab', Lvv2, t2) t2new += (tmp + tmp.transpose(1, 0, 3, 2)) Loo2 = foo + einsum('kc,ic->ki', fov, t1) Loo2 -= np.diag(np.diag(foo)) tmp = einsum('ki,kjab->ijab', Loo2, t2) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) else: Loo = imd.Loo(t1, t2, eris) Lvv = imd.Lvv(t1, t2, eris) Loo -= np.diag(np.diag(foo)) Lvv -= np.diag(np.diag(fvv)) Woooo = imd.cc_Woooo(t1, t2, eris) Wvoov = imd.cc_Wvoov(t1, t2, eris) Wvovo = imd.cc_Wvovo(t1, t2, eris) Wvvvv = imd.cc_Wvvvv(t1, t2, eris) tau = t2 + einsum('ia,jb->ijab', t1, t1) t2new += einsum('klij,klab->ijab', Woooo, tau) t2new += einsum('abcd,ijcd->ijab', Wvvvv, tau) tmp = einsum('ac,ijcb->ijab', Lvv, t2) t2new += (tmp + tmp.transpose(1, 0, 3, 2)) tmp = einsum('ki,kjab->ijab', Loo, t2) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) tmp = 2 * einsum('akic,kjcb->ijab', Wvoov, t2) tmp -= einsum('akci,kjcb->ijab', Wvovo, t2) t2new += (tmp + tmp.transpose(1, 0, 3, 2)) tmp = einsum('akic,kjbc->ijab', Wvoov, t2) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) tmp = einsum('bkci,kjac->ijab', Wvovo, t2) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) tmp2 = einsum('kibc,ka->abic', eris.oovv, -t1) tmp2 += np.asarray(eris.ovvv).conj().transpose(1, 3, 0, 2) tmp = einsum('abic,jc->ijab', tmp2, t1) t2new += (tmp + tmp.transpose(1, 0, 3, 2)) tmp2 = einsum('kcai,jc->akij', eris.ovvo, t1) tmp2 += np.asarray(eris.ooov).transpose(3, 1, 2, 0).conj() tmp = einsum('akij,kb->ijab', tmp2, t1) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) mo_e = eris.fock.diagonal().real eia = mo_e[:nocc, None] - mo_e[None, nocc:] eijab = lib.direct_sum('ia,jb->ijab', eia, eia) t1new /= eia t2new /= eijab return t1new, t2new
def grad_elec(mp_grad, t2, atmlst=None, verbose=logger.INFO): mp = mp_grad.base log = logger.new_logger(mp, verbose) time0 = logger.process_clock(), logger.perf_counter() log.debug('Build mp2 rdm1 intermediates') d1 = mp2._gamma1_intermediates(mp, t2) doo, dvv = d1 time1 = log.timer_debug1('rdm1 intermediates', *time0) # Set nocc, nvir for half-transformation of 2pdm. Frozen orbitals are exculded. # nocc, nvir should be updated to include the frozen orbitals when proceeding # the 1-particle quantities later. mol = mp_grad.mol with_frozen = not ((mp.frozen is None) or (isinstance(mp.frozen, (int, numpy.integer)) and mp.frozen == 0) or (len(mp.frozen) == 0)) OA, VA, OF, VF = _index_frozen_active(mp.get_frozen_mask(), mp.mo_occ) orbo = mp.mo_coeff[:, OA] orbv = mp.mo_coeff[:, VA] nao, nocc = orbo.shape nvir = orbv.shape[1] # Partially transform MP2 density matrix and hold it in memory # The rest transformation are applied during the contraction to ERI integrals part_dm2 = _ao2mo.nr_e2(t2.reshape(nocc**2, nvir**2), numpy.asarray(orbv.T, order='F'), (0, nao, 0, nao), 's1', 's1').reshape(nocc, nocc, nao, nao) part_dm2 = (part_dm2.transpose(0, 2, 3, 1) * 4 - part_dm2.transpose(0, 3, 2, 1) * 2) hf_dm1 = mp._scf.make_rdm1(mp.mo_coeff, mp.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() diagidx = numpy.arange(nao) diagidx = diagidx * (diagidx + 1) // 2 + diagidx de = numpy.zeros((len(atmlst), 3)) Imat = numpy.zeros((nao, nao)) fdm2 = lib.H5TmpFile() vhf1 = fdm2.create_dataset('vhf1', (len(atmlst), 3, nao, nao), 'f8') # 2e AO integrals dot 2pdm max_memory = max(0, mp.max_memory - lib.current_memory()[0]) blksize = max(1, int(max_memory * .9e6 / 8 / (nao**3 * 2.5))) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] ip1 = p0 vhf = numpy.zeros((3, nao, nao)) for b0, b1, nf in _shell_prange(mol, shl0, shl1, blksize): ip0, ip1 = ip1, ip1 + nf dm2buf = lib.einsum('pi,iqrj->pqrj', orbo[ip0:ip1], part_dm2) dm2buf += lib.einsum('qi,iprj->pqrj', orbo, part_dm2[:, ip0:ip1]) dm2buf = lib.einsum('pqrj,sj->pqrs', dm2buf, orbo) dm2buf = dm2buf + dm2buf.transpose(0, 1, 3, 2) dm2buf = lib.pack_tril(dm2buf.reshape(-1, nao, nao)).reshape(nf, nao, -1) dm2buf[:, :, diagidx] *= .5 shls_slice = (b0, b1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas) eri0 = mol.intor('int2e', aosym='s2kl', shls_slice=shls_slice) Imat += lib.einsum('ipx,iqx->pq', eri0.reshape(nf, nao, -1), dm2buf) eri0 = None eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=shls_slice).reshape(3, nf, nao, -1) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 dm2buf = None # HF part for i in range(3): eri1tmp = lib.unpack_tril(eri1[i]).reshape(nf * nao, -1) eri1tmp = eri1tmp.reshape(nf, nao, nao, nao) vhf[i] += numpy.einsum('ijkl,ij->kl', eri1tmp, hf_dm1[ip0:ip1]) vhf[i] -= numpy.einsum('ijkl,il->kj', eri1tmp, hf_dm1[ip0:ip1]) * .5 vhf[i, ip0:ip1] += numpy.einsum('ijkl,kl->ij', eri1tmp, hf_dm1) vhf[i, ip0:ip1] -= numpy.einsum('ijkl,jk->il', eri1tmp, hf_dm1) * .5 eri1 = eri1tmp = None vhf1[k] = vhf log.debug('2e-part grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer_debug1('2e-part grad of atom %d' % ia, *time1) # Recompute nocc, nvir to include the frozen orbitals and make contraction for # the 1-particle quantities, see also the kernel function in ccsd_grad module. mo_coeff = mp.mo_coeff mo_energy = mp._scf.mo_energy nao, nmo = mo_coeff.shape nocc = numpy.count_nonzero(mp.mo_occ > 0) Imat = reduce(numpy.dot, (mo_coeff.T, Imat, mp._scf.get_ovlp(), mo_coeff)) * -1 dm1mo = numpy.zeros((nmo, nmo)) if with_frozen: dco = Imat[OF[:, None], OA] / (mo_energy[OF, None] - mo_energy[OA]) dfv = Imat[VF[:, None], VA] / (mo_energy[VF, None] - mo_energy[VA]) dm1mo[OA[:, None], OA] = doo + doo.T dm1mo[OF[:, None], OA] = dco dm1mo[OA[:, None], OF] = dco.T dm1mo[VA[:, None], VA] = dvv + dvv.T dm1mo[VF[:, None], VA] = dfv dm1mo[VA[:, None], VF] = dfv.T else: dm1mo[:nocc, :nocc] = doo + doo.T dm1mo[nocc:, nocc:] = dvv + dvv.T dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) vhf = mp._scf.get_veff(mp.mol, dm1) * 2 Xvo = reduce(numpy.dot, (mo_coeff[:, nocc:].T, vhf, mo_coeff[:, :nocc])) Xvo += Imat[:nocc, nocc:].T - Imat[nocc:, :nocc] dm1mo += _response_dm1(mp, Xvo) time1 = log.timer_debug1('response_rdm1 intermediates', *time1) Imat[nocc:, :nocc] = Imat[:nocc, nocc:].T im1 = reduce(numpy.dot, (mo_coeff, Imat, mo_coeff.T)) time1 = log.timer_debug1('response_rdm1', *time1) log.debug('h1 and JK1') # Initialize hcore_deriv with the underlying SCF object because some # extensions (e.g. QM/MM, solvent) modifies the SCF object only. mf_grad = mp_grad.base._scf.nuc_grad_method() hcore_deriv = mf_grad.hcore_generator(mol) s1 = mf_grad.get_ovlp(mol) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[:nocc].reshape(-1, 1) zeta = reduce(numpy.dot, (mo_coeff, zeta * dm1mo, mo_coeff.T)) dm1 = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T) vhf_s1occ = reduce(numpy.dot, (p1, mp._scf.get_veff(mol, dm1 + dm1.T), p1)) time1 = log.timer_debug1('h1 and JK1', *time1) # Hartree-Fock part contribution dm1p = hf_dm1 + dm1 * 2 dm1 += hf_dm1 zeta += rhf_grad.make_rdm1e(mo_energy, mo_coeff, mp.mo_occ) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # s[1] dot I, note matrix im1 is not hermitian de[k] += numpy.einsum('xij,ij->x', s1[:, p0:p1], im1[p0:p1]) de[k] += numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1]) # h[1] \dot DM, contribute to f1 h1ao = hcore_deriv(ia) de[k] += numpy.einsum('xij,ji->x', h1ao, dm1) # -s[1]*e \dot DM, contribute to f1 de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) de[k] -= numpy.einsum('xji,ij->x', s1[:, p0:p1], zeta[:, p0:p1]) # -vhf[s_ij[1]], contribute to f1, *2 for s1+s1.T de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], vhf_s1occ[p0:p1]) * 2 de[k] -= numpy.einsum('xij,ij->x', vhf1[k], dm1p) log.timer('%s gradients' % mp.__class__.__name__, *time0) return de
def update_amps(cc, t1, t2, eris, max_memory=2000): time0 = time.clock(), time.time() log = logger.Logger(cc.stdout, cc.verbose) 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 = imd.cc_Foo(t1, t2, eris) Fvv = imd.cc_Fvv(t1, t2, eris) Fov = imd.cc_Fov(t1, t2, eris) Loo = imd.Loo(t1, t2, eris) Lvv = imd.Lvv(t1, t2, eris) Woooo = imd.cc_Woooo(t1, t2, eris) Wvvvv = imd.cc_Wvvvv(t1, t2, eris) Wvoov = imd.cc_Wvoov(t1, t2, eris) Wvovo = imd.cc_Wvovo(t1, t2, eris) # Move energy terms to the other side Foo -= foo Fvv -= fvv Loo -= foo Lvv -= fvv # T1 equation # TODO: Check this conj(). Hirata and Bartlett has # f_{vo}(a,i), which should be equal to f_{ov}^*(i,a) t1new = fov.conj().copy() t1new += -2 * einsum('kc,ka,ic->ia', fov, t1, t1) t1new += einsum('ac,ic->ia', Fvv, t1) t1new += -einsum('ki,ka->ia', Foo, t1) t1new += einsum('kc,kica->ia', Fov, 2 * t2) t1new += einsum('kc,ikca->ia', Fov, -t2) t1new += einsum('kc,ic,ka->ia', Fov, t1, t1) t1new += 2 * einsum('akic,kc->ia', eris.voov, t1) t1new += -einsum('kaic,kc->ia', eris.ovov, t1) t1new += 2 * einsum('akcd,ikcd->ia', eris.vovv, t2) t1new += -einsum('akdc,ikcd->ia', eris.vovv, t2) t1new += 2 * einsum('akcd,ic,kd->ia', eris.vovv, t1, t1) t1new += -einsum('akdc,ic,kd->ia', eris.vovv, t1, t1) t1new += -2 * einsum('klic,klac->ia', eris.ooov, t2) t1new += einsum('lkic,klac->ia', eris.ooov, t2) t1new += -2 * einsum('klic,ka,lc->ia', eris.ooov, t1, t1) t1new += einsum('lkic,ka,lc->ia', eris.ooov, t1, t1) # T2 equation # For conj(), see Hirata and Bartlett, Eq. (36) t2new = np.array(eris.oovv).conj() t2new += einsum('klij,klab->ijab', Woooo, t2) t2new += einsum('klij,ka,lb->ijab', Woooo, t1, t1) for a in range(nvir): Wvvvv_a = np.array(Wvvvv[a]) t2new[:, :, a, :] += einsum('bcd,ijcd->ijb', Wvvvv_a, t2) t2new[:, :, a, :] += einsum('bcd,ic,jd->ijb', Wvvvv_a, t1, t1) tmp = einsum('ac,ijcb->ijab', Lvv, t2) t2new += (tmp + tmp.transpose(1, 0, 3, 2)) tmp = einsum('ki,kjab->ijab', Loo, t2) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) tmp2 = np.array(eris.vovv).transpose(3,2,1,0).conj() \ - einsum('kbic,ka->abic',eris.ovov,t1) tmp = einsum('abic,jc->ijab', tmp2, t1) t2new += (tmp + tmp.transpose(1, 0, 3, 2)) tmp2 = np.array(eris.ooov).transpose(3,2,1,0).conj() \ + einsum('akic,jc->akij',eris.voov,t1) tmp = einsum('akij,kb->ijab', tmp2, t1) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) tmp = 2 * einsum('akic,kjcb->ijab', Wvoov, t2) - einsum( 'akci,kjcb->ijab', Wvovo, t2) t2new += (tmp + tmp.transpose(1, 0, 3, 2)) tmp = einsum('akic,kjbc->ijab', Wvoov, t2) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) tmp = einsum('bkci,kjac->ijab', Wvovo, t2) t2new -= (tmp + tmp.transpose(1, 0, 3, 2)) t1new /= eia t2new /= eijab time0 = log.timer_debug1('update t1 t2', *time0) return t1new, t2new
def solve_mo1(sscobj, h1): cput1 = (time.clock(), time.time()) log = logger.Logger(sscobj.stdout, sscobj.verbose) mol = sscobj.mol mo_energy = sscobj._scf.mo_energy mo_coeff = sscobj._scf.mo_coeff mo_occ = sscobj._scf.mo_occ h1aa, h1ab, h1ba, h1bb = h1 nset = len(h1aa) eai_aa = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[0][mo_occ[0] > 0]) eai_ab = 1. / lib.direct_sum('a-i->ai', mo_energy[0][mo_occ[0] == 0], mo_energy[1][mo_occ[1] > 0]) eai_ba = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[0][mo_occ[0] > 0]) eai_bb = 1. / lib.direct_sum('a-i->ai', mo_energy[1][mo_occ[1] == 0], mo_energy[1][mo_occ[1] > 0]) mo1 = (numpy.asarray(h1aa) * -eai_aa, numpy.asarray(h1ab) * -eai_ab, numpy.asarray(h1ba) * -eai_ba, numpy.asarray(h1bb) * -eai_bb) h1aa = h1ab = h1ba = h1bb = None if not sscobj.cphf: return mo1 orboa = mo_coeff[0][:, mo_occ[0] > 0] orbva = mo_coeff[0][:, mo_occ[0] == 0] orbob = mo_coeff[1][:, mo_occ[1] > 0] orbvb = mo_coeff[1][:, mo_occ[1] == 0] nocca = orboa.shape[1] nvira = orbva.shape[1] noccb = orbob.shape[1] nvirb = orbvb.shape[1] p1 = nvira * nocca p2 = p1 + nvira * noccb p3 = p2 + nvirb * nocca def _split_mo1(mo1): mo1 = mo1.reshape(nset, -1) mo1aa = mo1[:, :p1].reshape(nset, nvira, nocca) mo1ab = mo1[:, p1:p2].reshape(nset, nvira, noccb) mo1ba = mo1[:, p2:p3].reshape(nset, nvirb, nocca) mo1bb = mo1[:, p3:].reshape(nset, nvirb, noccb) return mo1aa, mo1ab, mo1ba, mo1bb mo1 = numpy.hstack((mo1[0].reshape(nset, -1), mo1[1].reshape(nset, -1), mo1[2].reshape(nset, -1), mo1[3].reshape(nset, -1))) vresp = _gen_uhf_response(mf, with_j=False, hermi=0) mo_va_oa = numpy.asarray(numpy.hstack((orbva, orboa)), order='F') mo_va_ob = numpy.asarray(numpy.hstack((orbva, orbob)), order='F') mo_vb_oa = numpy.asarray(numpy.hstack((orbvb, orboa)), order='F') mo_vb_ob = numpy.asarray(numpy.hstack((orbvb, orbob)), order='F') def vind(mo1): mo1aa, mo1ab, mo1ba, mo1bb = _split_mo1(mo1) dm1aa = _dm1_mo2ao(mo1aa, orbva, orboa) dm1ab = _dm1_mo2ao(mo1ab, orbva, orbob) dm1ba = _dm1_mo2ao(mo1ba, orbvb, orboa) dm1bb = _dm1_mo2ao(mo1bb, orbvb, orbob) # imaginary Hermitian dm1 = numpy.vstack([ dm1aa - dm1aa.transpose(0, 2, 1), dm1ab - dm1ba.transpose(0, 2, 1), dm1ba - dm1ab.transpose(0, 2, 1), dm1bb - dm1bb.transpose(0, 2, 1) ]) v1 = vresp(dm1) v1aa = _ao2mo.nr_e2(v1[:nset], mo_va_oa, (0, nvira, nvira, nvira + nocca)) v1ab = _ao2mo.nr_e2(v1[nset * 1:nset * 2], mo_va_ob, (0, nvira, nvira, nvira + noccb)) v1ba = _ao2mo.nr_e2(v1[nset * 2:nset * 3], mo_vb_oa, (0, nvirb, nvirb, nvirb + nocca)) v1bb = _ao2mo.nr_e2(v1[nset * 3:], mo_vb_ob, (0, nvirb, nvirb, nvirb + noccb)) v1aa = v1aa.reshape(nset, nvira, nocca) v1ab = v1ab.reshape(nset, nvira, noccb) v1ba = v1ba.reshape(nset, nvirb, nocca) v1bb = v1bb.reshape(nset, nvirb, noccb) v1aa *= eai_aa v1ab *= eai_ab v1ba *= eai_ba v1bb *= eai_bb v1mo = numpy.hstack((v1aa.reshape(nset, -1), v1ab.reshape(nset, -1), v1ba.reshape(nset, -1), v1bb.reshape(nset, -1))) return v1mo.ravel() mo1 = lib.krylov(vind, mo1.ravel(), tol=1e-9, max_cycle=20, verbose=log) log.timer('solving FC CPHF eqn', *cput1) mo1 = _split_mo1(mo1) return mo1
def kernel(mycc, t1=None, t2=None, l1=None, l2=None, eris=None, atmlst=None, mf_grad=None, verbose=logger.INFO): if t1 is None: t1 = mycc.t1 if t2 is None: t2 = mycc.t2 if l1 is None: l1 = mycc.l1 if l2 is None: l2 = mycc.l2 if eris is None: eris = ccsd._ERIS(mycc) if mf_grad is None: mf_grad = rhf_grad.Gradients(mycc._scf) log = logger.Logger(mycc.stdout, mycc.verbose) time0 = time.clock(), time.time() mol = mycc.mol if mycc.frozen is not 0: raise NotImplementedError('frozen orbital ccsd_grad') moidx = ccsd.get_moidx(mycc) mo_coeff = mycc.mo_coeff[:, moidx] #FIXME: ensure mycc.mo_coeff is canonical orbital mo_energy = eris.fock.diagonal() nocc, nvir = t1.shape nao, nmo = mo_coeff.shape nao_pair = nao * (nao + 1) // 2 log.debug('Build ccsd rdm1 intermediates') d1 = ccsd_rdm.gamma1_intermediates(mycc, t1, t2, l1, l2) doo, dov, dvo, dvv = d1 time1 = log.timer('rdm1 intermediates', *time0) log.debug('Build ccsd rdm2 intermediates') d2 = ccsd_rdm.gamma2_incore(mycc, t1, t2, l1, l2) time1 = log.timer('rdm2 intermediates', *time1) log.debug('Build ccsd response_rdm1') Ioo, Ivv, Ivo, Xvo = IX_intermediates(mycc, t1, t2, l1, l2, eris, d1, d2) time1 = log.timer('response_rdm1 intermediates', *time1) dm1mo = response_dm1(mycc, t1, t2, l1, l2, eris, (Ioo, Ivv, Ivo, Xvo)) dm1mo[:nocc, :nocc] = doo * 2 dm1mo[nocc:, nocc:] = dvv * 2 dm1ao = reduce(numpy.dot, (mo_coeff, dm1mo, mo_coeff.T)) im1 = numpy.zeros_like(dm1mo) im1[:nocc, :nocc] = Ioo im1[nocc:, nocc:] = Ivv im1[nocc:, :nocc] = Ivo im1[:nocc, nocc:] = Ivo.T im1 = reduce(numpy.dot, (mo_coeff, im1, mo_coeff.T)) time1 = log.timer('response_rdm1', *time1) log.debug('symmetrized rdm2 and MO->AO transformation') dm1_with_hf = dm1mo.copy() for i in range(nocc): dm1_with_hf[i, i] += 1 dm2ao = _rdm2_mo2ao(mycc, d2, dm1_with_hf, mo_coeff) time1 = log.timer('MO->AO transformation', *time1) log.debug('h1 and JK1') h1 = mf_grad.get_hcore(mol) s1 = mf_grad.get_ovlp(mol) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[:nocc].reshape(-1, 1) zeta = reduce(numpy.dot, (mo_coeff, zeta * dm1mo, mo_coeff.T)) p1 = numpy.dot(mo_coeff[:, :nocc], mo_coeff[:, :nocc].T) vhf4sij = reduce(numpy.dot, (p1, mycc._scf.get_veff(mol, dm1ao + dm1ao.T), p1)) time1 = log.timer('h1 and JK1', *time1) # Hartree-Fock part contribution hf_dm1 = mycc._scf.make_rdm1(mycc.mo_coeff, mycc.mo_occ) dm1ao += hf_dm1 zeta += mf_grad.make_rdm1e(mycc.mo_energy, mycc.mo_coeff, mycc.mo_occ) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst), 3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # s[1] dot I, note matrix im1 is not hermitian de[k] = (numpy.einsum('xij,ij->x', s1[:, p0:p1], im1[p0:p1]) + numpy.einsum('xji,ij->x', s1[:, p0:p1], im1[:, p0:p1])) # h[1] \dot DM, *2 for +c.c., contribute to f1 h1ao = mf_grad._grad_rinv(mol, ia) h1ao[:, p0:p1] += h1[:, p0:p1] de[k] += (numpy.einsum('xij,ij->x', h1ao, dm1ao) + numpy.einsum('xji,ij->x', h1ao, dm1ao)) # -s[1]*e \dot DM, contribute to f1 de[k] -= (numpy.einsum('xij,ij->x', s1[:, p0:p1], zeta[p0:p1]) + numpy.einsum('xji,ij->x', s1[:, p0:p1], zeta[:, p0:p1])) # -vhf[s_ij[1]], contribute to f1, *2 for s1+s1.T de[k] -= numpy.einsum('xij,ij->x', s1[:, p0:p1], vhf4sij[p0:p1]) * 2 # 2e AO integrals dot 2pdm eri1 = mol.intor('int2e_ip1', comp=3, aosym='s2kl', shls_slice=(shl0, shl1, 0, mol.nbas, 0, mol.nbas, 0, mol.nbas)) eri1 = eri1.reshape(3, p1 - p0, nao, -1) dm2buf = _load_block_tril(dm2ao, p0, p1) de[k] -= numpy.einsum('xijk,ijk->x', eri1, dm2buf) * 2 eri1 = dm2buf = None log.debug('grad of atom %d %s = %s', ia, mol.atom_symbol(ia), de[k]) time1 = log.timer('grad of atom %d' % ia, *time1) de += rhf_grad.grad_nuc(mol) log.note('CCSD gradinets') log.note('==============') log.note(' x y z') for k, ia in enumerate(atmlst): log.note('%d %s %15.9f %15.9f %15.9f', ia, mol.atom_symbol(ia), *de[k]) log.timer('CCSD gradients', *time0) return de
def mol_to_xyg3_grad(mol): print("In mol_to_xyg3_grad", flush=True) nmo = mol.nao nocc = mol.nelec[0] nvir = nmo - nocc so = slice(0, nocc) sv = slice(nocc, nmo) sa = slice(0, nmo) scfh = GGAHelper(mol, "b3lypg", mol_to_grids(mol)) nch = GGAHelper(mol, "0.8033*HF - 0.0140*LDA + 0.2107*B88, 0.6789*LYP", mol_to_grids(mol), init_scf=False) ncgga = NCGGAEngine(scfh, nch) e, eo, ev = scfh.e, scfh.eo, scfh.ev C, Co, Cv = scfh.C, scfh.Co, scfh.Cv eri0_mo = scfh.eri0_mo eri1_ao = scfh.eri1_ao S_1_mo = scfh.S_1_mo F_1_mo = scfh.F_1_mo Ax0_Core = scfh.Ax0_Core D_iajb = lib.direct_sum("i - a + j - b", scfh.eo, scfh.ev, scfh.eo, scfh.ev) t_iajb = eri0_mo[so, sv, so, sv] / D_iajb T_iajb = 2 * t_iajb - t_iajb.swapaxes(1, 3) D_r = np.zeros((nmo, nmo)) D_r[so, so] += - 2 * np.einsum("iakb, jakb -> ij", T_iajb, t_iajb) D_r[sv, sv] += 2 * np.einsum("iajc, ibjc -> ab", T_iajb, t_iajb) L = np.zeros((nvir, nocc)) L += Ax0_Core(sv, so, sa, sa)(D_r) L -= 4 * np.einsum("jakb, ijbk -> ai", T_iajb, eri0_mo[so, so, sv, so]) L += 4 * np.einsum("ibjc, abjc -> ai", T_iajb, eri0_mo[sv, sv, so, sv]) D_r[sv, so] = scf.cphf.solve(Ax0_Core(sv, so, sv, so), e, scfh.mo_occ, L, max_cycle=100, tol=1e-13)[0] # W[I] - Correct with s1-im1 term in PySCF D_WI = np.zeros((nmo, nmo)) D_WI[so, so] = - 2 * np.einsum("iakb, jakb -> ij", T_iajb, eri0_mo[so, sv, so, sv]) D_WI[sv, sv] = - 2 * np.einsum("iajc, ibjc -> ab", T_iajb, eri0_mo[so, sv, so, sv]) D_WI[sv, so] = - 4 * np.einsum("jakb, ijbk -> ai", T_iajb, eri0_mo[so, so, sv, so]) # W[II] - Correct with s1-zeta term in PySCF # Note that zeta in PySCF includes HF energy weighted density rdm1e # The need of scaler 1 in D_WII[sv, so] is that Aikens use doubled P D_WII = np.zeros((nmo, nmo)) D_WII[so, so] = - 0.5 * D_r[so, so] * lib.direct_sum("i + j -> ij", eo, eo) D_WII[sv, sv] = - 0.5 * D_r[sv, sv] * lib.direct_sum("a + b -> ab", ev, ev) D_WII[sv, so] = - D_r[sv, so] * eo # W[III] - Correct with s1-vhf_s1occ term in PySCF D_WIII = np.zeros((nmo, nmo)) D_WIII[so, so] = - 0.5 * Ax0_Core(so, so, sa, sa)(D_r) # Summation D_W = D_WI + D_WII + D_WIII # Non-seperatable - Correct with `de` generated in PySCF code part --2e AO integrals dot 2pdm-- D_pdm2_NS = 2 * np.einsum("iajb, ui, va, kj, lb -> uvkl", T_iajb, Co, Cv, Co, Cv) grad_B3LYP_MP2 = ( + (D_r * F_1_mo).sum(axis=(-1, -2)) + (D_W * S_1_mo).sum(axis=(-1, -2)) + (D_pdm2_NS * eri1_ao).sum(axis=(-1, -2, -3, -4)) ) return ncgga.E_1 + 0.3211 * grad_B3LYP_MP2
def kernel(tdgrad, z, atmlst=None, mf_grad=None, max_memory=2000, verbose=logger.INFO): mol = tdgrad.mol mf = tdgrad.base._scf mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff.shape nocc = (mo_occ > 0).sum() nvir = nmo - nocc #eai = lib.direct_sum('a-i->ai', mo_energy[nocc:], mo_energy[:nocc]) z = z[0].reshape(nocc, nvir).T orbv = mo_coeff[:, nocc:] orbo = mo_coeff[:, :nocc] def fvind(x): dm = numpy.einsum('pi,xij,qj->xpq', orbv, x, orbo) v_ao = mf.get_veff(mol, (dm + dm.transpose(0, 2, 1))) * 2 return numpy.einsum('pi,xpq,qj->xij', orbv, v_ao, orbo).reshape(3, -1) h1 = rhf_grad.get_hcore(mol) s1 = rhf_grad.get_ovlp(mol) eri1 = -mol.intor('int2e_ip1', aosym='s1', comp=3) eri1 = eri1.reshape(3, nao, nao, nao, nao) eri0 = ao2mo.kernel(mol, mo_coeff) eri0 = ao2mo.restore(1, eri0, nmo).reshape(nmo, nmo, nmo, nmo) g = eri0 * 2 - eri0.transpose(0, 3, 2, 1) zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[nocc:] if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst), 3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] mol.set_rinv_origin(mol.atom_coord(ia)) h1ao = -mol.atom_charge(ia) * mol.intor('int1e_iprinv', comp=3) h1ao[:, p0:p1] += h1[:, p0:p1] h1ao = h1ao + h1ao.transpose(0, 2, 1) h1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff, h1ao, mo_coeff) s1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff[p0:p1], s1[:, p0:p1], mo_coeff) s1mo = s1mo + s1mo.transpose(0, 2, 1) f1 = h1mo - numpy.einsum('xpq,pq->xpq', s1mo, zeta) f1 -= numpy.einsum('klpq,xlk->xpq', g[:nocc, :nocc], s1mo[:, :nocc, :nocc]) eri1a = eri1.copy() eri1a[:, :p0] = 0 eri1a[:, p1:] = 0 eri1a = eri1a + eri1a.transpose(0, 2, 1, 3, 4) eri1a = eri1a + eri1a.transpose(0, 3, 4, 1, 2) g1 = numpy.einsum('xpjkl,pi->xijkl', eri1a, mo_coeff) g1 = numpy.einsum('xipkl,pj->xijkl', g1, mo_coeff) g1 = numpy.einsum('xijpl,pk->xijkl', g1, mo_coeff) g1 = numpy.einsum('xijkp,pl->xijkl', g1, mo_coeff) g1 = g1 * 2 - g1.transpose(0, 1, 4, 3, 2) f1 += numpy.einsum('xkkpq->xpq', g1[:, :nocc, :nocc]) f1ai = f1[:, nocc:, :nocc].copy() c1 = s1mo * -.5 c1vo = cphf.solve(fvind, mo_energy, mo_occ, f1ai, max_cycle=50)[0] c1[:, nocc:, :nocc] = c1vo c1[:, :nocc, nocc:] = -(s1mo[:, nocc:, :nocc] + c1vo).transpose(0, 2, 1) f1 += numpy.einsum('kapq,xak->xpq', g[:nocc, nocc:], c1vo) f1 += numpy.einsum('akpq,xak->xpq', g[nocc:, :nocc], c1vo) e1 = numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:], z, z) e1 += numpy.einsum('xab,ai,bi->x', f1[:, nocc:, nocc:], z, z) e1 -= numpy.einsum('xij,ai,aj->x', f1[:, :nocc, :nocc], z, z) g1 = numpy.einsum('pjkl,xpi->xijkl', g, c1) g1 += numpy.einsum('ipkl,xpj->xijkl', g, c1) g1 += numpy.einsum('ijpl,xpk->xijkl', g, c1) g1 += numpy.einsum('ijkp,xpl->xijkl', g, c1) e1 += numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:], z, z) de[k] = e1 return de
def update_lambda(mycc, t1, t2, l1, l2, eris, imds): """ Update GCCSD lambda. """ time0 = logger.process_clock(), logger.perf_counter() log = logger.Logger(mycc.stdout, mycc.verbose) t1T = t1.T t2T = np.asarray(t2.transpose(2, 3, 0, 1), order='C') t1 = t2 = None nvir_seg, nvir, nocc = t2T.shape[:3] l1T = l1.T l2T = np.asarray(l2.transpose(2, 3, 0, 1), order='C') l1 = l2 = None ntasks = mpi.pool.size vlocs = [_task_location(nvir, task_id) for task_id in range(ntasks)] vloc0, vloc1 = vlocs[rank] log.debug2('vlocs %s', vlocs) assert vloc1 - vloc0 == nvir_seg fvo = eris.fock[nocc:, :nocc] mo_e_o = eris.mo_energy[:nocc] mo_e_v = eris.mo_energy[nocc:] + mycc.level_shift v1 = imds.v1 - np.diag(mo_e_v) v2 = imds.v2 - np.diag(mo_e_o) mba = einsum('cakl, cbkl -> ba', l2T, t2T) * 0.5 mba = mpi.allreduce_inplace(mba) mij = einsum('cdki, cdkj -> ij', l2T, t2T) * 0.5 mij = mpi.allreduce_inplace(mij) # m3 [a]bij m3 = einsum('abkl, ijkl -> abij', l2T, np.asarray(imds.woooo)) tauT = t2T #+ np.einsum('ai, bj -> abij', t1T[vloc0:vloc1] * 2.0, t1T, optimize=True) tmp = einsum('cdij, cdkl -> ijkl', l2T, tauT) tmp = mpi.allreduce_inplace(tmp) tauT = None vvoo = np.asarray(eris.xvoo) tmp = einsum('abkl, ijkl -> abij', vvoo, tmp) tmp *= 0.25 m3 += tmp tmp = None #tmp = einsum('cdij, dk -> ckij', l2T, t1T) #for task_id, tmp, p0, p1 in _rotate_vir_block(tmp, vlocs=vlocs): # m3 -= einsum('kcba, ckij -> abij', eris.ovvx[:, p0:p1], tmp) # tmp = None eris_vvvv = eris.xvvv.transpose(2, 3, 0, 1) tmp_2 = np.empty_like(l2T) # used for line 387 for task_id, l2T_tmp, p0, p1 in _rotate_vir_block(l2T, vlocs=vlocs): tmp = einsum('cdij, cdab -> abij', l2T_tmp, eris_vvvv[p0:p1]) tmp *= 0.5 m3 += tmp tmp_2[:, p0:p1] = einsum('acij, cb -> baij', l2T_tmp, v1[:, vloc0:vloc1]) tmp = l2T_tmp = None eris_vvvv = None #l1Tnew = einsum('abij, bj -> ai', m3, t1T) #l1Tnew = mpi.allgather(l1Tnew) l1Tnew = np.zeros_like(l1T) l2Tnew = m3 l2Tnew += vvoo #fvo1 = fvo #+ mpi.allreduce(einsum('cbkj, ck -> bj', vvoo, t1T[vloc0:vloc1])) #tmp = np.einsum('ai, bj -> abij', l1T[vloc0:vloc1], fvo1, optimize=True) tmp = 0.0 wvovo = np.asarray(imds.wovvo).transpose(1, 0, 2, 3) for task_id, w_tmp, p0, p1 in _rotate_vir_block(wvovo, vlocs=vlocs): tmp -= einsum('acki, cjbk -> abij', l2T[:, p0:p1], w_tmp) w_tmp = None wvovo = None tmp = tmp - tmp.transpose(0, 1, 3, 2) l2Tnew += tmp tmpT = mpi.alltoall_new([tmp[:, p0:p1] for p0, p1 in vlocs], split_recvbuf=True) for task_id, (p0, p1) in enumerate(vlocs): tmp = tmpT[task_id].reshape(p1 - p0, nvir_seg, nocc, nocc) l2Tnew[:, p0:p1] -= tmp.transpose(1, 0, 2, 3) tmp = None #tmp = einsum('ak, ijkb -> baij', l1T, eris.ooox) #tmp -= tmp_2 tmp = -tmp_2 tmp1vv = mba #+ np.dot(t1T, l1T.T) # ba tmp -= einsum('ca, bcij -> baij', tmp1vv, vvoo) l2Tnew += tmp tmpT = mpi.alltoall_new([tmp[:, p0:p1] for p0, p1 in vlocs], split_recvbuf=True) for task_id, (p0, p1) in enumerate(vlocs): tmp = tmpT[task_id].reshape(p1 - p0, nvir_seg, nocc, nocc) l2Tnew[:, p0:p1] -= tmp.transpose(1, 0, 2, 3) tmp = None #tmp = einsum('jcab, ci -> baji', eris.ovvx, -l1T) tmp = einsum('abki, jk -> abij', l2T, v2) tmp1oo = mij #+ np.dot(l1T.T, t1T) # ik tmp -= einsum('ik, abkj -> abij', tmp1oo, vvoo) vvoo = None l2Tnew += tmp l2Tnew -= tmp.transpose(0, 1, 3, 2) tmp = None #l1Tnew += fvo #tmp = einsum('bj, ibja -> ai', -l1T[vloc0:vloc1], eris.oxov) #l1Tnew += np.dot(v1.T, l1T) #l1Tnew -= np.dot(l1T, v2.T) #tmp -= einsum('cakj, icjk -> ai', l2T, imds.wovoo) #tmp -= einsum('bcak, bcik -> ai', imds.wvvvo, l2T) #tmp += einsum('baji, bj -> ai', l2T, imds.w3[vloc0:vloc1]) #tmp_2 = t1T[vloc0:vloc1] - np.dot(tmp1vv[vloc0:vloc1], t1T) #tmp_2 -= np.dot(t1T[vloc0:vloc1], mij) #tmp_2 += einsum('bcjk, ck -> bj', t2T, l1T) #tmp += einsum('baji, bj -> ai', vvoo, tmp_2) #tmp_2 = None #tmp += einsum('icab, bc -> ai', eris.oxvv, tmp1vv[:, vloc0:vloc1]) #l1Tnew += mpi.allreduce(tmp) #l1Tnew -= mpi.allgather(einsum('jika, kj -> ai', eris.ooox, tmp1oo)) #tmp = fvo - mpi.allreduce(einsum('bakj, bj -> ak', vvoo, t1T[vloc0:vloc1])) #vvoo = None #l1Tnew -= np.dot(tmp, mij.T) #l1Tnew -= np.dot(mba.T, tmp) eia = mo_e_o[:, None] - mo_e_v #l1Tnew /= eia.T for i in range(vloc0, vloc1): l2Tnew[i - vloc0] /= lib.direct_sum('i + jb -> bij', eia[:, i], eia) time0 = log.timer_debug1('update l1 l2', *time0) return l1Tnew.T, l2Tnew.transpose(2, 3, 0, 1)
def _gamma2_intermediates(mycc, t1, t2, l1, l2, eris=None, compress_vvvv=False): d2 = uccsd_rdm._gamma2_intermediates(mycc, t1, t2, l1, l2) if eris is None: eris = mycc.ao2mo() dovov, dovOV, dOVov, dOVOV = d2[0] dvvvv, dvvVV, dVVvv, dVVVV = d2[1] doooo, dooOO, dOOoo, dOOOO = d2[2] doovv, dooVV, dOOvv, dOOVV = d2[3] dovvo, dovVO, dOVvo, dOVVO = d2[4] dvvov, dvvOV, dVVov, dVVOV = d2[5] dovvv, dovVV, dOVvv, dOVVV = d2[6] dooov, dooOV, dOOov, dOOOV = d2[7] t1a, t1b = t1 t2aa, t2ab, t2bb = t2 nocca, noccb, nvira, nvirb = t2ab.shape nmoa = eris.focka.shape[0] nmob = eris.fockb.shape[0] mo_ea = eris.focka.diagonal().real mo_eb = eris.fockb.diagonal().real eia = mo_ea[:nocca, None] - mo_ea[nocca:] eIA = mo_eb[:noccb, None] - mo_eb[noccb:] fvo = eris.focka[nocca:, :nocca] fVO = eris.fockb[noccb:, :noccb] # aaa d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eia, eia) w = numpy.einsum('ijae,kceb->ijkabc', t2aa, numpy.asarray(eris.get_ovvv()).conj()) w -= numpy.einsum('mkbc,iajm->ijkabc', t2aa, numpy.asarray(eris.ovoo.conj())) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.ovov).conj(), t1a) v += numpy.einsum('jkbc,ai->ijkabc', t2aa, fvo) * .5 rw = r6(p6(w)) / d3 wvd = r6(p6(w * 2 + v)) / d3 dovov += numpy.einsum('ia,ijkabc->jbkc', t1a, rw.conj()) * 0.25 # *(1/8) instead of (1/4) because ooov appears 4 times in the 2pdm tensor due # to symmetrization, and its contribution is scaled by 1/2 in Tr(H,2pdm) dooov -= numpy.einsum('mkbc,ijkabc->jmia', t2aa, wvd.conj()) * .125 dovvv += numpy.einsum('kjcf,ijkabc->iafb', t2aa, wvd.conj()) * .125 # bbb d3 = lib.direct_sum('ia+jb+kc->ijkabc', eIA, eIA, eIA) w = numpy.einsum('ijae,kceb->ijkabc', t2bb, numpy.asarray(eris.get_OVVV()).conj()) w -= numpy.einsum('imab,kcjm->ijkabc', t2bb, numpy.asarray(eris.OVOO.conj())) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.OVOV).conj(), t1b) v += numpy.einsum('jkbc,ai->ijkabc', t2bb, fVO) * .5 rw = r6(p6(w)) / d3 wvd = r6(p6(w * 2 + v)) / d3 dOVOV += numpy.einsum('ia,ijkabc->jbkc', t1b, rw.conj()) * .25 dOOOV -= numpy.einsum('mkbc,ijkabc->jmia', t2bb, wvd.conj()) * .125 dOVVV += numpy.einsum('kjcf,ijkabc->iafb', t2bb, wvd.conj()) * .125 # baa d3 = lib.direct_sum('ia+jb+kc->ijkabc', eIA, eia, eia) w = numpy.einsum('jIeA,kceb->IjkAbc', t2ab, numpy.asarray(eris.get_ovvv()).conj()) * 2 w += numpy.einsum('jIbE,kcEA->IjkAbc', t2ab, numpy.asarray(eris.get_ovVV()).conj()) * 2 w += numpy.einsum('jkbe,IAec->IjkAbc', t2aa, numpy.asarray(eris.get_OVvv()).conj()) w -= numpy.einsum('mIbA,kcjm->IjkAbc', t2ab, numpy.asarray(eris.ovoo).conj()) * 2 w -= numpy.einsum('jMbA,kcIM->IjkAbc', t2ab, numpy.asarray(eris.ovOO).conj()) * 2 w -= numpy.einsum('jmbc,IAkm->IjkAbc', t2aa, numpy.asarray(eris.OVoo).conj()) v = numpy.einsum('jbkc,IA->IjkAbc', numpy.asarray(eris.ovov).conj(), t1b) v += numpy.einsum('kcIA,jb->IjkAbc', numpy.asarray(eris.ovOV).conj(), t1a) v += numpy.einsum('kcIA,jb->IjkAbc', numpy.asarray(eris.ovOV).conj(), t1a) v += numpy.einsum('jkbc,AI->IjkAbc', t2aa, fVO) * .5 v += numpy.einsum('kIcA,bj->IjkAbc', t2ab, fvo) * 2 rw = r4(w) / d3 wvd = r4(w * 2 + v) / d3 dovvv += numpy.einsum('jiea,ijkabc->kceb', t2ab, wvd.conj()) * .25 dovVV += numpy.einsum('jibe,ijkabc->kcea', t2ab, wvd.conj()) * .25 dOVvv += numpy.einsum('jkbe,ijkabc->iaec', t2aa, wvd.conj()) * .125 dooov -= numpy.einsum('miba,ijkabc->jmkc', t2ab, wvd.conj()) * .25 dOOov -= numpy.einsum('jmba,ijkabc->imkc', t2ab, wvd.conj()) * .25 dooOV -= numpy.einsum('jmbc,ijkabc->kmia', t2aa, wvd.conj()) * .125 dovov += numpy.einsum('ia,ijkabc->jbkc', t1b, rw.conj()) * .25 #dOVov += numpy.einsum('jb,ijkabc->iakc', t1a, rw.conj()) * .25 dovOV += numpy.einsum('jb,ijkabc->kcia', t1a, rw.conj()) * .25 # bba d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eIA, eIA) w = numpy.einsum('ijae,kceb->ijkabc', t2ab, numpy.asarray(eris.get_OVVV()).conj()) * 2 w += numpy.einsum('ijeb,kcea->ijkabc', t2ab, numpy.asarray(eris.get_OVvv()).conj()) * 2 w += numpy.einsum('jkbe,iaec->ijkabc', t2bb, numpy.asarray(eris.get_ovVV()).conj()) w -= numpy.einsum('imab,kcjm->ijkabc', t2ab, numpy.asarray(eris.OVOO).conj()) * 2 w -= numpy.einsum('mjab,kcim->ijkabc', t2ab, numpy.asarray(eris.OVoo).conj()) * 2 w -= numpy.einsum('jmbc,iakm->ijkabc', t2bb, numpy.asarray(eris.ovOO).conj()) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.OVOV).conj(), t1a) v += numpy.einsum('iakc,jb->ijkabc', numpy.asarray(eris.ovOV).conj(), t1b) v += numpy.einsum('iakc,jb->ijkabc', numpy.asarray(eris.ovOV).conj(), t1b) v += numpy.einsum('JKBC,ai->iJKaBC', t2bb, fvo) * .5 v += numpy.einsum('iKaC,BJ->iJKaBC', t2ab, fVO) * 2 rw = r4(w) / d3 wvd = r4(w * 2 + v) / d3 dOVVV += numpy.einsum('ijae,ijkabc->kceb', t2ab, wvd.conj()) * .25 dOVvv += numpy.einsum('ijeb,ijkabc->kcea', t2ab, wvd.conj()) * .25 dovVV += numpy.einsum('jkbe,ijkabc->iaec', t2bb, wvd.conj()) * .125 dOOOV -= numpy.einsum('imab,ijkabc->jmkc', t2ab, wvd.conj()) * .25 dooOV -= numpy.einsum('mjab,ijkabc->imkc', t2ab, wvd.conj()) * .25 dOOov -= numpy.einsum('jmbc,ijkabc->kmia', t2bb, wvd.conj()) * .125 dOVOV += numpy.einsum('ia,ijkabc->jbkc', t1a, rw.conj()) * .25 dovOV += numpy.einsum('jb,ijkabc->iakc', t1b, rw.conj()) * .25 #dOVov += numpy.einsum('jb,ijkabc->kcia', t1b, rw.conj()) * .25 if compress_vvvv: nmoa, nmob = mycc.nmo nocca, noccb, nvira, nvirb = t2ab.shape idxa = numpy.tril_indices(nvira) idxa = idxa[0] * nvira + idxa[1] idxb = numpy.tril_indices(nvirb) idxb = idxb[0] * nvirb + idxb[1] dvvvv = dvvvv + dvvvv.transpose(1, 0, 2, 3) dvvvv = lib.take_2d(dvvvv.reshape(nvira**2, nvira**2), idxa, idxa) dvvvv *= .5 dvvVV = dvvVV + dvvVV.transpose(1, 0, 2, 3) dvvVV = lib.take_2d(dvvVV.reshape(nvira**2, nvirb**2), idxa, idxb) dVVVV = dVVVV + dVVVV.transpose(1, 0, 2, 3) dVVVV = lib.take_2d(dVVVV.reshape(nvirb**2, nvirb**2), idxb, idxb) dVVVV *= .5 d2 = ((dovov, dovOV, dOVov, dOVOV), (dvvvv, dvvVV, dVVvv, dVVVV), (doooo, dooOO, dOOoo, dOOOO), (doovv, dooVV, dOOvv, dOOVV), (dovvo, dovVO, dOVvo, dOVVO), (dvvov, dvvOV, dVVov, dVVOV), (dovvv, dovVV, dOVvv, dOVVV), (dooov, dooOV, dOOov, dOOOV)) return d2
def kernel(td_grad, x_y, singlet=True, atmlst=None, max_memory=2000, verbose=logger.INFO): log = logger.new_logger(td_grad, verbose) time0 = time.clock(), time.time() mol = td_grad.mol mf = td_grad.base._scf mo_coeff = mf.mo_coeff mo_energy = mf.mo_energy mo_occ = mf.mo_occ nao, nmo = mo_coeff.shape nocc = (mo_occ > 0).sum() nvir = nmo - nocc x, y = x_y xpy = (x + y).reshape(nocc, nvir).T xmy = (x - y).reshape(nocc, nvir).T orbv = mo_coeff[:, nocc:] orbo = mo_coeff[:, :nocc] dvv = numpy.einsum('ai,bi->ab', xpy, xpy) + numpy.einsum( 'ai,bi->ab', xmy, xmy) doo = -numpy.einsum('ai,aj->ij', xpy, xpy) - numpy.einsum( 'ai,aj->ij', xmy, xmy) dmzvop = reduce(numpy.dot, (orbv, xpy, orbo.T)) dmzvom = reduce(numpy.dot, (orbv, xmy, orbo.T)) dmzoo = reduce(numpy.dot, (orbo, doo, orbo.T)) dmzoo += reduce(numpy.dot, (orbv, dvv, orbv.T)) mem_now = lib.current_memory()[0] max_memory = max(2000, td_grad.max_memory * .9 - mem_now) ni = mf._numint ni.libxc.test_deriv_order(mf.xc, 3, raise_error=True) omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin) # dm0 = mf.make_rdm1(mo_coeff, mo_occ), but it is not used when computing # fxc since rho0 is passed to fxc function. dm0 = None rho0, vxc, fxc = ni.cache_xc_kernel(mf.mol, mf.grids, mf.xc, [mo_coeff] * 2, [mo_occ * .5] * 2, spin=1) f1vo, f1oo, vxc1, k1ao = \ _contract_xc_kernel(td_grad, mf.xc, dmzvop, dmzoo, True, True, singlet, max_memory) if abs(hyb) > 1e-10: dm = (dmzoo, dmzvop + dmzvop.T, dmzvom - dmzvom.T) vj, vk = mf.get_jk(mol, dm, hermi=0) vk *= hyb if abs(omega) > 1e-10: vk += rks._get_k_lr(mol, dm, omega) * (alpha - hyb) veff0doo = vj[0] * 2 - vk[0] + f1oo[0] + k1ao[0] * 2 wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2 if singlet: veff = vj[1] * 2 - vk[1] + f1vo[0] * 2 else: veff = -vk[1] + f1vo[0] * 2 veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff)) wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc], xpy) * 2 wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:, nocc:], xpy) * 2 veff = -vk[2] veff0mom = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff)) wvo -= numpy.einsum('ki,ai->ak', veff0mom[:nocc, :nocc], xmy) * 2 wvo += numpy.einsum('ac,ai->ci', veff0mom[nocc:, nocc:], xmy) * 2 else: vj = mf.get_j(mol, (dmzoo, dmzvop + dmzvop.T), hermi=1) veff0doo = vj[0] * 2 + f1oo[0] + k1ao[0] * 2 wvo = reduce(numpy.dot, (orbv.T, veff0doo, orbo)) * 2 if singlet: veff = vj[1] * 2 + f1vo[0] * 2 else: veff = f1vo[0] * 2 veff0mop = reduce(numpy.dot, (mo_coeff.T, veff, mo_coeff)) wvo -= numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc], xpy) * 2 wvo += numpy.einsum('ac,ai->ci', veff0mop[nocc:, nocc:], xpy) * 2 veff0mom = numpy.zeros((nmo, nmo)) def fvind(x): # Cannot make call to .base.get_vind because first order orbitals are solved # through closed shell ground state CPHF. dm = reduce(numpy.dot, (orbv, x.reshape(nvir, nocc), orbo.T)) dm = dm + dm.T # Call singlet XC kernel contraction, for closed shell ground state vindxc = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm, 0, singlet, rho0, vxc, fxc, max_memory) if abs(hyb) > 1e-10: vj, vk = mf.get_jk(mol, dm) veff = vj * 2 - hyb * vk + vindxc if abs(omega) > 1e-10: veff -= rks._get_k_lr(mol, dm, omega, hermi=1) * (alpha - hyb) else: vj = mf.get_j(mol, dm) veff = vj * 2 + vindxc return reduce(numpy.dot, (orbv.T, veff, orbo)).ravel() z1 = cphf.solve(fvind, mo_energy, mo_occ, wvo, max_cycle=td_grad.cphf_max_cycle, tol=td_grad.cphf_conv_tol)[0] z1 = z1.reshape(nvir, nocc) time1 = log.timer('Z-vector using CPHF solver', *time0) z1ao = reduce(numpy.dot, (orbv, z1, orbo.T)) # Note Z-vector is always associated to singlet integrals. fxcz1 = _contract_xc_kernel(td_grad, mf.xc, z1ao, None, False, False, True, max_memory)[0] if abs(hyb) > 1e-10: vj, vk = mf.get_jk(mol, z1ao, hermi=0) veff = vj * 2 - hyb * vk + fxcz1[0] if abs(omega) > 1e-10: veff -= rks._get_k_lr(mol, z1ao, omega) * (alpha - hyb) else: vj = mf.get_j(mol, z1ao, hermi=1) veff = vj * 2 + fxcz1[0] im0 = numpy.zeros((nmo, nmo)) im0[:nocc, :nocc] = reduce(numpy.dot, (orbo.T, veff0doo + veff, orbo)) im0[:nocc, :nocc] += numpy.einsum('ak,ai->ki', veff0mop[nocc:, :nocc], xpy) im0[:nocc, :nocc] += numpy.einsum('ak,ai->ki', veff0mom[nocc:, :nocc], xmy) im0[nocc:, nocc:] = numpy.einsum('ci,ai->ac', veff0mop[nocc:, :nocc], xpy) im0[nocc:, nocc:] += numpy.einsum('ci,ai->ac', veff0mom[nocc:, :nocc], xmy) im0[nocc:, :nocc] = numpy.einsum('ki,ai->ak', veff0mop[:nocc, :nocc], xpy) * 2 im0[nocc:, :nocc] += numpy.einsum('ki,ai->ak', veff0mom[:nocc, :nocc], xmy) * 2 zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5 zeta[nocc:, :nocc] = mo_energy[:nocc] zeta[:nocc, nocc:] = mo_energy[nocc:] dm1 = numpy.zeros((nmo, nmo)) dm1[:nocc, :nocc] = doo dm1[nocc:, nocc:] = dvv dm1[nocc:, :nocc] = z1 dm1[:nocc, :nocc] += numpy.eye(nocc) * 2 # for ground state im0 = reduce(numpy.dot, (mo_coeff, im0 + zeta * dm1, mo_coeff.T)) hcore_deriv = td_grad.hcore_generator(mol) s1 = td_grad.get_ovlp(mol) dmz1doo = z1ao + dmzoo oo0 = reduce(numpy.dot, (orbo, orbo.T)) if abs(hyb) > 1e-10: dm = (oo0, dmz1doo + dmz1doo.T, dmzvop + dmzvop.T, dmzvom - dmzvom.T) vj, vk = td_grad.get_jk(mol, dm) vk *= hyb if abs(omega) > 1e-10: with mol.with_range_coulomb(omega): vk += td_grad.get_k(mol, dm) * (alpha - hyb) vj = vj.reshape(-1, 3, nao, nao) vk = vk.reshape(-1, 3, nao, nao) if singlet: veff1 = vj * 2 - vk else: veff1 = numpy.vstack((vj[:2] * 2 - vk[:2], -vk[2:])) else: vj = td_grad.get_j(mol, (oo0, dmz1doo + dmz1doo.T, dmzvop + dmzvop.T)) vj = vj.reshape(-1, 3, nao, nao) veff1 = numpy.zeros((4, 3, nao, nao)) if singlet: veff1[:3] = vj * 2 else: veff1[:2] = vj[:2] * 2 veff1[0] += vxc1[1:] veff1[1] += (f1oo[1:] + fxcz1[1:] + k1ao[1:] * 2) * 2 # *2 for dmz1doo+dmz1oo.T veff1[2] += f1vo[1:] * 2 time1 = log.timer('2e AO integral derivatives', *time1) if atmlst is None: atmlst = range(mol.natm) offsetdic = mol.offset_nr_by_atom() de = numpy.zeros((len(atmlst), 3)) for k, ia in enumerate(atmlst): shl0, shl1, p0, p1 = offsetdic[ia] # Ground state gradients h1ao = hcore_deriv(ia) h1ao[:, p0:p1] += veff1[0, :, p0:p1] h1ao[:, :, p0:p1] += veff1[0, :, p0:p1].transpose(0, 2, 1) # oo0*2 for doubly occupied orbitals e1 = numpy.einsum('xpq,pq->x', h1ao, oo0) * 2 e1 += numpy.einsum('xpq,pq->x', h1ao, dmz1doo) e1 -= numpy.einsum('xpq,pq->x', s1[:, p0:p1], im0[p0:p1]) e1 -= numpy.einsum('xqp,pq->x', s1[:, p0:p1], im0[:, p0:p1]) e1 += numpy.einsum('xij,ij->x', veff1[1, :, p0:p1], oo0[p0:p1]) e1 += numpy.einsum('xij,ij->x', veff1[2, :, p0:p1], dmzvop[p0:p1, :]) * 2 e1 += numpy.einsum('xij,ij->x', veff1[3, :, p0:p1], dmzvom[p0:p1, :]) * 2 e1 += numpy.einsum('xji,ij->x', veff1[2, :, p0:p1], dmzvop[:, p0:p1]) * 2 e1 -= numpy.einsum('xji,ij->x', veff1[3, :, p0:p1], dmzvom[:, p0:p1]) * 2 de[k] = e1 log.timer('TDDFT nuclear gradients', *time0) return de
def _gamma1_intermediates(mycc, t1, t2, l1, l2, eris=None, for_grad=False): d1 = uccsd_rdm._gamma1_intermediates(mycc, t1, t2, l1, l2) if eris is None: eris = mycc.ao2mo() t1a, t1b = t1 t2aa, t2ab, t2bb = t2 nocca, noccb, nvira, nvirb = t2ab.shape nmoa = eris.focka.shape[0] nmob = eris.fockb.shape[0] mo_ea = eris.focka.diagonal().real mo_eb = eris.fockb.diagonal().real eia = mo_ea[:nocca, None] - mo_ea[nocca:] eIA = mo_eb[:noccb, None] - mo_eb[noccb:] fvo = eris.focka[nocca:, :nocca] fVO = eris.fockb[noccb:, :noccb] # aaa d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eia, eia) w = numpy.einsum('ijae,kceb->ijkabc', t2aa, numpy.asarray(eris.get_ovvv()).conj()) w -= numpy.einsum('mkbc,iajm->ijkabc', t2aa, numpy.asarray(eris.ovoo.conj())) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.ovov).conj(), t1a) v += numpy.einsum('jkbc,ai->ijkabc', t2aa, fvo) * .5 rw = p6(r6(w)) / d3 wvd = p6(w + v) / d3 goo = numpy.einsum('iklabc,jklabc->ij', wvd.conj(), rw) * .125 gvv = numpy.einsum('ijkacd,ijkbcd->ab', wvd, rw.conj()) * .125 gvo = numpy.einsum('jkbc,ijkabc->ai', t2aa.conj(), rw) * .125 # bbb d3 = lib.direct_sum('ia+jb+kc->ijkabc', eIA, eIA, eIA) w = numpy.einsum('ijae,kceb->ijkabc', t2bb, numpy.asarray(eris.get_OVVV()).conj()) w -= numpy.einsum('imab,kcjm->ijkabc', t2bb, numpy.asarray(eris.OVOO.conj())) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.OVOV).conj(), t1b) v += numpy.einsum('jkbc,ai->ijkabc', t2bb, fVO) * .5 rw = p6(r6(w)) / d3 wvd = p6(w + v) / d3 gOO = numpy.einsum('iklabc,jklabc->ij', wvd.conj(), rw) * .125 gVV = numpy.einsum('ijkacd,ijkbcd->ab', wvd, rw.conj()) * .125 gVO = numpy.einsum('jkbc,ijkabc->ai', t2bb.conj(), rw) * .125 # baa d3 = lib.direct_sum('ia+jb+kc->ijkabc', eIA, eia, eia) w = numpy.einsum('jIeA,kceb->IjkAbc', t2ab, numpy.asarray(eris.get_ovvv()).conj()) * 2 w += numpy.einsum('jIbE,kcEA->IjkAbc', t2ab, numpy.asarray(eris.get_ovVV()).conj()) * 2 w += numpy.einsum('jkbe,IAec->IjkAbc', t2aa, numpy.asarray(eris.get_OVvv()).conj()) w -= numpy.einsum('mIbA,kcjm->IjkAbc', t2ab, numpy.asarray(eris.ovoo).conj()) * 2 w -= numpy.einsum('jMbA,kcIM->IjkAbc', t2ab, numpy.asarray(eris.ovOO).conj()) * 2 w -= numpy.einsum('jmbc,IAkm->IjkAbc', t2aa, numpy.asarray(eris.OVoo).conj()) v = numpy.einsum('jbkc,IA->IjkAbc', numpy.asarray(eris.ovov).conj(), t1b) v += numpy.einsum('kcIA,jb->IjkAbc', numpy.asarray(eris.ovOV).conj(), t1a) v += numpy.einsum('kcIA,jb->IjkAbc', numpy.asarray(eris.ovOV).conj(), t1a) v += numpy.einsum('jkbc,AI->IjkAbc', t2aa, fVO) * .5 v += numpy.einsum('kIcA,bj->IjkAbc', t2ab, fvo) * 2 rw = r4(w) / d3 wvd = (w + v) / d3 goo += numpy.einsum('kilabc,kjlabc->ij', wvd.conj(), rw) * .25 goo += numpy.einsum('kliabc,kljabc->ij', wvd.conj(), rw) * .25 gOO += numpy.einsum('iklabc,jklabc->ij', wvd.conj(), rw) * .25 gvv += numpy.einsum('ijkcad,ijkcbd->ab', wvd, rw.conj()) * .25 gvv += numpy.einsum('ijkcda,ijkcdb->ab', wvd, rw.conj()) * .25 gVV += numpy.einsum('ijkacd,ijkbcd->ab', wvd, rw.conj()) * .25 gvo += numpy.einsum('kica,ijkabc->bj', t2ab.conj(), rw) * .5 gVO += numpy.einsum('jkbc,ijkabc->ai', t2aa.conj(), rw) * .125 # bba d3 = lib.direct_sum('ia+jb+kc->ijkabc', eia, eIA, eIA) w = numpy.einsum('ijae,kceb->ijkabc', t2ab, numpy.asarray(eris.get_OVVV()).conj()) * 2 w += numpy.einsum('ijeb,kcea->ijkabc', t2ab, numpy.asarray(eris.get_OVvv()).conj()) * 2 w += numpy.einsum('jkbe,iaec->ijkabc', t2bb, numpy.asarray(eris.get_ovVV()).conj()) w -= numpy.einsum('imab,kcjm->ijkabc', t2ab, numpy.asarray(eris.OVOO).conj()) * 2 w -= numpy.einsum('mjab,kcim->ijkabc', t2ab, numpy.asarray(eris.OVoo).conj()) * 2 w -= numpy.einsum('jmbc,iakm->ijkabc', t2bb, numpy.asarray(eris.ovOO).conj()) v = numpy.einsum('jbkc,ia->ijkabc', numpy.asarray(eris.OVOV).conj(), t1a) v += numpy.einsum('iakc,jb->ijkabc', numpy.asarray(eris.ovOV).conj(), t1b) v += numpy.einsum('iakc,jb->ijkabc', numpy.asarray(eris.ovOV).conj(), t1b) v += numpy.einsum('JKBC,ai->iJKaBC', t2bb, fvo) * .5 v += numpy.einsum('iKaC,BJ->iJKaBC', t2ab, fVO) * 2 rw = r4(w) / d3 wvd = (w + v) / d3 goo += numpy.einsum('iklabc,jklabc->ij', wvd.conj(), rw) * .25 gOO += numpy.einsum('kilabc,kjlabc->ij', wvd.conj(), rw) * .25 gOO += numpy.einsum('kliabc,kljabc->ij', wvd.conj(), rw) * .25 gvv += numpy.einsum('ijkacd,ijkbcd->ab', wvd, rw.conj()) * .25 gVV += numpy.einsum('ijkcad,ijkcbd->ab', wvd, rw.conj()) * .25 gVV += numpy.einsum('ijkcda,ijkcdb->ab', wvd, rw.conj()) * .25 gVO += numpy.einsum('ikac,ijkabc->bj', t2ab.conj(), rw) * .5 gvo += numpy.einsum('jkbc,ijkabc->ai', t2bb.conj(), rw) * .125 doo, dOO = d1[0] dov, dOV = d1[1] dvo, dVO = d1[2] dvv, dVV = d1[3] if for_grad: doo -= goo dOO -= gOO dvv += gvv dVV += gVV else: doo[numpy.diag_indices(nocca)] -= goo.diagonal() dOO[numpy.diag_indices(noccb)] -= gOO.diagonal() dvv[numpy.diag_indices(nvira)] += gvv.diagonal() dVV[numpy.diag_indices(nvirb)] += gVV.diagonal() dvo += gvo dVO += gVO return d1
def ucphf_with_freq(mf, mo_energy, mo_occ, h1, freq=0, max_cycle=20, tol=1e-9, hermi=False, verbose=logger.WARN): log = logger.new_logger(verbose=verbose) t0 = (time.clock(), time.time()) occidxa = mo_occ[0] > 0 occidxb = mo_occ[1] > 0 viridxa = ~occidxa viridxb = ~occidxb mo_ea, mo_eb = mo_energy # e_ai - freq may produce very small elements which can cause numerical # issue in krylov solver LEVEL_SHIF = 0.1 e_ai_a = lib.direct_sum('a-i->ai', mo_ea[viridxa], mo_ea[occidxa]).ravel() e_ai_b = lib.direct_sum('a-i->ai', mo_eb[viridxb], mo_eb[occidxb]).ravel() diag = (e_ai_a - freq, e_ai_b - freq, e_ai_a + freq, e_ai_b + freq) diag[0][diag[0] < LEVEL_SHIF] += LEVEL_SHIF diag[1][diag[1] < LEVEL_SHIF] += LEVEL_SHIF diag[2][diag[2] < LEVEL_SHIF] += LEVEL_SHIF diag[3][diag[3] < LEVEL_SHIF] += LEVEL_SHIF mo0a, mo0b = mf.mo_coeff nao, nmoa = mo0a.shape nmob = mo0b.shape orbva = mo0a[:, viridxa] orbvb = mo0b[:, viridxb] orboa = mo0a[:, occidxa] orbob = mo0b[:, occidxb] nvira = orbva.shape[1] nvirb = orbvb.shape[1] nocca = orboa.shape[1] noccb = orbob.shape[1] h1a = h1[0].reshape(-1, nvira * nocca) h1b = h1[1].reshape(-1, nvirb * noccb) ncomp = h1a.shape[0] mo1base = numpy.hstack( (-h1a / diag[0], -h1b / diag[1], -h1a / diag[2], -h1b / diag[3])) offsets = numpy.cumsum((nocca * nvira, noccb * nvirb, nocca * nvira)) vresp = _gen_uhf_response(mf, hermi=0) def vind(xys): nz = len(xys) dm1a = numpy.empty((nz, nao, nao)) dm1b = numpy.empty((nz, nao, nao)) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca), orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira, nocca).T, orbva.T)) dm1a[i] = dmx + dmy # AX + BY dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb), orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb, noccb).T, orbvb.T)) dm1b[i] = dmx + dmy # AX + BY v1ao = vresp(numpy.stack((dm1a, dm1b))) v1voa = lib.einsum('xpq,pi,qj->xij', v1ao[0], orbva, orboa).reshape(nz, -1) v1vob = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbvb, orbob).reshape(nz, -1) v1ova = lib.einsum('xpq,pi,qj->xji', v1ao[0], orboa, orbva).reshape(nz, -1) v1ovb = lib.einsum('xpq,pi,qj->xji', v1ao[1], orbob, orbvb).reshape(nz, -1) for i in range(nz): xa, xb, ya, yb = numpy.split(xys[i], offsets) v1voa[i] += (e_ai_a - freq - diag[0]) * xa v1voa[i] /= diag[0] v1vob[i] += (e_ai_b - freq - diag[1]) * xb v1vob[i] /= diag[1] v1ova[i] += (e_ai_a + freq - diag[2]) * ya v1ova[i] /= diag[2] v1ovb[i] += (e_ai_b + freq - diag[3]) * yb v1ovb[i] /= diag[3] v = numpy.hstack((v1voa, v1vob, v1ova, v1ovb)) return v # FIXME: krylov solver is not accurate enough for many freqs. Using tight # tol and lindep could offer small help. A better linear equation solver # is needed. mo1 = lib.krylov(vind, mo1base, tol=tol, max_cycle=max_cycle, hermi=hermi, lindep=1e-18, verbose=log) log.timer('krylov solver in CPHF', *t0) dm1a = numpy.empty((ncomp, nao, nao)) dm1b = numpy.empty((ncomp, nao, nao)) for i in range(ncomp): xa, xb, ya, yb = numpy.split(mo1[i], offsets) dmx = reduce(numpy.dot, (orbva, xa.reshape(nvira, nocca) * 2, orboa.T)) dmy = reduce(numpy.dot, (orboa, ya.reshape(nvira, nocca).T * 2, orbva.T)) dm1a[i] = dmx + dmy dmx = reduce(numpy.dot, (orbvb, xb.reshape(nvirb, noccb) * 2, orbob.T)) dmy = reduce(numpy.dot, (orbob, yb.reshape(nvirb, noccb).T * 2, orbvb.T)) dm1b[i] = dmx + dmy v1ao = vresp(numpy.stack((dm1a, dm1b))) mo_e1_a = lib.einsum('xpq,pi,qj->xij', v1ao[0], orboa, orboa) mo_e1_b = lib.einsum('xpq,pi,qj->xij', v1ao[1], orbob, orbob) mo_e1 = (mo_e1_a, mo_e1_b) xa, xb, ya, yb = numpy.split(mo1, offsets, axis=1) mo1 = (xa.reshape(ncomp, nvira, nocca), xb.reshape(ncomp, nvirb, noccb), ya.reshape(ncomp, nvira, nocca), yb.reshape(ncomp, nvirb, noccb)) return mo1, mo_e1
def update_amps_independent_compressions( cc, t1: np.ndarray, t2: np.ndarray, eris: ccsd._ChemistsERIs, ): """Update the CC t1 and t2 amplitudes using a compressed t2 tensor for several of the contractions. Parameters ---------- cc : fricc.FRILCCSD CC object t1 : np.ndarray t1 amplitudes (nocc,nvirt) t2 : np.ndarray t2 amplitudes (nocc,nocc,nvirt,nvirt) eris : ccsd._ChemistsERIs 2e-integrals Returns ------- (np.ndarray,np.ndarray) The new t1 and t2 amplitudes Notes ----- Ref: Taube and Bartlett J. Chem. Phys. 130, 144112 (2009) Eq. 13 and 15 """ # # Check Args # assert isinstance(eris, ccsd._ChemistsERIs) log = lib.logger.new_logger(cc) m_keep = cc.fri_settings["m_keep"] # TODO add input checks m_keep = cc.fri_settings["m_keep"] if m_keep > t2.size or m_keep == 0: raise ValueError( "Bad m_keep value! The following condition wasn't met 0 < m_keep <= t2.size" ) compressed_contractions = cc.fri_settings["compressed_contractions"] contraction_timings = {} # # Shorthands # nocc, nvir = t1.shape fock = eris.fock mo_e_o = eris.mo_energy[:nocc] mo_e_v = eris.mo_energy[nocc:] + cc.level_shift fov = fock[:nocc, nocc:].copy() t_update_amps = time.perf_counter() # # Compression # log.debug(f"M_KEEP = {m_keep} of {t2.size}") # log.warn(f"|t2|_1 = {np.linalg.norm(t2.ravel(), ord=1)}") # np.save("fricc_t2.npy", t2.ravel()) # exit(0) t_compress = time.perf_counter() t2_sparse = [ SparseTensor4d( t2, t2.shape, int(m_keep), cc.fri_settings["compression"], cc.fri_settings["sampling_method"], cc.fri_settings["verbose"], ) for _ in range(6) ] t_compress = time.perf_counter() - t_compress # # Updating the Amplitudes # Foo = fock[:nocc, :nocc].copy() Fvv = fock[nocc:, nocc:].copy() Fov = fock[:nocc, nocc:].copy() # Move energy terms to the other side Foo[np.diag_indices(nocc)] -= mo_e_o Fvv[np.diag_indices(nvir)] -= mo_e_v ############### # T1 equation # ############### eris_ovoo = np.asarray(eris.ovoo, order="C") eris_ovvv = np.asarray(eris.get_ovvv()) if cc.fri_settings["LCCD"]: t1 = np.zeros_like(t1) t1new = np.zeros_like(t1) # DO LCCD else: t1new = np.zeros_like(t1) # Term 1 t1new += fov.conj() # Term 2 t1new += np.einsum("ac,ic->ia", Fvv, t1) # Term 3 t1new += -np.einsum("ki,ka->ia", Foo, t1) # Term 4 t1new += 2 * np.einsum("kcai,kc->ia", eris.ovvo, t1) t1new += -np.einsum("kiac,kc->ia", eris.oovv, t1) # Term 5 t1new += 2 * lib.einsum("kdac,ikcd->ia", eris_ovvv, t2) t1new += -lib.einsum("kcad,ikcd->ia", eris_ovvv, t2) # Term 6 t1new += -2 * lib.einsum("lcki,klac->ia", eris_ovoo, t2) t1new += lib.einsum("kcli,klac->ia", eris_ovoo, t2) # Term 7 t1new += 2 * np.einsum("kc,kica->ia", Fov, t2) t1new += -np.einsum("kc,ikca->ia", Fov, t2) ############### # T2 equation # ############### # Term 1 t2new = np.zeros_like(t2) t2new += np.asarray(eris.ovov).conj().transpose(0, 2, 1, 3) # Term 2 tmp = lib.einsum("ki,kjab->ijab", Foo, t2) t2new -= tmp + tmp.transpose(1, 0, 3, 2) # Term 3 tmp = lib.einsum("ac,ijcb->ijab", Fvv, t2) t2new += tmp + tmp.transpose(1, 0, 3, 2) Woooo = np.asarray(eris.oooo).copy().transpose(0, 2, 1, 3) Wvoov = np.asarray(eris.ovvo).copy().transpose(2, 0, 3, 1) Wvovo = np.asarray(eris.oovv).copy().transpose(2, 0, 3, 1) Wvvvv = np.asarray(imd._get_vvvv(eris)).transpose(0, 2, 1, 3) # Term 4 if "O^2V^4" in compressed_contractions: t_2323 = time.perf_counter() contract_DTSpT(Wvvvv, t2_sparse[0], t2new, "2323") contraction_timings["2323"] = time.perf_counter() - t_2323 else: t2new += lib.einsum("abcd,ijcd->ijab", Wvvvv, t2) # Term 5 if "O^4V^2" in compressed_contractions: t_0101 = time.perf_counter() contract_DTSpT(Woooo, t2_sparse[1], t2new, "0101") contraction_timings["0101"] = time.perf_counter() - t_0101 else: t2new += lib.einsum("klij,klab->ijab", Woooo, t2) # FRI-Compressed contraction # Term 6 if "O^3V^3" in compressed_contractions: tmp = np.zeros_like(t2new) t_1302 = time.perf_counter() contract_DTSpT(Wvoov, t2_sparse[2], tmp, "1302") contraction_timings["1302"] = time.perf_counter() - t_1302 t_1202 = time.perf_counter() contract_DTSpT(Wvovo, t2_sparse[3], tmp, "1202") contraction_timings["1202"] = time.perf_counter() - t_1202 t2new += tmp + tmp.transpose(1, 0, 3, 2) tmp = np.zeros_like(t2new) t_1303 = time.perf_counter() contract_DTSpT(Wvoov, t2_sparse[4], tmp, "1303") contraction_timings["1303"] = time.perf_counter() - t_1303 t2new -= tmp + tmp.transpose(1, 0, 3, 2) tmp = np.zeros_like(t2new) t_1203 = time.perf_counter() contract_DTSpT(Wvovo, t2_sparse[5], tmp, "1203") contraction_timings["1203"] = time.perf_counter() - t_1203 t2new -= tmp + tmp.transpose(1, 0, 3, 2) else: tmp = 2 * lib.einsum("akic,kjcb->ijab", Wvoov, t2) tmp -= lib.einsum("akci,kjcb->ijab", Wvovo, t2) t2new += tmp + tmp.transpose(1, 0, 3, 2) tmp = lib.einsum("akic,kjbc->ijab", Wvoov, t2) t2new -= tmp + tmp.transpose(1, 0, 3, 2) tmp = lib.einsum("bkci,kjac->ijab", Wvovo, t2) t2new -= tmp + tmp.transpose(1, 0, 3, 2) # Term 7 tmp = lib.einsum("akij,kb->ijab", eris_ovoo.transpose(1, 3, 0, 2).conj(), t1) t2new -= tmp + tmp.transpose(1, 0, 3, 2) # Term 8 tmp = lib.einsum("iabc,jc->ijab", np.asarray(eris_ovvv).conj(), t1) t2new += tmp + tmp.transpose(1, 0, 3, 2) # # eia = mo_e_o[:, None] - mo_e_v eijab = lib.direct_sum("ia,jb->ijab", eia, eia) t1new /= eia t2new /= eijab # # Timing # t_update_amps = time.perf_counter() - t_update_amps log.debug(f"\nFRI: Compression Time {t_compress:.3f}") fri_time = copy.copy(t_compress) for k, v in contraction_timings.items(): log.debug(f"FRI: Contraction {k} Time: {v:.3f} (s)") fri_time += v fri_time_frac = (fri_time) / t_update_amps log.debug( f"FRI: CCSD Total Time {t_update_amps:.3f} FRI-related fraction = {fri_time_frac:.3f}\n" ) return t1new, t2new
def build_se_part(gf2, eri, gf_occ, gf_vir, nmom, os_factor=1.0, ss_factor=1.0): ''' Builds the auxiliaries. ''' cput0 = (time.clock(), time.time()) log = logger.Logger(gf2.stdout, gf2.verbose) assert type(gf_occ) is agf2.GreensFunction assert type(gf_vir) is agf2.GreensFunction nmo = gf2.nmo nocc = gf_occ.naux nvir = gf_vir.naux tol = gf2.weight_tol if not (gf2.frozen is None or gf2.frozen == 0): mask = agf2.ragf2.get_frozen_mask(agf2) nmo -= np.sum(~mask) ei, ci = gf_occ.energy, gf_occ.coupling ea, ca = gf_vir.energy, gf_vir.coupling qxi, qja = agf2.dfragf2._make_qmo_eris_incore(gf2, eri, (ci, ci, ca)) t = np.zeros((2 * nmom + 2, nmo, nmo)) eija = lib.direct_sum('i,j,a->ija', ei, ei, -ea) naux = qxi.shape[0] buf = [np.empty((nmo, nocc * nvir)), np.empty((nmo * nocc, nvir))] for i in mpi_helper.nrange(nocc): qx = qxi.reshape(naux, nmo, nocc)[:, :, i] xija = lib.dot(qx.T, qja, c=buf[0]) xjia = lib.dot(qxi.T, qja[:, i * nvir:(i + 1) * nvir], c=buf[1]) xjia = xjia.reshape(nmo, nocc * nvir) xjia = 2.0 * xija - xjia #TODO: oo/ss factors eja = eija[i].ravel() for n in range(2 * nmom + 2): t[n] = lib.dot(xija, xjia.T, beta=1, c=t[n]) xjia *= eja[None] mpi_helper.barrier() mpi_helper.allreduce_safe_inplace(t) #t = _agf2.dfragf2_slow_fast_build(qxi, qja, ei, ea, 2*nmom+2, os_factor=os_factor, ss_factor=ss_factor) if not np.all(np.isfinite(t)): raise ValueError('Overflow from large moments') m, b = block_lanczos.block_lanczos(t, nmom + 1) e, v = block_lanczos.build_from_tridiag(m, b) se = agf2.SelfEnergy(e, v, chempot=gf_occ.chempot) se.remove_uncoupled(tol=tol) if not (gf2.frozen is None or gf2.frozen == 0): coupling = np.zeros((nmo, se.naux)) coupling[mask] = se.coupling se = agf2.SelfEnergy(se.energy, coupling, chempot=se.chempot) log.timer('se part', *cput0) return se
def get_ab(mf, mo_energy=None, mo_coeff=None, mo_occ=None): r'''A and B matrices for TDDFT response function. A[i,a,j,b] = \delta_{ab}\delta_{ij}(E_a - E_i) + (ia||bj) B[i,a,j,b] = (ia||jb) ''' if mo_energy is None: mo_energy = mf.mo_energy if mo_coeff is None: mo_coeff = mf.mo_coeff if mo_occ is None: mo_occ = mf.mo_occ assert (mo_coeff.dtype == numpy.double) mol = mf.mol nao, nmo = mo_coeff.shape occidx = numpy.where(mo_occ == 2)[0] viridx = numpy.where(mo_occ == 0)[0] orbv = mo_coeff[:, viridx] orbo = mo_coeff[:, occidx] nvir = orbv.shape[1] nocc = orbo.shape[1] mo = numpy.hstack((orbo, orbv)) nmo = nocc + nvir e_ia = lib.direct_sum('a-i->ia', mo_energy[viridx], mo_energy[occidx]) a = numpy.diag(e_ia.ravel()).reshape(nocc, nvir, nocc, nvir) b = numpy.zeros_like(a) def add_hf_(a, b, hyb=1): eri_mo = ao2mo.general(mol, [orbo, mo, mo, mo], compact=False) eri_mo = eri_mo.reshape(nocc, nmo, nmo, nmo) a += numpy.einsum('iabj->iajb', eri_mo[:nocc, nocc:, nocc:, :nocc]) * 2 a -= numpy.einsum('ijba->iajb', eri_mo[:nocc, :nocc, nocc:, nocc:]) * hyb b += numpy.einsum('iajb->iajb', eri_mo[:nocc, nocc:, :nocc, nocc:]) * 2 b -= numpy.einsum('jaib->iajb', eri_mo[:nocc, nocc:, :nocc, nocc:]) * hyb if isinstance(mf, scf.hf.KohnShamDFT): ni = mf._numint ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True) if getattr(mf, 'nlc', '') != '': logger.warn( mf, 'NLC functional found in DFT object. Its second ' 'deriviative is not available. Its contribution is ' 'not included in the response function.') omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin) add_hf_(a, b, hyb) xctype = ni._xc_type(mf.xc) dm0 = mf.make_rdm1(mo_coeff, mo_occ) make_rho = ni._gen_rho_evaluator(mol, dm0, hermi=1)[0] mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) if xctype == 'LDA': ao_deriv = 0 for ao, mask, weight, coords \ in ni.block_loop(mol, mf.grids, nao, ao_deriv, max_memory): rho = make_rho(0, ao, mask, 'LDA') fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[2] frr = fxc[0] rho_o = lib.einsum('rp,pi->ri', ao, orbo) rho_v = lib.einsum('rp,pi->ri', ao, orbv) rho_ov = numpy.einsum('ri,ra->ria', rho_o, rho_v) w_ov = numpy.einsum('ria,r->ria', rho_ov, weight * frr) iajb = lib.einsum('ria,rjb->iajb', rho_ov, w_ov) * 2 a += iajb b += iajb elif xctype == 'GGA': ao_deriv = 1 for ao, mask, weight, coords \ in ni.block_loop(mol, mf.grids, nao, ao_deriv, max_memory): rho = make_rho(0, ao, mask, 'GGA') vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3] vgamma = vxc[1] frho, frhogamma, fgg = fxc[:3] rho_o = lib.einsum('xrp,pi->xri', ao, orbo) rho_v = lib.einsum('xrp,pi->xri', ao, orbv) rho_ov = numpy.einsum('xri,ra->xria', rho_o, rho_v[0]) rho_ov[1:4] += numpy.einsum('ri,xra->xria', rho_o[0], rho_v[1:4]) # sigma1 ~ \nabla(\rho_\alpha+\rho_\beta) dot \nabla(|b><j|) z_{bj} sigma1 = numpy.einsum('xr,xria->ria', rho[1:4], rho_ov[1:4]) w_ov = numpy.empty_like(rho_ov) w_ov[0] = numpy.einsum('r,ria->ria', frho, rho_ov[0]) w_ov[0] += numpy.einsum('r,ria->ria', 2 * frhogamma, sigma1) f_ov = numpy.einsum('r,ria->ria', 4 * fgg, sigma1) f_ov += numpy.einsum('r,ria->ria', 2 * frhogamma, rho_ov[0]) w_ov[1:] = numpy.einsum('ria,xr->xria', f_ov, rho[1:4]) w_ov[1:] += numpy.einsum('r,xria->xria', 2 * vgamma, rho_ov[1:4]) w_ov *= weight[:, None, None] iajb = lib.einsum('xria,xrjb->iajb', rho_ov, w_ov) * 2 a += iajb b += iajb elif xctype == 'NLC': raise NotImplementedError('NLC') elif xctype == 'MGGA': raise NotImplementedError('meta-GGA') else: add_hf_(a, b) return a, b
def make_diagonal(myci, eris): nocca, noccb = eris.nocc nmoa = eris.focka.shape[0] nmob = eris.fockb.shape[1] nvira = nmoa - nocca nvirb = nmob - noccb jdiag_aa = numpy.zeros((nmoa,nmoa)) jdiag_ab = numpy.zeros((nmoa,nmob)) jdiag_bb = numpy.zeros((nmob,nmob)) jdiag_aa[:nocca,:nocca] = numpy.einsum('iijj->ij', eris.oooo) jdiag_aa[:nocca,nocca:] = numpy.einsum('iijj->ij', eris.oovv) jdiag_aa[nocca:,:nocca] = jdiag_aa[:nocca,nocca:].T jdiag_ab[:nocca,:noccb] = numpy.einsum('iijj->ij', eris.ooOO) jdiag_ab[:nocca,noccb:] = numpy.einsum('iijj->ij', eris.ooVV) jdiag_ab[nocca:,:noccb] = numpy.einsum('iijj->ji', eris.OOvv) jdiag_bb[:noccb,:noccb] = numpy.einsum('iijj->ij', eris.OOOO) jdiag_bb[:noccb,noccb:] = numpy.einsum('iijj->ij', eris.OOVV) jdiag_bb[noccb:,:noccb] = jdiag_bb[:noccb,noccb:].T kdiag_aa = numpy.zeros((nmoa,nmoa)) kdiag_bb = numpy.zeros((nmob,nmob)) kdiag_aa[:nocca,:nocca] = numpy.einsum('ijji->ij', eris.oooo) kdiag_aa[:nocca,nocca:] = numpy.einsum('ijji->ij', eris.ovvo) kdiag_aa[nocca:,:nocca] = kdiag_aa[:nocca,nocca:].T kdiag_bb[:noccb,:noccb] = numpy.einsum('ijji->ij', eris.OOOO) kdiag_bb[:noccb,noccb:] = numpy.einsum('ijji->ij', eris.OVVO) kdiag_bb[noccb:,:noccb] = kdiag_bb[:noccb,noccb:].T # if eris.vvvv is not None and eris.vvVV is not None and eris.VVVV is not None: # def diag_idx(n): # idx = numpy.arange(n) # return idx * (idx + 1) // 2 + idx # jdiag_aa[nocca:,nocca:] = eris.vvvv[diag_idx(nvira)[:,None],diag_idx(nvira)] # jdiag_ab[nocca:,noccb:] = eris.vvVV[diag_idx(nvira)[:,None],diag_idx(nvirb)] # jdiag_bb[noccb:,noccb:] = eris.VVVV[diag_idx(nvirb)[:,None],diag_idx(nvirb)] # kdiag_aa[nocca:,nocca:] = lib.unpack_tril(eris.vvvv.diagonal()) # kdiag_bb[noccb:,noccb:] = lib.unpack_tril(eris.VVVV.diagonal()) jkdiag_aa = jdiag_aa - kdiag_aa jkdiag_bb = jdiag_bb - kdiag_bb mo_ea = eris.focka.diagonal() mo_eb = eris.fockb.diagonal() ehf = (mo_ea[:nocca].sum() + mo_eb[:noccb].sum() - jkdiag_aa[:nocca,:nocca].sum() * .5 - jdiag_ab[:nocca,:noccb].sum() - jkdiag_bb[:noccb,:noccb].sum() * .5) dia_a = lib.direct_sum('a-i->ia', mo_ea[nocca:], mo_ea[:nocca]) dia_a -= jkdiag_aa[:nocca,nocca:] dia_b = lib.direct_sum('a-i->ia', mo_eb[noccb:], mo_eb[:noccb]) dia_b -= jkdiag_bb[:noccb,noccb:] e1diag_a = dia_a + ehf e1diag_b = dia_b + ehf e2diag_aa = lib.direct_sum('ia+jb->ijab', dia_a, dia_a) e2diag_aa += ehf e2diag_aa += jkdiag_aa[:nocca,:nocca].reshape(nocca,nocca,1,1) e2diag_aa -= jkdiag_aa[:nocca,nocca:].reshape(nocca,1,1,nvira) e2diag_aa -= jkdiag_aa[:nocca,nocca:].reshape(1,nocca,nvira,1) e2diag_aa += jkdiag_aa[nocca:,nocca:].reshape(1,1,nvira,nvira) e2diag_ab = lib.direct_sum('ia+jb->ijab', dia_a, dia_b) e2diag_ab += ehf e2diag_ab += jdiag_ab[:nocca,:noccb].reshape(nocca,noccb,1,1) e2diag_ab += jdiag_ab[nocca:,noccb:].reshape(1,1,nvira,nvirb) e2diag_ab -= jdiag_ab[:nocca,noccb:].reshape(nocca,1,1,nvirb) e2diag_ab -= jdiag_ab[nocca:,:noccb].T.reshape(1,noccb,nvira,1) e2diag_bb = lib.direct_sum('ia+jb->ijab', dia_b, dia_b) e2diag_bb += ehf e2diag_bb += jkdiag_bb[:noccb,:noccb].reshape(noccb,noccb,1,1) e2diag_bb -= jkdiag_bb[:noccb,noccb:].reshape(noccb,1,1,nvirb) e2diag_bb -= jkdiag_bb[:noccb,noccb:].reshape(1,noccb,nvirb,1) e2diag_bb += jkdiag_bb[noccb:,noccb:].reshape(1,1,nvirb,nvirb) return amplitudes_to_cisdvec(ehf, (e1diag_a, e1diag_b), (e2diag_aa, e2diag_ab, e2diag_bb))
def make_rdm2(mp, t2=None, eris=None, verbose=logger.NOTE): r''' Spin-traced two-particle density matrix in MO basis dm2[p,q,r,s] = \sum_{sigma,tau} <p_sigma^\dagger r_tau^\dagger s_tau q_sigma> Note the contraction between ERIs (in Chemist's notation) and rdm2 is E = einsum('pqrs,pqrs', eri, rdm2) ''' if t2 is None: t2 = mp.t2 nmo = nmo0 = mp.nmo nocc = nocc0 = mp.nocc nvir = nmo - nocc if t2 is None: if eris is None: eris = mp.ao2mo() mo_energy = _mo_energy_without_core(mp, mp.mo_energy) eia = mo_energy[:nocc, None] - mo_energy[None, nocc:] if not (mp.frozen is 0 or mp.frozen is None): nmo0 = mp.mo_occ.size nocc0 = numpy.count_nonzero(mp.mo_occ > 0) moidx = get_frozen_mask(mp) oidx = numpy.where(moidx & (mp.mo_occ > 0))[0] vidx = numpy.where(moidx & (mp.mo_occ == 0))[0] else: moidx = oidx = vidx = None dm1 = make_rdm1(mp, t2, eris, verbose) dm1[numpy.diag_indices(nocc0)] -= 2 dm2 = numpy.zeros((nmo0, nmo0, nmo0, nmo0), dtype=dm1.dtype) # Chemist notation #dm2[:nocc,nocc:,:nocc,nocc:] = t2.transpose(0,3,1,2)*2 - t2.transpose(0,2,1,3) #dm2[nocc:,:nocc,nocc:,:nocc] = t2.transpose(3,0,2,1)*2 - t2.transpose(2,0,3,1) for i in range(nocc): if t2 is None: gi = numpy.asarray(eris.ovov[i * nvir:(i + 1) * nvir]) gi = gi.reshape(nvir, nocc, nvir).transpose(1, 0, 2) t2i = gi.conj() / lib.direct_sum('jb+a->jba', eia, eia[i]) else: t2i = t2[i] # dm2 was computed as dm2[p,q,r,s] = < p^\dagger r^\dagger s q > in the # above. Transposing it so that it be contracted with ERIs (in Chemist's # notation): # E = einsum('pqrs,pqrs', eri, rdm2) dovov = t2i.transpose(1, 0, 2) * 2 - t2i.transpose(2, 0, 1) dovov *= 2 if moidx is None: dm2[i, nocc:, :nocc, nocc:] = dovov dm2[nocc:, i, nocc:, :nocc] = dovov.conj().transpose(0, 2, 1) else: dm2[oidx[i], vidx[:, None, None], oidx[:, None], vidx] = dovov dm2[vidx[:, None, None], oidx[i], vidx[:, None], oidx] = dovov.conj().transpose(0, 2, 1) # Be careful with convention of dm1 and dm2 # dm1[q,p] = <p^\dagger q> # dm2[p,q,r,s] = < p^\dagger r^\dagger s q > # E = einsum('pq,qp', h1, dm1) + .5 * einsum('pqrs,pqrs', eri, dm2) # When adding dm1 contribution, dm1 subscripts need to be flipped for i in range(nocc0): dm2[i, i, :, :] += dm1.T * 2 dm2[:, :, i, i] += dm1.T * 2 dm2[:, i, i, :] -= dm1.T dm2[i, :, :, i] -= dm1 for i in range(nocc0): for j in range(nocc0): dm2[i, i, j, j] += 4 dm2[i, j, j, i] -= 2 return dm2 #.transpose(1,0,3,2)
def build_se_part(agf2, eri, gf_occ, gf_vir, os_factor=1.0, ss_factor=1.0): ''' Builds either the auxiliaries of the occupied self-energy, or virtual if :attr:`gf_occ` and :attr:`gf_vir` are swapped. Args: eri : _ChemistsERIs Electronic repulsion integrals gf_occ : GreensFunction Occupied Green's function gf_vir : GreensFunction Virtual Green's function Kwargs: os_factor : float Opposite-spin factor for spin-component-scaled (SCS) calculations. Default 1.0 ss_factor : float Same-spin factor for spin-component-scaled (SCS) calculations. Default 1.0 Returns: :class:`SelfEnergy` ''' cput0 = (time.clock(), time.time()) log = logger.Logger(agf2.stdout, agf2.verbose) assert type(gf_occ) is aux.GreensFunction assert type(gf_vir) is aux.GreensFunction nmo = agf2.nmo nocc = gf_occ.naux nvir = gf_vir.naux naux = nocc * nocc * nvir tol = agf2.weight_tol if not (agf2.frozen is None or agf2.frozen == 0): mask = ragf2.get_frozen_mask(agf2) nmo -= np.sum(~mask) e = np.zeros((naux)) v = np.zeros((nmo, naux)) fpos = np.sqrt(0.5 * os_factor) fneg = np.sqrt(0.5 * os_factor + ss_factor) fdia = np.sqrt(os_factor) eja = lib.direct_sum('j,a->ja', gf_occ.energy, -gf_vir.energy) coeffs = (gf_occ.coupling, gf_occ.coupling, gf_vir.coupling) qeri = _make_qmo_eris_incore(agf2, eri, coeffs) p1 = 0 for i in range(nocc): xija = qeri[:,i,:i].reshape(nmo, -1) xjia = qeri[:,:i,i].reshape(nmo, -1) xiia = qeri[:,i,i].reshape(nmo, -1) eija = gf_occ.energy[i] + eja[:i+1] p0, p1 = p1, p1 + i*nvir e[p0:p1] = eija[:i].ravel() v[:,p0:p1] = fneg * (xija - xjia) p0, p1 = p1, p1 + i*nvir e[p0:p1] = eija[:i].ravel() v[:,p0:p1] = fpos * (xija + xjia) p0, p1 = p1, p1 + nvir e[p0:p1] = eija[i].ravel() v[:,p0:p1] = fdia * xiia se = aux.SelfEnergy(e, v, chempot=gf_occ.chempot) se.remove_uncoupled(tol=tol) if not (agf2.frozen is None or agf2.frozen == 0): coupling = np.zeros((agf2.nmo, se.naux)) coupling[mask] = se.coupling se = aux.SelfEnergy(se.energy, coupling, chempot=se.chempot) log.timer('se part', *cput0) return se