def Srs(mc, dms, eris=None, verbose=None): #Subspace S_rs^{(-2)} mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) dm1 = dms['1'] dm2 = dms['2'] dm3 = dms['3'] ncore = mo_core.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if mo_virt.shape[1] == 0: return 0, 0 if eris is None: h1e = mc.h1e_for_cas()[0] h2e = ao2mo.restore(1, mc.ao2mo(mo_cas), ncas).transpose(0, 2, 1, 3) h2e_v = ao2mo.incore.general(mc._scf._eri, [mo_virt, mo_cas, mo_virt, mo_cas], compact=False) h2e_v = h2e_v.reshape(mo_virt.shape[1], ncas, mo_virt.shape[1], ncas).transpose(0, 2, 1, 3) else: h1e = eris['h1eff'][ncore:nocc, ncore:nocc] h2e = eris['ppaa'][ncore:nocc, ncore:nocc].transpose(0, 2, 1, 3) h2e_v = eris['papa'][nocc:, :, nocc:].transpose(0, 2, 1, 3) # a7 is very sensitive to the accuracy of HF orbital and CI wfn rm2, a7 = make_a7(h1e, h2e, dm1, dm2, dm3) norm = 0.5 * einsum('rsqp,rsba,pqba->rs', h2e_v, h2e_v, rm2) h = 0.5 * einsum('rsqp,rsba,pqab->rs', h2e_v, h2e_v, a7) diff = mc.mo_energy[nocc:, None] + mc.mo_energy[None, nocc:] return _norm_to_energy(norm, h, diff)
def make_a23(h1e, h2e, dm1, dm2, dm3): a23 = -einsum('ip,caib->abcp',h1e,dm2)\ -einsum('pijk,cajbik->abcp',h2e,dm3)\ +2.0*einsum('bp,ca->abcp',h1e,dm1)\ +2.0*einsum('pibk,caik->abcp',h2e,dm2) return a23
def Sijr(mc, dms, eris, verbose=None): #Subspace S_ijr^{(1)} mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) dm1 = dms['1'] dm2 = dms['2'] ncore = mo_core.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if eris is None: h1e = mc.h1e_for_cas()[0] h2e = ao2mo.restore(1, mc.ao2mo(mo_cas), ncas).transpose(0, 2, 1, 3) h2e_v = ao2mo.incore.general(mc._scf._eri, [mo_virt, mo_core, mo_cas, mo_core], compact=False) h2e_v = h2e_v.reshape(mo_virt.shape[1], ncore, ncas, ncore).transpose(0, 2, 1, 3) else: h1e = eris['h1eff'][ncore:nocc, ncore:nocc] h2e = eris['ppaa'][ncore:nocc, ncore:nocc].transpose(0, 2, 1, 3) h2e_v = eris['pacv'][:ncore].transpose(3, 1, 2, 0) if 'h1' in dms: hdm1 = dms['h1'] else: hdm1 = make_hdm1(dm1) a3 = make_a3(h1e, h2e, dm1, dm2, hdm1) norm = 2.0*einsum('rpji,raji,pa->rji',h2e_v,h2e_v,hdm1)\ - 1.0*einsum('rpji,raij,pa->rji',h2e_v,h2e_v,hdm1) h = 2.0*einsum('rpji,raji,pa->rji',h2e_v,h2e_v,a3)\ - 1.0*einsum('rpji,raij,pa->rji',h2e_v,h2e_v,a3) diff = mc.mo_energy[nocc:, None, None] - mc.mo_energy[ None, :ncore, None] - mc.mo_energy[None, None, :ncore] return _norm_to_energy(norm, h, diff)
def Sijrs(mc, eris, verbose=None): mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) ncore = mo_core.shape[1] nvirt = mo_virt.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if eris is None: erifile = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR) feri = ao2mo.outcore.general(mc.mol, (mo_core, mo_virt, mo_core, mo_virt), erifile.name, verbose=mc.verbose) else: feri = eris['cvcv'] eia = mc.mo_energy[:ncore, None] - mc.mo_energy[None, nocc:] norm = 0 e = 0 with ao2mo.load(feri) as cvcv: for i in range(ncore): djba = (eia.reshape(-1, 1) + eia[i].reshape(1, -1)).ravel() gi = numpy.asarray(cvcv[i * nvirt:(i + 1) * nvirt]) gi = gi.reshape(nvirt, ncore, nvirt).transpose(1, 2, 0) t2i = (gi.ravel() / djba).reshape(ncore, nvirt, nvirt) # 2*ijab-ijba theta = gi * 2 - gi.transpose(0, 2, 1) norm += einsum('jab,jab', gi, theta) e += einsum('jab,jab', t2i, theta) return norm, e
def Srsi(mc, dms, eris, verbose=None): #Subspace S_ijr^{(1)} mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) dm1 = dms['1'] dm2 = dms['2'] ncore = mo_core.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if eris is None: h1e = mc.h1e_for_cas()[0] h2e = ao2mo.restore(1, mc.ao2mo(mo_cas), ncas).transpose(0, 2, 1, 3) h2e_v = ao2mo.incore.general(mc._scf._eri, [mo_virt, mo_core, mo_virt, mo_cas], compact=False) h2e_v = h2e_v.reshape(mo_virt.shape[1], ncore, mo_virt.shape[1], ncas).transpose(0, 2, 1, 3) else: h1e = eris['h1eff'][ncore:nocc, ncore:nocc] h2e = eris['ppaa'][ncore:nocc, ncore:nocc].transpose(0, 2, 1, 3) h2e_v = eris['pacv'][nocc:].transpose(3, 0, 2, 1) k27 = make_k27(h1e, h2e, dm1, dm2) norm = 2.0*einsum('rsip,rsia,pa->rsi',h2e_v,h2e_v,dm1)\ - 1.0*einsum('rsip,sria,pa->rsi',h2e_v,h2e_v,dm1) h = 2.0*einsum('rsip,rsia,pa->rsi',h2e_v,h2e_v,k27)\ - 1.0*einsum('rsip,sria,pa->rsi',h2e_v,h2e_v,k27) diff = mc.mo_energy[nocc:, None, None] + mc.mo_energy[ None, nocc:, None] - mc.mo_energy[None, None, :ncore] return _norm_to_energy(norm, h, diff)
def make_a25(h1e, h2e, dm1, dm2): a25 = -einsum('pi,ai->ap',h1e,dm1)\ -einsum('pijk,jaik->ap',h2e,dm2)\ +2.0*einsum('ap->pa',h1e)\ +2.0*einsum('piaj,ij->ap',h2e,dm1) return a25
def Hx(x): x_reshape = np.reshape(x, guessShape) tmp1 = einsum('ijk,nqks->ijnqs', HBlock[0], x_reshape) # Could be 'ijk,mpir->jkmpr' tmp2 = einsum('jlmn,ijnqs->ilmqs', mpo, tmp1) tmp3 = einsum('lopq,ilmqs->imops', mpo, tmp2) finalVec = einsum('ros,imops->mpir', HBlock[1], tmp3) return -finalVec.ravel()
def makeNextGuess(A, S, B, a, maxBondDim=10): a0 = a[1] a1 = min(maxBondDim, a0 * 2) (n1, n2, n3) = A.shape Aguess = np.pad(einsum('ijk,k->ijk', A, S), ((0, 0), (0, a0 - n2), (0, a1 - n3)), 'constant') Bguess = np.pad(B, ((0, 0), (0, a1 - n3), (0, a0 - n2)), 'constant') initGuess = einsum('ijk,lkm->iljm', Aguess, Bguess) return initGuess
def Hx(x): print(x.shape) x_reshape = np.reshape(x,guessShape) tmp1 = einsum('ijk,nqks->ijnqs',LHBlock,x_reshape) # Could be 'ijk,mpir->jkmpr' tmp2 = einsum('jlmn,ijnqs->ilmqs',W[2],tmp1) tmp3 = einsum('lopq,ilmqs->imops',W[2],tmp2) finalVec = einsum('ros,imops->mpir',RHBlock,tmp3) print(finalVec.ravel().shape) return -finalVec.ravel()
def make_a9(h1e, h2e, hdm1, hdm2, hdm3): a9 = einsum('ib,pqai->pqab', h1e, hdm2) a9 += einsum('ijib,pqaj->pqab', h2e, hdm2) * 2.0 a9 -= einsum('ijjb,pqai->pqab', h2e, hdm2) a9 -= einsum('ijkb,pkqaij->pqab', h2e, hdm3) a9 += einsum('ia,pqib->pqab', h1e, hdm2) a9 -= einsum('ijja,pqib->pqab', h2e, hdm2) a9 -= einsum('ijba,pqji->pqab', h2e, hdm2) a9 += einsum('ijia,pqjb->pqab', h2e, hdm2) * 2.0 a9 -= einsum('ijka,pqkjbi->pqab', h2e, hdm3) return a9
def make_hdm3(dm1, dm2, dm3, hdm1, hdm2): delta = numpy.eye(dm3.shape[0]) hdm3 = - einsum('pb,qrac->pqrabc',delta,hdm2)\ - einsum('br,pqac->pqrabc',delta,hdm2)\ + einsum('bq,prac->pqrabc',delta,hdm2)*2.0\ + einsum('ap,bqcr->pqrabc',delta,dm2)*2.0\ - einsum('ap,cr,bq->pqrabc',delta,delta,dm1)*4.0\ + einsum('cr,bqap->pqrabc',delta,dm2)*2.0\ - einsum('bqapcr->pqrabc',dm3)\ + einsum('ar,pc,bq->pqrabc',delta,delta,dm1)*2.0\ - einsum('ar,bqcp->pqrabc',delta,dm2) return hdm3
def make_hdm2(dm1, dm2): delta = numpy.eye(dm2.shape[0]) dm2 = einsum('ikjl->ijkl', dm2) - einsum('jk,il->ijkl', delta, dm1) hdm2 = einsum('klij->ijkl',dm2)\ + einsum('il,kj->ijkl',delta,dm1)\ + einsum('jk,li->ijkl',delta,dm1)\ - 2.0*einsum('ik,lj->ijkl',delta,dm1)\ - 2.0*einsum('jl,ki->ijkl',delta,dm1)\ - 2.0*einsum('il,jk->ijkl',delta,delta)\ + 4.0*einsum('ik,jl->ijkl',delta,delta) return hdm2
def make_a16(h1e, h2e, dms, civec, norb, nelec, link_index=None): dm3 = dms['3'] #dm4 = dms['4'] if 'f3ca' in dms and 'f3ac' in dms: f3ca = dms['f3ca'] f3ac = dms['f3ac'] else: if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec // 2 else: neleca, nelecb = nelec if link_index is None: link_indexa = fci.cistring.gen_linkstr_index(range(norb), neleca) link_indexb = fci.cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index eri = h2e.transpose(0, 2, 1, 3) f3ca = _contract4pdm('NEVPTkern_cedf_aedf', eri, civec, norb, nelec, (link_indexa, link_indexb)) f3ac = _contract4pdm('NEVPTkern_aedf_ecdf', eri, civec, norb, nelec, (link_indexa, link_indexb)) a16 = -einsum('ib,rpqiac->pqrabc', h1e, dm3) a16 += einsum('ia,rpqbic->pqrabc', h1e, dm3) a16 -= einsum('ci,rpqbai->pqrabc', h1e, dm3) # qjkiac = acqjki + delta(ja)qcki + delta(ia)qjkc - delta(qc)ajki - delta(kc)qjai #:a16 -= einsum('kbij,rpqjkiac->pqrabc', h2e, dm4) a16 -= f3ca.transpose(1, 4, 0, 2, 5, 3) # c'a'acb'b -> a'b'c'abc a16 -= einsum('kbia,rpqcki->pqrabc', h2e, dm3) a16 -= einsum('kbaj,rpqjkc->pqrabc', h2e, dm3) a16 += einsum('cbij,rpqjai->pqrabc', h2e, dm3) fdm2 = einsum('kbij,rpajki->prab', h2e, dm3) for i in range(norb): a16[:, i, :, :, :, i] += fdm2 #:a16 += einsum('ijka,rpqbjcik->pqrabc', h2e, dm4) a16 += f3ac.transpose(1, 2, 0, 4, 3, 5) # c'a'b'bac -> a'b'c'abc #:a16 -= einsum('kcij,rpqbajki->pqrabc', h2e, dm4) a16 -= f3ca.transpose(1, 2, 0, 4, 3, 5) # c'a'b'bac -> a'b'c'abc a16 += einsum('jbij,rpqiac->pqrabc', h2e, dm3) a16 -= einsum('cjka,rpqbjk->pqrabc', h2e, dm3) a16 += einsum('jcij,rpqbai->pqrabc', h2e, dm3) return a16
def Sij(mc, dms, eris, verbose=None): #Subspace S_ij^{(-2)} mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) dm1 = dms['1'] dm2 = dms['2'] dm3 = dms['3'] ncore = mo_core.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if mo_core.size == 0: return 0.0, 0 if eris is None: h1e = mc.h1e_for_cas()[0] h2e = ao2mo.restore(1, mc.ao2mo(mo_cas), ncas).transpose(0, 2, 1, 3) h2e_v = ao2mo.incore.general(mc._scf._eri, [mo_cas, mo_core, mo_cas, mo_core], compact=False) h2e_v = h2e_v.reshape(ncas, ncore, ncas, ncore).transpose(0, 2, 1, 3) else: h1e = eris['h1eff'][ncore:nocc, ncore:nocc] h2e = eris['ppaa'][ncore:nocc, ncore:nocc].transpose(0, 2, 1, 3) h2e_v = eris['papa'][:ncore, :, :ncore].transpose(1, 3, 0, 2) if 'h1' in dms: hdm1 = dms['h1'] else: hdm1 = make_hdm1(dm1) if 'h2' in dms: hdm2 = dms['h2'] else: hdm2 = make_hdm2(dm1, dm2) if 'h3' in dms: hdm3 = dms['h3'] else: hdm3 = make_hdm3(dm1, dm2, dm3, hdm1, hdm2) # a9 is very sensitive to the accuracy of HF orbital and CI wfn a9 = make_a9(h1e, h2e, hdm1, hdm2, hdm3) norm = 0.5 * einsum('qpij,baij,pqab->ij', h2e_v, h2e_v, hdm2) h = 0.5 * einsum('qpij,baij,pqab->ij', h2e_v, h2e_v, a9) diff = mc.mo_energy[:ncore, None] + mc.mo_energy[None, :ncore] return _norm_to_energy(norm, h, -diff)
def Si(mc, ci, dms, eris=None, verbose=None): #Subspace S_i^{(1)} mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) dm1 = dms['1'] dm2 = dms['2'] dm3 = dms['3'] #dm4 = dms['4'] ncore = mo_core.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if eris is None: h1e = mc.h1e_for_cas()[0] h2e = ao2mo.restore(1, mc.ao2mo(mo_cas), ncas).transpose(0, 2, 1, 3) h2e_v = ao2mo.incore.general(mc._scf._eri, [mo_cas, mo_core, mo_cas, mo_cas], compact=False) h2e_v = h2e_v.reshape(ncas, ncore, ncas, ncas).transpose(0, 2, 1, 3) core_dm = numpy.dot(mo_core, mo_core.T) * 2 core_vhf = mc.get_veff(mc.mol, core_dm) h1e_v = reduce(numpy.dot, (mo_cas.T, mc.get_hcore() + core_vhf, mo_core)) else: h1e = eris['h1eff'][ncore:nocc, ncore:nocc] h2e = eris['ppaa'][ncore:nocc, ncore:nocc].transpose(0, 2, 1, 3) h2e_v = eris['ppaa'][ncore:nocc, :ncore].transpose(0, 2, 1, 3) h1e_v = eris['h1eff'][ncore:nocc, :ncore] if getattr(mc.fcisolver, 'nevpt_intermediate', None): #mc.fcisolver.make_a22(ncas, state) a22 = mc.fcisolver.nevpt_intermediate('A22', ncas, mc.nelecas, ci) else: a22 = make_a22(h1e, h2e, dms, ci, ncas, mc.nelecas) a23 = make_a23(h1e, h2e, dm1, dm2, dm3) a25 = make_a25(h1e, h2e, dm1, dm2) delta = numpy.eye(ncas) dm3_h = einsum('abef,cd->abcdef',dm2,delta)*2\ - dm3.transpose(0,1,3,2,4,5) dm2_h = einsum('ab,cd->abcd',dm1,delta)*2\ - dm2.transpose(0,1,3,2) dm1_h = 2 * delta - dm1.transpose(1, 0) ener = einsum('qpir,pqrabc,baic->i',h2e_v,a22,h2e_v)\ + einsum('qpir,pqra,ai->i',h2e_v,a23,h1e_v)*2.0\ + einsum('pi,pa,ai->i',h1e_v,a25,h1e_v) norm = einsum('qpir,rpqbac,baic->i',h2e_v,dm3_h,h2e_v)\ + einsum('qpir,rpqa,ai->i',h2e_v,dm2_h,h1e_v)*2.0\ + einsum('pi,pa,ai->i',h1e_v,dm1_h,h1e_v) return _norm_to_energy(norm, ener, -mc.mo_energy[:ncore])
def makeBlocks(mps, mpo=None, block=None, lmps=None): if block is None: if mpo is None: block = [np.array([[1.]]), np.array([[1.]])] else: block = [np.array([[[1.]]]), np.array([[[1.]]])] if lmps is None: lmps = mps if mpo is None: tmp1 = einsum('jl,ijk->ilk', block[0], lmps[0].conj()) block[0] = einsum('ilk,ilm->km', tmp1, mps[0]) tmp1 = einsum('op,nko->nkp', block[1], lmps[1].conj()) block[1] = einsum('nkp,nmp->km', tmp1, mps[1]) else: tmp1 = einsum('ijk,lim->jklm', block[0], lmps[0].conj()) tmp2 = einsum('jklm,jnlo->kmno', tmp1, mpo[0]) block[0] = einsum('kmno,okp->mnp', tmp2, mps[0]) tmp1 = einsum('nop,kmp->kmno', mps[1], block[1]) tmp2 = einsum('kmno,lmin->iklo', tmp1, mpo[1]) block[1] = einsum('iklo,ijk->jlo', tmp2, lmps[1].conj()) return block
def make_a12(h1e, h2e, dm1, dm2, dm3): a12 = einsum('ia,qpib->pqab',h1e,dm2)\ - einsum('bi,qpai->pqab',h1e,dm2)\ + einsum('ijka,qpjbik->pqab',h2e,dm3)\ - einsum('kbij,qpajki->pqab',h2e,dm3)\ - einsum('bjka,qpjk->pqab',h2e,dm2)\ + einsum('jbij,qpai->pqab',h2e,dm2) return a12
def Sr(mc, ci, dms, eris=None, verbose=None): #The subspace S_r^{(-1)} mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) dm1 = dms['1'] dm2 = dms['2'] dm3 = dms['3'] #dm4 = dms['4'] ncore = mo_core.shape[1] nvirt = mo_virt.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if eris is None: h1e = mc.h1e_for_cas()[0] h2e = ao2mo.restore(1, mc.ao2mo(mo_cas), ncas).transpose(0, 2, 1, 3) h2e_v = ao2mo.incore.general(mc._scf._eri, [mo_virt, mo_cas, mo_cas, mo_cas], compact=False) h2e_v = h2e_v.reshape(mo_virt.shape[1], ncas, ncas, ncas).transpose(0, 2, 1, 3) core_dm = numpy.dot(mo_core, mo_core.T) * 2 core_vhf = mc.get_veff(mc.mol, core_dm) h1e_v = reduce(numpy.dot, (mo_virt.T, mc.get_hcore() + core_vhf, mo_cas)) h1e_v -= einsum('mbbn->mn', h2e_v) else: h1e = eris['h1eff'][ncore:nocc, ncore:nocc] h2e = eris['ppaa'][ncore:nocc, ncore:nocc].transpose(0, 2, 1, 3) h2e_v = eris['ppaa'][nocc:, ncore:nocc].transpose(0, 2, 1, 3) h1e_v = eris['h1eff'][nocc:, ncore:nocc] - einsum('mbbn->mn', h2e_v) if getattr(mc.fcisolver, 'nevpt_intermediate', None): a16 = mc.fcisolver.nevpt_intermediate('A16', ncas, mc.nelecas, ci) else: a16 = make_a16(h1e, h2e, dms, ci, ncas, mc.nelecas) a17 = make_a17(h1e, h2e, dm2, dm3) a19 = make_a19(h1e, h2e, dm1, dm2) ener = einsum('ipqr,pqrabc,iabc->i',h2e_v,a16,h2e_v)\ + einsum('ipqr,pqra,ia->i',h2e_v,a17,h1e_v)*2.0\ + einsum('ip,pa,ia->i',h1e_v,a19,h1e_v) norm = einsum('ipqr,rpqbac,iabc->i',h2e_v,dm3,h2e_v)\ + einsum('ipqr,rpqa,ia->i',h2e_v,dm2,h1e_v)*2.0\ + einsum('ip,pa,ia->i',h1e_v,dm1,h1e_v) return _norm_to_energy(norm, ener, mc.mo_energy[nocc:])
def mpo2mat(mpo): N = len(mpo) (_,_,d,_) = mpo[0].shape mat = np.zeros((d**N,d**N)) occ = np.zeros((d**N,N),dtype=int) for i in range(d**N): occ[i,:] = np.asarray(list(map(lambda x: int(x),'0'*(N-len(bin(i)[N:]))+bin(i)[N:]))) for i in range(d**N): i_occ = occ[i,:] for j in range(d**N): j_occ = occ[j,:] tmp_mat = np.array([[1]]) for k in range(N): tmp_mat = einsum('ij,jk->ik',tmp_mat,mpo[k][:,:,i_occ[k],j_occ[k]]) mat[i,j] += tmp_mat[[0]] return mat
def createInitMPS(W, Wl=None, maxBondDim=10, d=2, obsvs=None): left = True if Wl is None: left = False H = mpo2mat([W[0], W[1]]) # Diagonalize Hamiltonian (e0, lwf, rwf) = sortEig(H) # Ensure Proper Normalization # <-|R> = 1 # <L|R> = 1 rwf = rwf / np.sum(rwf) lwf = lwf / np.sum(lwf * rwf) ############################################ # Reshape wavefunction for SVD rpsi = np.reshape(rwf, (2, 2)) lpsi = np.reshape(lwf, (2, 2)) ############################################ # Do SVD of initial unit cell a = [1, min(maxBondDim, d)] (A, S, B) = decompose(rpsi, a) if left: (Al, Sl, Bl) = decompose(lpsi, a) ############################################ # Evaluate Observables if left: obVals = evaluateObservables([A, S, B], [Al, Sl, Bl], obsvs, init=True) else: obVals = evaluateObservables([A, S, B], [A, S, B], obsvs, init=True) ############################################ # Store left and right environments block = makeBlocks([A, B]) hBlock = makeBlocks([A, B], mpo=[W[0], W[1]]) nextGuess = makeNextGuess(A, S, B, a, maxBondDim) E = einsum('ijk,i,k,ijk->', hBlock[0], S, S, hBlock[1]) / einsum( 'ko,k,o,ko->', block[0], S, S, block[1]) if left: blockL = makeBlocks([Al, Bl]) hBlockL = makeBlocks([Al, Bl], mpo=[Wl[0], Wl[1]]) blockLR = makeBlocks([A, B], lmps=[Al, Bl]) hBlockLR = makeBlocks([A, B], lmps=[Al, Bl], mpo=[W[0], W[1]]) nextGuessL = makeNextGuess(Al, Sl, Bl, a, maxBondDim) block = [block, blockL, blockLR] hBlock = [hBlock, hBlockL, hBlockLR] nextGuess = [nextGuess, nextGuessL] El = einsum('ijk,i,k,ijk->', hBlockL[0], Sl, Sl, hBlockL[1]) / einsum( 'ko,k,o,ko->', blockL[0], Sl, Sl, blockL[1]) Elr = einsum('ijk,i,k,ijk->', hBlockLR[0], Sl, S, hBlockLR[1]) / einsum( 'ko,k,o,ko->', blockLR[0], Sl, S, blockLR[1]) return (E, [A, B], block, hBlock, nextGuess)
# Make Initial Unit Cell H = np.zeros((2**2,2**2)) occ = np.zeros((2**2,2),dtype=int) sum_occ = np.zeros(2**2,dtype=int) for i in range(2**2): occ[i,:] = np.asarray(list(map(lambda x: int(x),'0'*(2-len(bin(i)[2:]))+bin(i)[2:]))) #print(occ[i,:]) sum_occ[i] = np.sum(occ[i,:]) # Calculate Hamiltonian for i in range(2**2): i_occ = occ[i,:] for j in range(2**2): j_occ = occ[j,:] tmp_mat0 = np.array([[1]]) for k in range(2): tmp_mat0 = einsum('ij,jk->ik',tmp_mat0,W[k][:,:,i_occ[k],j_occ[k]]) H[i,j] += tmp_mat0[[0]] # Diagonalize Hamiltonian e0,lwf,rwf = la.eig(H,left=True) inds = np.argsort(e0) e0 = e0[inds[-1]] rwf = rwf[:,inds[-1]] lwf = lwf[:,inds[-1]] # Ensure Proper Normalization # <-|R> = 1 # <L|R> = 1 rwf = rwf/np.sum(rwf) lwf = lwf/np.sum(lwf*rwf) print('\nExact Diagonalization Energy: {}'.format(e0)) print('Energy Check {}'.format(einsum('i,ij,j->',lwf.conj(),H,rwf)/einsum('i,i->',lwf.conj(),rwf))) ############################################
def evaluateObservables(state, lstate, obsvs, block=[np.array([[1.]]), np.array([[1.]])], init=False, norm=1.): for ob in obsvs: if ob["useBlock"] == False: if len(ob["mpo"]) == 2: tmp1 = einsum('ik , lim, m->klm ', block[0], lstate[0].conj(), lstate[1].conj()) tmp2 = einsum('klm , jnlo ->kmno', tmp1, ob["mpo"][0]) tmp3 = einsum('kmno, okp, p->mnp ', tmp2, state[0], state[1]) tmp4 = einsum('mnp , qmr ->npqr', tmp3, lstate[2].conj()) tmp5 = einsum('npqr, nsqt ->prt ', tmp4, ob["mpo"][1]) tmp6 = einsum('prt , tpu ->ru ', tmp5, state[2]) ob["val"] = einsum('ru , ru -> ', tmp6, block[1]) / norm else: ob["val"] = [None] * 2 tmp1 = einsum('ik , lim, m->klm ', block[0], lstate[0].conj(), lstate[1].conj()) tmp2 = einsum('klm , jnlo ->kmo ', tmp1, ob["mpo"]) tmp3 = einsum('kmo , okp, p->mp ', tmp2, state[0], state[1]) tmp4 = einsum('mp , qmr ->pqr ', tmp3, lstate[2].conj()) tmp5 = einsum('pqr , qpu ->ru ', tmp4, state[2]) ob["val"][0] = einsum('ru , ru -> ', tmp5, block[1]) / norm tmp1 = einsum('ik , lim, m->klm ', block[0], lstate[0].conj(), lstate[1].conj()) tmp2 = einsum('klm , lkn, n->mn ', tmp1, state[0], state[1]) tmp3 = einsum('mn , omp ->nop ', tmp2, lstate[2].conj()) tmp4 = einsum('nop , qros ->psn ', tmp3, ob["mpo"]) tmp5 = einsum('psn , snt ->pt ', tmp4, state[2]) ob["val"][1] = einsum('pt,pt->', tmp5, block[1]) / norm else: # Select correct site operators if init: mpo = [ob["mpo"][0], ob["mpo"][1]] newBlock = makeBlocks([state[0], state[2]], mpo, block=None, lmps=[lstate[0], lstate[2]]) else: mpo = [ob["mpo"][2], ob["mpo"][2]] newBlock = makeBlocks([state[0], state[2]], mpo, block=ob["block"], lmps=[lstate[0], lstate[2]]) ob["block"][0] = newBlock[0] ob["block"][1] = newBlock[1] # Evaluate Operator ob["val"] = einsum('ijk,ijk,i,k', ob["block"][0], ob["block"][1], state[1], lstate[1]) / norm
def runOptLR(mps, mpo, block, hBlock, nextGuess, E_init=0, maxBondDim=10, minIter=10, maxIter=10000, tol=1e-10, plotConv=True, d=2, obsvs=None, updateFunc=None): if VERBOSE > 3: print('Running LR Optimization Scheme') # Extract Inputs mps, mpsl = mps[0], mps[1] mpo, mpol = mpo[0], mpo[1] blockL = block[1] blockLR = block[2] block = block[0] hBlockL = hBlock[1] hBlockLR = hBlock[2] hBlock = hBlock[0] nextGuessL = nextGuess[1] nextGuess = nextGuess[0] # Make a function that can update stuff if updateFunc is not None: passVars = (mps, mpsl, mpo, mpol, blockL, blockLR, block, hBlockL, hBlockLR, hBlock, nextGuessL, nextGuess, obsvs) returnVars = updateFunc(passVars) mps = returnVars[0] mpsl = returnVars[1] mpo = returnVars[2] mpol = returnVars[3] blockL = returnVars[4] blockLR = returnVars[5] block = returnVars[6] hBlockL = returnVars[7] hBlockLR = returnVars[8] hBlock = returnVars[9] nextGuessL = returnVars[10] nextGuess = returnVars[11] obsvs = returnVars[12] # Set up Iterative Loop Parameters fig = initializePlot(plotConv) converged = False iterCnt = 0 nBond = 1 E_prev = E_init a = [1, min(maxBondDim, d)] # Keep Track of bond dimensions Evec = [E_init] EEvec = [0.] nBondVec = [1] while not converged: nBond += 2 a[0] = a[1] a[1] = min(maxBondDim, a[0] * 2) # ------------------------------------------------------------------------------ # Run Eigensolver H = setupEigenProb(mpo, hBlock, nextGuess) E, v = runEigenSolver(H) E /= nBond Hl = setupEigenProb(mpol, hBlockL, nextGuessL) El, vl = runEigenSolver(Hl) El /= nBond v, vl = normEigVecs(v, vl) # ------------------------------------------------------------------------------ # Reshape result into state (_, _, n1, _) = mpo.shape (_, _, n2, _) = mpo.shape (n3, _, _) = hBlock[0].shape (n4, _, _) = hBlock[1].shape psi = np.reshape(v, (n1, n2, n3, n4)) # s_l s_(l+1) a_(l-1) a_(l+1) psi = np.transpose(psi, (2, 0, 1, 3)) # a_(l-1) s_l a_(l+1) s_(l+1) psi = np.reshape(psi, (n3 * n1, n4 * n2)) lpsi = np.reshape(vl, (n1, n2, n3, n4)) lpsi = np.transpose(lpsi, (2, 0, 1, 3)) lpsi = np.reshape(lpsi, (n3 * n1, n4 * n2)) # ------------------------------------------------------------------------------ # Perform USV Decomposition (A, S, B) = decompose(psi, a) mps = [A, B] EE, _ = calcEntanglement(S) (Al, Sl, Bl) = decompose(lpsi, a) mpsl = [Al, Bl] ############################################ # Evaluate Observables obVals = evaluateObservables([A, S, B], [Al, Sl, Bl], block=blockLR, obsvs=obsvs) # ----------------------------------------------------------------------------- # Store left and right environments block = makeBlocks(mps, block=block) hBlock = makeBlocks(mps, mpo=[mpo, mpo], block=hBlock) blockL = makeBlocks(mpsl, block=blockL) hBlockL = makeBlocks(mpsl, mpo=[mpol, mpol], block=hBlockL) blockLR = makeBlocks(mps, lmps=mpsl, block=blockLR) hBlockLR = makeBlocks(mps, lmps=mpsl, mpo=[mpo, mpo], block=hBlockLR) E = einsum('ijk,i,k,ijk->', hBlock[0], S, S, hBlock[1]) / einsum( 'ko,k,o,ko->', block[0], S, S, block[1]) / nBond El = einsum('ijk,i,k,ijk->', hBlockL[0], Sl, Sl, hBlockL[1]) / einsum( 'ko,k,o,ko->', blockL[0], Sl, Sl, blockL[1]) / nBond Elr = einsum('ijk,i,k,ijk->', hBlockLR[0], S, Sl, hBlockLR[1]) / einsum( 'ko,k,o,ko->', blockLR[0], S, Sl, blockLR[1]) / nBond obsvs = normalizeObservables( obsvs, einsum('ko,k,o,ko->', blockLR[0], S, Sl, blockLR[1])) # ----------------------------------------------------------------------------- # Make next Initial Guess nextGuess = makeNextGuess(A, S, B, a, maxBondDim) nextGuessL = makeNextGuess(Al, Sl, Bl, a, maxBondDim) # ------------------------------------------------------------------------------ # Check for convergence if VERBOSE > 2: print( '\tEnergy from Optimization = {},{},{}\tvonNeumann Entropy = {}' .format(E, El, Elr, EE)) if (np.abs(E - E_prev) < tol) and (iterCnt > minIter): converged = True if VERBOSE > 1: print('System Converged {} {}'.format(E, E_prev)) elif iterCnt == maxIter: converged = True if VERBOSE > 1: print('Convergence not acheived') else: E_prev = E iterCnt += 1 Evec.append(E) EEvec.append(EE) nBondVec.append(nBond) updatePlot(plotConv, fig, Evec, nBondVec) if updateFunc is not None: passVars = (mps, mpsl, mpo, mpol, blockL, blockLR, block, hBlockL, hBlockLR, hBlock, nextGuessL, nextGuess, obsvs) returnVars = updateFunc(passVars) mps = returnVars[0] mpsl = returnVars[1] mpo = returnVars[2] mpol = returnVars[3] blockL = returnVars[4] blockLR = returnVars[5] block = returnVars[6] hBlockL = returnVars[7] hBlockLR = returnVars[8] hBlock = returnVars[9] nextGuessL = returnVars[10] nextGuess = returnVars[11] obsvs = returnVars[12] return Evec, EEvec, obsvs
def make_k27(h1e, h2e, dm1, dm2): k27 = -einsum('ai,pi->pa',h1e,dm1)\ -einsum('iajk,pkij->pa',h2e,dm2)\ +einsum('iaji,pj->pa',h2e,dm1) return k27
def setupEigenProbSlow(HBlock, mpo): # PH - Do for left Eigenvec H = einsum('ijk,jlmn,lopq,ros->mpirnqks', HBlock[0], mpo, mpo, HBlock[1]) (n1, n2, n3, n4, n5, n6, n7, n8) = H.shape H = np.reshape(H, (n1 * n2 * n3 * n4, n5 * n6 * n7 * n8)) return H
def make_a7(h1e, h2e, dm1, dm2, dm3): #This dm2 and dm3 need to be in the form of norm order delta = numpy.eye(dm2.shape[0]) # a^+_ia^+_ja_ka^l = E^i_lE^j_k -\delta_{j,l} E^i_k rm2 = einsum('iljk->ijkl', dm2) - einsum('ik,jl->ijkl', dm1, delta) # E^{i,j,k}_{l,m,n} = E^{i,j}_{m,n}E^k_l -\delta_{k,m}E^{i,j}_{l,n}- \delta_{k,n}E^{i,j}_{m,l} # = E^i_nE^j_mE^k_l -\delta_{j,n}E^i_mE^k_l -\delta_{k,m}E^{i,j}_{l,n} -\delta_{k,n}E^{i,j}_{m,l} rm3 = einsum('injmkl->ijklmn',dm3)\ - einsum('jn,imkl->ijklmn',delta,dm2)\ - einsum('km,ijln->ijklmn',delta,rm2)\ - einsum('kn,ijml->ijklmn',delta,rm2) a7 = -einsum('bi,pqia->pqab',h1e,rm2)\ -einsum('ai,pqbi->pqab',h1e,rm2)\ -einsum('kbij,pqkija->pqab',h2e,rm3) \ -einsum('kaij,pqkibj->pqab',h2e,rm3) \ -einsum('baij,pqij->pqab',h2e,rm2) return rm2, a7
def make_a22(h1e, h2e, dms, civec, norb, nelec, link_index=None): dm2 = dms['2'] dm3 = dms['3'] #dm4 = dms['4'] if 'f3ca' in dms and 'f3ac' in dms: f3ca = dms['f3ca'] f3ac = dms['f3ac'] else: if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec // 2 else: neleca, nelecb = nelec if link_index is None: link_indexa = fci.cistring.gen_linkstr_index(range(norb), neleca) link_indexb = fci.cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index eri = h2e.transpose(0, 2, 1, 3) f3ca = _contract4pdm('NEVPTkern_cedf_aedf', eri, civec, norb, nelec, (link_indexa, link_indexb)) f3ac = _contract4pdm('NEVPTkern_aedf_ecdf', eri, civec, norb, nelec, (link_indexa, link_indexb)) a22 = -einsum('pb,kipjac->ijkabc', h1e, dm3) a22 -= einsum('pa,kibjpc->ijkabc', h1e, dm3) a22 += einsum('cp,kibjap->ijkabc', h1e, dm3) a22 += einsum('cqra,kibjqr->ijkabc', h2e, dm3) a22 -= einsum('qcpq,kibjap->ijkabc', h2e, dm3) # qjprac = acqjpr + delta(ja)qcpr + delta(ra)qjpc - delta(qc)ajpr - delta(pc)qjar #a22 -= einsum('pqrb,kiqjprac->ijkabc', h2e, dm4) a22 -= f3ac.transpose(1, 5, 0, 2, 4, 3) # c'a'acbb' fdm2 = einsum('pqrb,kiqcpr->ikbc', h2e, dm3) for i in range(norb): a22[:, i, :, i, :, :] -= fdm2 a22 -= einsum('pqab,kiqjpc->ijkabc', h2e, dm3) a22 += einsum('pcrb,kiajpr->ijkabc', h2e, dm3) a22 += einsum('cqrb,kiqjar->ijkabc', h2e, dm3) #a22 -= einsum('pqra,kibjqcpr->ijkabc', h2e, dm4) a22 -= f3ac.transpose(1, 3, 0, 4, 2, 5) # c'a'bb'ac -> a'b'c'abc #a22 += einsum('rcpq,kibjaqrp->ijkabc', h2e, dm4) a22 += f3ca.transpose(1, 3, 0, 4, 2, 5) # c'a'bb'ac -> a'b'c'abc a22 += 2.0 * einsum('jb,kiac->ijkabc', h1e, dm2) a22 += 2.0 * einsum('pjrb,kiprac->ijkabc', h2e, dm3) fdm2 = einsum('pa,kipc->ikac', h1e, dm2) fdm2 -= einsum('cp,kiap->ikac', h1e, dm2) fdm2 -= einsum('cqra,kiqr->ikac', h2e, dm2) fdm2 += einsum('qcpq,kiap->ikac', h2e, dm2) fdm2 += einsum('pqra,kiqcpr->ikac', h2e, dm3) fdm2 -= einsum('rcpq,kiaqrp->ikac', h2e, dm3) for i in range(norb): a22[:, i, :, :, i, :] += fdm2 * 2 return a22
def fciqmc(self, dirname='.'): if isinstance(self.verbose, logger.Logger): log = self.verbose else: log = logger.Logger(self.stdout, self.verbose) time0 = (time.clock(), time.time()) print('Reading FCIQMC 1, 2, 3 RDMs...') dm1, dm2, dm3 = fciqmcscf.stochastic_mrpt.read_rdms_fciqmc( self.ncas, self.nelecas, dirname=dirname) dms = {'1': dm1, '2': dm2, '3': dm3} print('FCIQMC 1, 2, 3 RDMs read successfully.') if (not self.canonicalized): self.mo_coeff, _, self.mo_energy = self.canonicalize( self.mo_coeff, ci=None, verbose=self.verbose, casdm1=dm1) ncore = self.ncore ncas = self.ncas nocc = ncore + ncas assert dm1.shape[0] == ncas time1 = log.timer('3pdm, 4pdm', *time0) eris = _ERIS(self, self.mo_coeff) time1 = log.timer('integral transformation', *time1) aaaa = eris['ppaa'][ncore:nocc, ncore:nocc].copy() try: print('Reading FCIQMC NEVPT2 intermediate...') f3ac, f3ca = fciqmcscf.stochastic_mrpt.full_nevpt2_intermediates_fciqmc( dm1, dm2, dm3, self.ncas, aaaa.transpose(0, 2, 1, 3), dirname=dirname) print('FCIQMC NEVPT2 intermediates read successfully.') except IOError: print('FCIQMC NEVPT2 intermediate not found, reading 4RDM') dm4 = fciqmcscf.stochastic_mrpt.read_neci_pdm_mrpt( 'spinfree_FourRDM.1', self.ncas) print('Computing low-rank part of FCIQMC NEVPT2 intermediate...') f3ac, f3ca = fciqmcscf.stochastic_mrpt.calc_lower_rank_part_of_intermediates( dms['1'], dms['2'], dms['3'], aaaa.transpose(0, 2, 1, 3)) print('Adding rank-4 part of the NEVPT2 intermediate...') f3ac += einsum('pqra,kibjqcpr->ijkabc', aaaa.transpose(0, 2, 1, 3), dm4).transpose(2, 0, 4, 1, 3, 5) f3ca += einsum('rcpq,kibjaqrp->ijkabc', aaaa.transpose(0, 2, 1, 3), dm4).transpose(2, 0, 4, 1, 3, 5) print('complete') # the dms are all normal ordered, so switch to product-of-single-excitation ordering print('Reordering FCIQMC RDMs from NORD to POSE...') fciqmcscf.stochastic_mrpt.unreorder_dm123(dms['1'], dms['2'], dms['3'], inplace=True) print('complete') dms['f3ca'] = f3ca dms['f3ac'] = f3ac time1 = log.timer('eri-4pdm contraction', *time1) norm_Sr, e_Sr = Sr(self, None, dms, eris) logger.note(self, "Sr (-1)', E = %.14f", e_Sr) time1 = log.timer("space Sr (-1)'", *time1) norm_Si, e_Si = Si(self, None, dms, eris) logger.note(self, "Si (+1)', E = %.14f", e_Si) time1 = log.timer("space Si (+1)'", *time1) norm_Sijrs, e_Sijrs = Sijrs(self, eris) logger.note(self, "Sijrs (0) , E = %.14f", e_Sijrs) time1 = log.timer('space Sijrs (0)', *time1) norm_Sijr, e_Sijr = Sijr(self, dms, eris) logger.note(self, "Sijr (+1) , E = %.14f", e_Sijr) time1 = log.timer('space Sijr (+1)', *time1) norm_Srsi, e_Srsi = Srsi(self, dms, eris) logger.note(self, "Srsi (-1) , E = %.14f", e_Srsi) time1 = log.timer('space Srsi (-1)', *time1) norm_Srs, e_Srs = Srs(self, dms, eris) logger.note(self, "Srs (-2) , E = %.14f", e_Srs) time1 = log.timer('space Srs (-2)', *time1) norm_Sij, e_Sij = Sij(self, dms, eris) logger.note(self, "Sij (+2) , E = %.14f", e_Sij) time1 = log.timer('space Sij (+2)', *time1) norm_Sir, e_Sir = Sir(self, dms, eris) logger.note(self, "Sir (0)' , E = %.14f", e_Sir) time1 = log.timer("space Sir (0)'", *time1) nevpt_e = e_Sr + e_Si + e_Sijrs + e_Sijr + e_Srsi + e_Srs + e_Sij + e_Sir logger.note(self, "Nevpt2 Energy = %.15f", nevpt_e) log.timer('SC-NEVPT2', *time0) self.e_corr = nevpt_e return nevpt_e
def Sir(mc, dms, eris, verbose=None): #Subspace S_il^{(0)} mo_core, mo_cas, mo_virt = _extract_orbs(mc, mc.mo_coeff) dm1 = dms['1'] dm2 = dms['2'] dm3 = dms['3'] ncore = mo_core.shape[1] ncas = mo_cas.shape[1] nocc = ncore + ncas if eris is None: h1e = mc.h1e_for_cas()[0] h2e = ao2mo.restore(1, mc.ao2mo(mo_cas), ncas).transpose(0, 2, 1, 3) h2e_v1 = ao2mo.incore.general(mc._scf._eri, [mo_virt, mo_core, mo_cas, mo_cas], compact=False) h2e_v1 = h2e_v1.reshape(mo_virt.shape[1], ncore, ncas, ncas).transpose(0, 2, 1, 3) h2e_v2 = ao2mo.incore.general(mc._scf._eri, [mo_virt, mo_cas, mo_cas, mo_core], compact=False) h2e_v2 = h2e_v2.reshape(mo_virt.shape[1], ncas, ncas, ncore).transpose(0, 2, 1, 3) core_dm = numpy.dot(mo_core, mo_core.T) * 2 else: h1e = eris['h1eff'][ncore:nocc, ncore:nocc] h2e = eris['ppaa'][ncore:nocc, ncore:nocc].transpose(0, 2, 1, 3) h2e_v1 = eris['ppaa'][nocc:, :ncore].transpose(0, 2, 1, 3) h2e_v2 = eris['papa'][nocc:, :, :ncore].transpose(0, 3, 1, 2) h1e_v = eris['h1eff'][nocc:, :ncore] norm = einsum('rpiq,raib,qpab->ir',h2e_v1,h2e_v1,dm2)*2.0\ - einsum('rpiq,rabi,qpab->ir',h2e_v1,h2e_v2,dm2)\ - einsum('rpqi,raib,qpab->ir',h2e_v2,h2e_v1,dm2)\ + einsum('raqi,rabi,qb->ir',h2e_v2,h2e_v2,dm1)*2.0\ - einsum('rpqi,rabi,qbap->ir',h2e_v2,h2e_v2,dm2)\ + einsum('rpqi,raai,qp->ir',h2e_v2,h2e_v2,dm1)\ + einsum('rpiq,ri,qp->ir',h2e_v1,h1e_v,dm1)*4.0\ - einsum('rpqi,ri,qp->ir',h2e_v2,h1e_v,dm1)*2.0\ + einsum('ri,ri->ir',h1e_v,h1e_v)*2.0 a12 = make_a12(h1e, h2e, dm1, dm2, dm3) a13 = make_a13(h1e, h2e, dm1, dm2, dm3) h = einsum('rpiq,raib,pqab->ir',h2e_v1,h2e_v1,a12)*2.0\ - einsum('rpiq,rabi,pqab->ir',h2e_v1,h2e_v2,a12)\ - einsum('rpqi,raib,pqab->ir',h2e_v2,h2e_v1,a12)\ + einsum('rpqi,rabi,pqab->ir',h2e_v2,h2e_v2,a13) diff = mc.mo_energy[:ncore, None] - mc.mo_energy[None, nocc:] return _norm_to_energy(norm, h, -diff)
def make_a13(h1e, h2e, dm1, dm2, dm3): delta = numpy.eye(dm3.shape[0]) a13 = -einsum('ia,qbip->pqab', h1e, dm2) a13 += einsum('pa,qb->pqab', h1e, dm1) * 2.0 a13 += einsum('bi,qiap->pqab', h1e, dm2) a13 -= einsum('pa,bi,qi->pqab', delta, h1e, dm1) * 2.0 a13 -= einsum('ijka,qbjpik->pqab', h2e, dm3) a13 += einsum('kbij,qjapki->pqab', h2e, dm3) a13 += einsum('blma,qmlp->pqab', h2e, dm2) a13 += einsum('kpma,qbkm->pqab', h2e, dm2) * 2.0 a13 -= einsum('bpma,qm->pqab', h2e, dm1) * 2.0 a13 -= einsum('lbkl,qkap->pqab', h2e, dm2) a13 -= einsum('ap,mbkl,qlmk->pqab', delta, h2e, dm2) * 2.0 a13 += einsum('ap,lbkl,qk->pqab', delta, h2e, dm1) * 2.0 return a13