def make_rdm12e(fcivec, nsite, nelec): '''1-electron and 2-electron density matrices dm_pq = <|p^+ q|> dm_{pqrs} = <|p^+ r^+ q s|> (note 2pdm is ordered in chemist notation) ''' neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) na = cistring.num_strings(nsite, neleca) nb = cistring.num_strings(nsite, nelecb) ci0 = fcivec.reshape(na, nb, -1) rdm1 = numpy.zeros((nsite, nsite)) rdm2 = numpy.zeros((nsite, nsite, nsite, nsite)) for str0 in range(na): t1 = numpy.zeros((nsite, nsite, nb) + ci0.shape[2:]) for a, i, str1, sign in link_indexa[str0]: t1[i, a, :] += sign * ci0[str1, :] for k, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[i, a, k] += sign * ci0[str0, str1] rdm1 += numpy.einsum('mp,ijmp->ij', ci0[str0], t1) # i^+ j|0> => <0|j^+ i, so swap i and j #:rdm2 += numpy.einsum('ijmp,klmp->jikl', t1, t1) tmp = lib.dot(t1.reshape(nsite**2, -1), t1.reshape(nsite**2, -1).T) rdm2 += tmp.reshape((nsite, ) * 4).transpose(1, 0, 2, 3) rdm1, rdm2 = rdm.reorder_rdm(rdm1, rdm2, True) return rdm1, rdm2
def contract_2e(eri, fcivec, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) ci0 = fcivec.reshape(na,nb) t1 = numpy.zeros((norb,norb,na,nb)) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1[a,i,str1] += sign * ci0[str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[a,i,:,str1] += sign * ci0[:,str0] t1 = lib.einsum('bjai,aiAB->bjAB', eri.reshape([norb]*4), t1) fcinew = numpy.zeros_like(ci0) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * t1[a,i,str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:,str1] += sign * t1[a,i,:,str0] return fcinew.reshape(fcivec.shape)
def test_linkstr_index(self): idx1 = cistring.gen_linkstr_index_o0(range(4), 2) idx2 = cistring.gen_linkstr_index(range(4), 2) idx23 = numpy.array([[0, 0, 3, 1], [3, 3, 3, 1], [1, 0, 4, 1], [2, 0, 5, 1], [1, 3, 0, 1], [2, 3, 1, 1],]) self.assertTrue(numpy.all(idx1[:,:,2:] == idx2[:,:,2:])) self.assertTrue(numpy.all(idx23 == idx2[3])) idx1 = cistring.gen_linkstr_index(range(7), 3) idx2 = cistring.reform_linkstr_index(idx1) idx3 = cistring.gen_linkstr_index_trilidx(range(7), 3) idx3[:,:,1] = 0 self.assertTrue(numpy.all(idx2 == idx3)) tab1 = cistring.gen_cre_str_index_o0(range(8), 4) tab2 = cistring.gen_cre_str_index_o1(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab2).max(), 0, 12) tab1 = cistring.gen_des_str_index_o0(range(8), 4) tab2 = cistring.gen_des_str_index_o1(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab2).max(), 0, 12) tab1 = cistring.gen_linkstr_index_o0(range(8), 4) tab2 = cistring.gen_linkstr_index(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab2).sum(), 0, 12) tab3 = cistring.gen_linkstr_index_o1(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab3).sum(), 0, 12)
def make_rdm1_spin1(fname, cibra, ciket, norb, nelec, link_index=None): assert(cibra.flags.c_contiguous) assert(ciket.flags.c_contiguous) if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec//2 else: neleca, nelecb = nelec if link_index is None: link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,norb)) fn = getattr(librdm, fname) fn(rdm1.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) return rdm1
def make_hdiag(t, u, g, hpp, nsite, nelec, nphonon): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) occslista = [tab[:neleca,0] for tab in link_indexa] occslistb = [tab[:nelecb,0] for tab in link_indexb] nelec_tot = neleca + nelecb # electron part cishape = make_shape(nsite, nelec, nphonon) hdiag = numpy.zeros(cishape) for ia, aocc in enumerate(occslista): for ib, bocc in enumerate(occslistb): e1 = t[aocc,aocc].sum() + t[bocc,bocc].sum() e2 = u * nelec_tot hdiag[ia,ib] = e1 + e2 #TODO: electron-phonon part # phonon part for psite_id in range(nsite): for i in range(nphonon+1): slices0 = slices_for(psite_id, nsite, i) hdiag[slices0] += i+1 return hdiag.ravel()
def kernel(self, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, pspace_size=None, orbsym=None, wfnsym=None, **kwargs): if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) e, c = direct_spin1.kernel_ms1(self, h1e, eri, norb, nelec, ci0, (link_indexa, link_indexb), tol, lindep, max_cycle, max_space, nroots, davidson_only, pspace_size, **kwargs) return e, c
def make_dm1234(fname, cibra, ciket, norb, nelec): if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec//2 else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,)*2) rdm2 = numpy.empty((norb,)*4) rdm3 = numpy.empty((norb,)*6) rdm4 = numpy.empty((norb,)*8) librdm.FCIrdm4_drv(ctypes.c_void_p(_ctypes.dlsym(librdm._handle, fname)), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), rdm3.ctypes.data_as(ctypes.c_void_p), rdm4.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) rdm3 = _complete_dm3_(rdm2, rdm3) rdm4 = _complete_dm4_(rdm3, rdm4) return rdm1, rdm2, rdm3, rdm4
def contract_2e(eri, fcivec, norb, nelec, opt=None): '''Compute E_{pq}E_{rs}|CI>''' if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) ci0 = fcivec.reshape(na, nb) t1 = numpy.zeros((norb, norb, na, nb)) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1[a, i, str1] += sign * ci0[str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[a, i, :, str1] += sign * ci0[:, str0] t1 = lib.einsum('bjai,aiAB->bjAB', eri.reshape([norb] * 4), t1) fcinew = numpy.zeros_like(ci0) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * t1[a, i, str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:, str1] += sign * t1[a, i, :, str0] return fcinew.reshape(fcivec.shape)
def contract_2e(eri, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) t1a = numpy.zeros((nsite,nsite)+cishape) t1b = numpy.zeros((nsite,nsite)+cishape) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1a[a,i,str1] += sign * ci0[str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1b[a,i,:,str1] += sign * ci0[:,str0] g2e_aa = ao2mo.restore(1, eri[0], nsite) g2e_ab = ao2mo.restore(1, eri[1], nsite) g2e_bb = ao2mo.restore(1, eri[2], nsite) t2a = numpy.dot(g2e_aa.reshape(nsite**2,-1), t1a.reshape(nsite**2,-1)) t2a+= numpy.dot(g2e_ab.reshape(nsite**2,-1), t1b.reshape(nsite**2,-1)) t2b = numpy.dot(g2e_ab.reshape(nsite**2,-1).T, t1a.reshape(nsite**2,-1)) t2b+= numpy.dot(g2e_bb.reshape(nsite**2,-1), t1b.reshape(nsite**2,-1)) t2a = t2a.reshape((nsite,nsite)+cishape) t2b = t2b.reshape((nsite,nsite)+cishape) fcinew = numpy.zeros(cishape) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * t2a[a,i,str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:,str1] += sign * t2b[a,i,:,str0] return fcinew.reshape(fcivec.shape)
def make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if link_index is None: neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,norb)) rdm2 = numpy.empty((norb,norb,norb,norb)) librdm.FCIrdm12_drv(getattr(librdm, fname), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(symm)) return rdm1, rdm2
def make_rdm12e(fcivec, nsite, nelec): '''1-electron and 2-electron density matrices dm_pq = <|p^+ q|> dm_{pqrs} = <|p^+ r^+ q s|> (note 2pdm is ordered in chemist notation) ''' neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) na = cistring.num_strings(nsite, neleca) nb = cistring.num_strings(nsite, nelecb) ci0 = fcivec.reshape(na,nb,-1) rdm1 = numpy.zeros((nsite,nsite)) rdm2 = numpy.zeros((nsite,nsite,nsite,nsite)) for str0 in range(na): t1 = numpy.zeros((nsite,nsite,nb)+ci0.shape[2:]) for a, i, str1, sign in link_indexa[str0]: t1[i,a,:] += sign * ci0[str1,:] for k, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[i,a,k] += sign * ci0[str0,str1] rdm1 += numpy.einsum('mp,ijmp->ij', ci0[str0], t1) # i^+ j|0> => <0|j^+ i, so swap i and j #:rdm2 += numpy.einsum('ijmp,klmp->jikl', t1, t1) tmp = lib.dot(t1.reshape(nsite**2,-1), t1.reshape(nsite**2,-1).T) rdm2 += tmp.reshape((nsite,)*4).transpose(1,0,2,3) rdm1, rdm2 = rdm.reorder_rdm(rdm1, rdm2, True) return rdm1, rdm2
def make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if link_index is None: neleca, nelecb = _unpack_nelec(nelec) link_indexa = link_indexb = cistring.gen_linkstr_index( range(norb), neleca) if neleca != nelecb: link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] assert (cibra.size == na * nb) assert (ciket.size == na * nb) rdm1 = numpy.empty((norb, norb)) rdm2 = numpy.empty((norb, norb, norb, norb)) librdm.FCIrdm12_drv(getattr(librdm, fname), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(symm)) return rdm1, rdm2
def make_hdiag(h1e, eri, norb, nelec): '''Diagonal Hamiltonian for Davidson preconditioner ''' if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec h1e = numpy.ascontiguousarray(h1e) eri = pyscf.ao2mo.restore(1, eri, norb) link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na = link_indexa.shape[0] nb = link_indexb.shape[0] occslista = numpy.asarray(link_indexa[:, :neleca, 0], order='C') occslistb = numpy.asarray(link_indexb[:, :nelecb, 0], order='C') hdiag = numpy.empty(na * nb) jdiag = numpy.asarray(numpy.einsum('iijj->ij', eri), order='C') kdiag = numpy.asarray(numpy.einsum('ijji->ij', eri), order='C') libfci.FCImake_hdiag_uhf(hdiag.ctypes.data_as(ctypes.c_void_p), h1e.ctypes.data_as(ctypes.c_void_p), h1e.ctypes.data_as(ctypes.c_void_p), jdiag.ctypes.data_as(ctypes.c_void_p), jdiag.ctypes.data_as(ctypes.c_void_p), jdiag.ctypes.data_as(ctypes.c_void_p), kdiag.ctypes.data_as(ctypes.c_void_p), kdiag.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(neleca), ctypes.c_int(nelecb), occslista.ctypes.data_as(ctypes.c_void_p), occslistb.ctypes.data_as(ctypes.c_void_p)) return numpy.asarray(hdiag)
def make_dm123(fname, cibra, ciket, norb, nelec): r'''Spin traced 1, 2 and 3-particle density matrices. .. note:: The 2pdm is :math:`\langle p^\dagger q^\dagger r s\rangle` but is stored as [p,s,q,r]; The 3pdm is :math:`\langle p^\dagger q^\dagger r^\dagger s t u\rangle`, stored as [p,u,q,t,r,s]. ''' cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if isinstance(nelec, (int, numpy.number)): neleca = nelecb = nelec // 2 else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb, ) * 2) rdm2 = numpy.empty((norb, ) * 4) rdm3 = numpy.empty((norb, ) * 6) kernel = _ctypes.dlsym(librdm._handle, fname) librdm.FCIrdm3_drv(ctypes.c_void_p(kernel), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), rdm3.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) rdm3 = _complete_dm3_(rdm2, rdm3) return rdm1, rdm2, rdm3
def contract_2e(eri, fcivec, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) fcivec = fcivec.reshape(na,nb) t1 = numpy.zeros((norb,norb,na,nb)) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1[a,i,str1] += sign * fcivec[str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[a,i,:,str1] += sign * fcivec[:,str0] t1 = numpy.dot(eri.reshape(norb*norb,-1), t1.reshape(norb*norb,-1)) t1 = t1.reshape(norb,norb,na,nb) fcinew = numpy.zeros_like(fcivec) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * t1[a,i,str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:,str1] += sign * t1[a,i,:,str0] return fcinew
def make_dm123(fname, cibra, ciket, norb, nelec): r'''Spin traced 1, 2 and 3-particle density matrices. .. note:: The 2pdm is :math:`\langle p^\dagger q^\dagger s r\rangle` but is stored as [p,r,q,s]; The 3pdm is :math:`\langle p^\dagger q^\dagger r^\dagger u t s\rangle`, stored as [p,s,q,t,r,u]. ''' if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec//2 else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,)*2) rdm2 = numpy.empty((norb,)*4) rdm3 = numpy.empty((norb,)*6) kernel = _ctypes.dlsym(librdm._handle, fname) librdm.FCIrdm3_drv(ctypes.c_void_p(kernel), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), rdm3.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) rdm3 = _complete_dm3_(rdm2, rdm3) return rdm1, rdm2, rdm3
def make_dm123(fname, cibra, ciket, norb, nelec): r'''Spin traced 1, 2 and 3-particle density matrices. .. note:: In this function, 2pdm is :math:`\langle p^\dagger q r^\dagger s\rangle`; 3pdm is :math:`\langle p^\dagger q r^\dagger s t^\dagger u\rangle`. After calling reorder_dm123, the 2pdm and 3pdm are transformed to standard definition: 2pdm = :math:`\langle p^\dagger q^\dagger r s\rangle` but is stored as [p,s,q,r]; 3pdm = :math:`\langle p^\dagger q^\dagger r^\dagger s t u\rangle`, stored as [p,u,q,t,r,s]. ''' cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb, ) * 2) rdm2 = numpy.empty((norb, ) * 4) rdm3 = numpy.empty((norb, ) * 6) librdm.FCIrdm3_drv(getattr(librdm, fname), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), rdm3.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) rdm3 = _complete_dm3_(rdm2, rdm3) return rdm1, rdm2, rdm3
def make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if link_index is None: if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb, norb)) rdm2 = numpy.empty((norb, norb, norb, norb)) librdm.FCIrdm12_drv(getattr(librdm, fname), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(symm)) return rdm1, rdm2
def make_hdiag(h1e, eri, norb, nelec): '''Diagonal Hamiltonian for Davidson preconditioner ''' if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec h1e = numpy.ascontiguousarray(h1e) eri = pyscf.ao2mo.restore(1, eri, norb) link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na = link_indexa.shape[0] nb = link_indexb.shape[0] occslista = numpy.asarray(link_indexa[:,:neleca,0], order='C') occslistb = numpy.asarray(link_indexb[:,:nelecb,0], order='C') hdiag = numpy.empty(na*nb) jdiag = numpy.asarray(numpy.einsum('iijj->ij',eri), order='C') kdiag = numpy.asarray(numpy.einsum('ijji->ij',eri), order='C') libfci.FCImake_hdiag_uhf(hdiag.ctypes.data_as(ctypes.c_void_p), h1e.ctypes.data_as(ctypes.c_void_p), h1e.ctypes.data_as(ctypes.c_void_p), jdiag.ctypes.data_as(ctypes.c_void_p), jdiag.ctypes.data_as(ctypes.c_void_p), jdiag.ctypes.data_as(ctypes.c_void_p), kdiag.ctypes.data_as(ctypes.c_void_p), kdiag.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(neleca), ctypes.c_int(nelecb), occslista.ctypes.data_as(ctypes.c_void_p), occslistb.ctypes.data_as(ctypes.c_void_p)) return numpy.asarray(hdiag)
def make_rdm12e(fcivec, nsite, nelec): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) na = cistring.num_strings(nsite, neleca) nb = cistring.num_strings(nsite, nelecb) ci0 = fcivec.reshape(na,nb,-1) rdm1 = numpy.zeros((nsite,nsite)) rdm2 = numpy.zeros((nsite,nsite,nsite,nsite)) for str0 in range(na): t1 = numpy.zeros((nsite,nsite,nb)+ci0.shape[2:]) for a, i, str1, sign in link_indexa[str0]: t1[i,a,:] += sign * ci0[str1,:] for k, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[i,a,k] += sign * ci0[str0,str1] rdm1 += numpy.einsum('mp,ijmp->ij', ci0[str0], t1) # i^+ j|0> => <0|j^+ i, so swap i and j #:rdm2 += numpy.einsum('ijmp,klmp->jikl', t1, t1) tmp = lib.dot(t1.reshape(nsite**2,-1), t1.reshape(nsite**2,-1).T) rdm2 += tmp.reshape((nsite,)*4).transpose(1,0,2,3) rdm1, rdm2 = pyscf.fci.rdm.reorder_rdm(rdm1, rdm2, True) return rdm1, rdm2
def make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): assert(cibra.flags.c_contiguous) assert(ciket.flags.c_contiguous) if isinstance(nelec, (int, numpy.integer)): neleca = nelecb = nelec//2 else: neleca, nelecb = nelec if link_index is None: link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,norb)) rdm2 = numpy.empty((norb,norb,norb,norb)) fn = _ctypes.dlsym(librdm._handle, fname) librdm.FCIrdm12_drv(ctypes.c_void_p(fn), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(symm)) return rdm1, rdm2
def contract_2e(eri, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) t1a = numpy.zeros((nsite, nsite) + cishape) t1b = numpy.zeros((nsite, nsite) + cishape) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1a[a, i, str1] += sign * ci0[str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1b[a, i, :, str1] += sign * ci0[:, str0] g2e_aa = ao2mo.restore(1, eri[0], nsite) g2e_ab = ao2mo.restore(1, eri[1], nsite) g2e_bb = ao2mo.restore(1, eri[2], nsite) t2a = numpy.dot(g2e_aa.reshape(nsite**2, -1), t1a.reshape(nsite**2, -1)) t2a += numpy.dot(g2e_ab.reshape(nsite**2, -1), t1b.reshape(nsite**2, -1)) t2b = numpy.dot(g2e_ab.reshape(nsite**2, -1).T, t1a.reshape(nsite**2, -1)) t2b += numpy.dot(g2e_bb.reshape(nsite**2, -1), t1b.reshape(nsite**2, -1)) t2a = t2a.reshape((nsite, nsite) + cishape) t2b = t2b.reshape((nsite, nsite) + cishape) fcinew = numpy.zeros(cishape) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * t2a[a, i, str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:, str1] += sign * t2b[a, i, :, str0] return fcinew.reshape(fcivec.shape)
def contract_2e(eri, fcivec, norb, nelec, opt=None): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) ci0 = fcivec.reshape(na, nb) t1 = numpy.zeros((norb, norb, na, nb)) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1[a, i, str1] += sign * ci0[str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[a, i, :, str1] += sign * ci0[:, str0] t1 = numpy.dot(eri.reshape(norb * norb, -1), t1.reshape(norb * norb, -1)) t1 = t1.reshape(norb, norb, na, nb) fcinew = numpy.zeros_like(ci0) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * t1[a, i, str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:, str1] += sign * t1[a, i, :, str0] return fcinew.reshape(fcivec.shape)
def make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if link_index is None: if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,norb)) rdm2 = numpy.empty((norb,norb,norb,norb)) fn = _ctypes.dlsym(librdm._handle, fname) librdm.FCIrdm12_drv(ctypes.c_void_p(fn), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(symm)) return rdm1, rdm2
def test_linkstr_index(self): idx1 = cistring.gen_linkstr_index_o0(range(4), 2) idx2 = cistring.gen_linkstr_index(range(4), 2) idx23 = numpy.array([ [0, 0, 3, 1], [3, 3, 3, 1], [1, 0, 4, 1], [2, 0, 5, 1], [1, 3, 0, 1], [2, 3, 1, 1], ]) self.assertTrue(numpy.all(idx1[:, :, 2:] == idx2[:, :, 2:])) self.assertTrue(numpy.all(idx23 == idx2[3])) idx1 = cistring.gen_linkstr_index(range(7), 3) idx2 = cistring.reform_linkstr_index(idx1) idx3 = cistring.gen_linkstr_index_trilidx(range(7), 3) idx3[:, :, 1] = 0 self.assertTrue(numpy.all(idx2 == idx3)) tab1 = cistring.gen_cre_str_index_o0(range(8), 4) tab2 = cistring.gen_cre_str_index_o1(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab2).max(), 0, 12) tab1 = cistring.gen_des_str_index_o0(range(8), 4) tab2 = cistring.gen_des_str_index_o1(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab2).max(), 0, 12) tab1 = cistring.gen_linkstr_index_o0(range(8), 4) tab2 = cistring.gen_linkstr_index(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab2).sum(), 0, 12) tab3 = cistring.gen_linkstr_index_o1(range(8), 4) self.assertAlmostEqual(abs(tab1 - tab3).sum(), 0, 12)
def make_rdm1_spin1(fname, cibra, ciket, norb, nelec, link_index=None): assert(cibra is not None and ciket is not None) cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if link_index is None: neleca, nelecb = _unpack_nelec(nelec) link_indexa = link_indexb = cistring.gen_linkstr_index(range(norb), neleca) if neleca != nelecb: link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] assert(cibra.size == na*nb) assert(ciket.size == na*nb) rdm1 = numpy.empty((norb,norb)) fn = getattr(librdm, fname) fn(rdm1.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) return rdm1.T
def make_rdm1_spin1(fname, cibra, ciket, norb, nelec, link_index=None): cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if link_index is None: if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,norb)) fn = getattr(librdm, fname) fn(rdm1.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) return rdm1
def gen_linkstr(self, norb, nelec, tril=True, spin=None): if spin is None: spin = self.spin neleca, nelecb = _unpack_nelec(nelec, spin) if tril: link_indexa = cistring.gen_linkstr_index_trilidx(range(norb), neleca) link_indexb = cistring.gen_linkstr_index_trilidx(range(norb), nelecb) else: link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) return link_indexa, link_indexb
def _unpack(norb, nelec, link_index): if link_index is None: if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) return link_indexa, link_indexb else: return link_index
def make_rdm1s(fcivec, norb, nelec, link_index=None): '''Spin searated 1-particle density matrices, (alpha,beta) ''' if link_index is None: neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) link_index = (link_indexa, link_indexb) rdm1a = rdm.make_rdm1_spin1('FCImake_rdm1a', fcivec, fcivec, norb, nelec, link_index) rdm1b = rdm.make_rdm1_spin1('FCImake_rdm1b', fcivec, fcivec, norb, nelec, link_index) return rdm1a, rdm1b
def contract_2e(eri, fcivec, norb, nelec, link_index=None): r'''Contract the 2-electron Hamiltonian with a FCI vector to get a new FCI vector. Note the input arg eri is NOT the 2e hamiltonian matrix, the 2e hamiltonian is .. math:: h2e &= eri_{pq,rs} p^+ q r^+ s \\ &= (pq|rs) p^+ r^+ s q - (pq|rs) \delta_{qr} p^+ s So eri is defined as .. math:: eri_{pq,rs} = (pq|rs) - (1/Nelec) \sum_q (pq|qs) to restore the symmetry between pq and rs, .. math:: eri_{pq,rs} = (pq|rs) - (.5/Nelec) [\sum_q (pq|qs) + \sum_p (pq|rp)] See also :func:`direct_nosym.absorb_h1e` ''' fcivec = numpy.asarray(fcivec, order='C') if link_index is None: if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] assert (fcivec.size == na * nb) ci1 = numpy.empty_like(fcivec) libfci.FCIcontract_2es1(eri.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), ci1.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) return ci1
def contract_2e(eri, fcivec, norb, nelec, link_index=None): r'''Contract the 2-electron Hamiltonian with a FCI vector to get a new FCI vector. Note the input arg eri is NOT the 2e hamiltonian matrix, the 2e hamiltonian is .. math:: h2e &= eri_{pq,rs} p^+ q r^+ s \\ &= (pq|rs) p^+ r^+ s q - (pq|rs) \delta_{qr} p^+ s So eri is defined as .. math:: eri_{pq,rs} = (pq|rs) - (1/Nelec) \sum_q (pq|qs) to restore the symmetry between pq and rs, .. math:: eri_{pq,rs} = (pq|rs) - (.5/Nelec) [\sum_q (pq|qs) + \sum_p (pq|rp)] See also :func:`direct_nosym.absorb_h1e` ''' assert(fcivec.flags.c_contiguous) if link_index is None: if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] fcivec = fcivec.reshape(na,nb) ci1 = numpy.empty_like(fcivec) libfci.FCIcontract_2es1(eri.ctypes.data_as(ctypes.c_void_p), fcivec.ctypes.data_as(ctypes.c_void_p), ci1.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) return ci1
def contract_1e(h1e, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * ci0[str0] * h1e[a,i] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:,str1] += sign * ci0[:,str0] * h1e[a,i] return fcinew.reshape(fcivec.shape)
def contract_1e(h1e, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * ci0[str0] * h1e[a, i] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:, str1] += sign * ci0[:, str0] * h1e[a, i] return fcinew.reshape(fcivec.shape)
def make_rdm1s(fcivec, norb, nelec, link_index=None): if link_index is None: if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) link_index = (link_indexa, link_indexb) rdm1a = rdm.make_rdm1_spin1('FCImake_rdm1a', fcivec, fcivec, norb, nelec, link_index) rdm1b = rdm.make_rdm1_spin1('FCImake_rdm1b', fcivec, fcivec, norb, nelec, link_index) return rdm1a, rdm1b
def make_hdiag(h1e, eri, norb, nelec): if isinstance(nelec, (int, numpy.integer)): neleca = nelec // 2 else: neleca, nelecb = nelec assert neleca == nelecb h1e = numpy.ascontiguousarray(h1e) eri = pyscf.ao2mo.restore(1, eri, norb) link_index = cistring.gen_linkstr_index(range(norb), neleca) na = link_index.shape[0] occslist = link_index[:, :neleca, 0].copy("C") hdiag = numpy.empty((na, na)) jdiag = numpy.einsum("iijj->ij", eri).copy("C") kdiag = numpy.einsum("ijji->ij", eri).copy("C") libfci.FCImake_hdiag( hdiag.ctypes.data_as(ctypes.c_void_p), h1e.ctypes.data_as(ctypes.c_void_p), jdiag.ctypes.data_as(ctypes.c_void_p), kdiag.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(neleca), occslist.ctypes.data_as(ctypes.c_void_p), ) # symmetrize hdiag to reduce numerical error hdiag = pyscf.lib.transpose_sum(hdiag, inplace=True) * 0.5 return hdiag.ravel()
def kernel(self, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, pspace_size=None, orbsym=None, wfnsym=None, **kwargs): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) e, c = direct_spin1.kernel_ms1(self, h1e, eri, norb, nelec, ci0, (link_indexa,link_indexb), tol, lindep, max_cycle, max_space, nroots, davidson_only, pspace_size, **kwargs) return e, c
def make_rdm12_ms0(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): if link_index is None: neleca, nelecb = _unpack_nelec(nelec) assert(neleca == nelecb) link_index = cistring.gen_linkstr_index(range(norb), neleca) link_index = (link_index, link_index) return make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index, symm)
def test_fancy_index(self): norb = 9 nelec = 4 link_index = cistring.gen_linkstr_index(range(norb), nelec) na = link_index.shape[0] ci0 = numpy.random.random(na) t1ref = numpy.zeros((norb, na)) t2ref = numpy.zeros((norb, norb, na)) for str0, tab in enumerate(link_index): for a, i, str1, sign in tab: if a == i: t1ref[i, str1] += ci0[str0] else: t2ref[a, i, str1] += ci0[str0] link1 = link_index[link_index[:, :, 0] == link_index[:, :, 1]].reshape(na, -1, 4) link2 = link_index[link_index[:, :, 0] != link_index[:, :, 1]].reshape( na, -1, 4) t1 = numpy.zeros_like(t1ref) t2 = numpy.zeros_like(t2ref) t1[link1[:, :, 1], link1[:, :, 2]] = ci0[:, None] t2[link2[:, :, 0], link2[:, :, 1], link2[:, :, 2]] = ci0[:, None] self.assertAlmostEqual(abs(t1ref - t1).max(), 0, 12) self.assertAlmostEqual(abs(t2ref - t2).max(), 0, 12)
def make_rdm12_ms0(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): if link_index is None: neleca, nelecb = _unpack_nelec(nelec) assert (neleca == nelecb) link_index = cistring.gen_linkstr_index(range(norb), neleca) link_index = (link_index, link_index) return make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index, symm)
def test_parity(self): strs = cistring.gen_strings4orblist(range(5), 3) links = cistring.gen_linkstr_index(range(5), 3) parity = [] for addr0, link in enumerate(links): parity.append([cistring.parity(strs[addr0], strs[addr1]) for addr1 in link[:,2]]) self.assertEqual(parity, links[:,:,3].tolist())
def make_rdm1s(fcivec, norb, nelec, link_index=None): '''Spin searated 1-particle density matrices, (alpha,beta) ''' if link_index is None: if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) link_index = (link_indexa, link_indexb) rdm1a = rdm.make_rdm1_spin1('FCImake_rdm1a', fcivec, fcivec, norb, nelec, link_index) rdm1b = rdm.make_rdm1_spin1('FCImake_rdm1b', fcivec, fcivec, norb, nelec, link_index) return rdm1a, rdm1b
def make_rdm1s(fcivec, norb, nelec, link_index=None): '''Spin searated 1-particle density matrices, (alpha,beta) ''' if link_index is None: if isinstance(nelec, (int, numpy.number)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) link_index = (link_indexa, link_indexb) rdm1a = rdm.make_rdm1_spin1('FCImake_rdm1a', fcivec, fcivec, norb, nelec, link_index) rdm1b = rdm.make_rdm1_spin1('FCImake_rdm1b', fcivec, fcivec, norb, nelec, link_index) return rdm1a, rdm1b
def test_linkstr_index(self): idx1 = cistring.gen_linkstr_index_o0(range(4), 2) idx2 = cistring.gen_linkstr_index(range(4), 2) idx23 = numpy.array([[0, 0, 3, 1], [3, 3, 3, 1], [1, 0, 4, 1], [2, 0, 5, 1], [1, 3, 0, 1], [2, 3, 1, 1],]) self.assertTrue(numpy.all(idx1[:,:,2:] == idx2[:,:,2:])) self.assertTrue(numpy.all(idx23 == idx2[3])) idx1 = cistring.gen_linkstr_index(range(7), 3) idx2 = cistring.reform_linkstr_index(idx1) idx3 = cistring.gen_linkstr_index_trilidx(range(7), 3) idx3[:,:,1] = 0 self.assertTrue(numpy.all(idx2 == idx3))
def make_dm1234(fname, cibra, ciket, norb, nelec): r'''Spin traced 1, 2, 3 and 4-particle density matrices. .. note:: In this function, 2pdm is :math:`\langle p^\dagger q r^\dagger s\rangle`; 3pdm is :math:`\langle p^\dagger q r^\dagger s t^\dagger u\rangle`; 4pdm is :math:`\langle p^\dagger q r^\dagger s t^\dagger u v^\dagger w\rangle`. After calling reorder_dm1234, the 2pdm and 3pdm and 4pdm are transformed to standard definition: 2pdm = :math:`\langle p^\dagger q^\dagger s r\rangle` but is stored as [p,r,q,s]; 3pdm = :math:`\langle p^\dagger q^\dagger r^\dagger u t s\rangle`, stored as [p,s,q,t,r,u]; 4pdm = :math:`\langle p^\dagger q^\dagger r^\dagger s^dagger w v u t\rangle`, stored as [p,w,q,v,r,u,s,t]. ''' cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if isinstance(nelec, (int, numpy.number)): neleca = nelecb = nelec//2 else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na,nlinka = link_indexa.shape[:2] nb,nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb,)*2) rdm2 = numpy.empty((norb,)*4) rdm3 = numpy.empty((norb,)*6) rdm4 = numpy.empty((norb,)*8) librdm.FCIrdm4_drv(getattr(librdm, fname), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), rdm3.ctypes.data_as(ctypes.c_void_p), rdm4.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) rdm3 = _complete_dm3_(rdm2, rdm3) rdm4 = _complete_dm4_(rdm3, rdm4) return rdm1, rdm2, rdm3, rdm4
def make_dm1234(fname, cibra, ciket, norb, nelec): r'''Spin traced 1, 2, 3 and 4-particle density matrices. .. note:: In this function, 2pdm is :math:`\langle p^\dagger q r^\dagger s\rangle`; 3pdm is :math:`\langle p^\dagger q r^\dagger s t^\dagger u\rangle`; 4pdm is :math:`\langle p^\dagger q r^\dagger s t^\dagger u v^\dagger w\rangle`. After calling reorder_dm1234, the 2pdm and 3pdm and 4pdm are transformed to standard definition: 2pdm = :math:`\langle p^\dagger q^\dagger s r\rangle` but is stored as [p,r,q,s]; 3pdm = :math:`\langle p^\dagger q^\dagger r^\dagger u t s\rangle`, stored as [p,s,q,t,r,u]; 4pdm = :math:`\langle p^\dagger q^\dagger r^\dagger s^dagger w v u t\rangle`, stored as [p,t,q,u,r,v,s,w]. ''' cibra = numpy.asarray(cibra, order='C') ciket = numpy.asarray(ciket, order='C') if isinstance(nelec, (int, numpy.number)): neleca = nelecb = nelec // 2 else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] rdm1 = numpy.empty((norb, ) * 2) rdm2 = numpy.empty((norb, ) * 4) rdm3 = numpy.empty((norb, ) * 6) rdm4 = numpy.empty((norb, ) * 8) librdm.FCIrdm4_drv(getattr(librdm, fname), rdm1.ctypes.data_as(ctypes.c_void_p), rdm2.ctypes.data_as(ctypes.c_void_p), rdm3.ctypes.data_as(ctypes.c_void_p), rdm4.ctypes.data_as(ctypes.c_void_p), cibra.ctypes.data_as(ctypes.c_void_p), ciket.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(na), ctypes.c_int(nb), ctypes.c_int(nlinka), ctypes.c_int(nlinkb), link_indexa.ctypes.data_as(ctypes.c_void_p), link_indexb.ctypes.data_as(ctypes.c_void_p)) rdm3 = _complete_dm3_(rdm2, rdm3) rdm4 = _complete_dm4_(rdm3, rdm4) return rdm1, rdm2, rdm3, rdm4
def contract_1e(h1e, fcivec, nsite, nelec, nphonon): if isinstance(nelec, (int, numpy.number)): nelecb = nelec//2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: fcinew[str1] += sign * ci0[str0] * h1e[a,i] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: fcinew[:,str1] += sign * ci0[:,str0] * h1e[a,i] return fcinew.reshape(fcivec.shape)
def make_rdm12_ms0(fname, cibra, ciket, norb, nelec, link_index=None, symm=0): if link_index is None: if isinstance(nelec, (int, numpy.number)): neleca = nelec // 2 else: neleca, nelecb = nelec assert (neleca == nelecb) link_index = cistring.gen_linkstr_index(range(norb), neleca) link_index = (link_index, link_index) return make_rdm12_spin1(fname, cibra, ciket, norb, nelec, link_index, symm)
def make_rdm1e(fcivec, nsite, nelec): '''1-electron density matrix dm_pq = <|p^+ q|>''' neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(nsite), neleca) link_indexb = cistring.gen_linkstr_index(range(nsite), nelecb) na = cistring.num_strings(nsite, neleca) nb = cistring.num_strings(nsite, nelecb) rdm1 = numpy.zeros((nsite,nsite)) ci0 = fcivec.reshape(na,-1) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: rdm1[a,i] += sign * numpy.dot(ci0[str1],ci0[str0]) ci0 = fcivec.reshape(na,nb,-1) for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: rdm1[a,i] += sign * numpy.einsum('ax,ax->', ci0[:,str1],ci0[:,str0]) return rdm1
def test_parity(self): strs = cistring.gen_strings4orblist(range(5), 3) links = cistring.gen_linkstr_index(range(5), 3) parity = [] for addr0, link in enumerate(links): parity.append([ cistring.parity(strs[addr0], strs[addr1]) for addr1 in link[:, 2] ]) self.assertEqual(parity, links[:, :, 3].tolist())
def contract_2e_complex(g2e, fcivec, norb, nelec, link_index=None): #version of the pyscf subroutine contract_2e which allows for complex orbitals #still assumes real CI coefficients #removed calls to pyscf.ao2mo.restore #other changes from pyscf have been noted #subroutine follows logic of eqs 11.8.13-11.8.15 in helgaker, jorgensen and olsen neleca, nelecb = nelec if link_index is None: link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) else: link_indexa, link_indexb = link_index na = link_indexa.shape[0] nb = link_indexb.shape[0] fcivec = fcivec.reshape(na,nb) t1 = numpy.zeros((norb,norb,na,nb)) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1[a,i,str1] += sign * fcivec[str0] for k in range(na): for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[a,i,k,str1] += sign * fcivec[k,str0] #following line assumes the symmetry that g[p,q,r,s]=g[r,s,p,q] in chemists notation #this symmetry holds for real and complex orbitals t1 = numpy.dot(g2e.reshape(norb*norb,-1), t1.reshape(norb*norb,-1)) t1 = t1.reshape(norb,norb,na,nb) ci1 = numpy.zeros_like(fcivec, dtype=complex) #data type of ci1 is now complex for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: ci1[str0] += sign * t1[i,a,str1] #indices a and i have been switched from pyscf for k in range(na): for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: ci1[k,str0] += sign * t1[i,a,k,str1] #indices a and i have been switched from pyscf return ci1
def make_rdm1s(fcivec, norb, nelec, link_index=None): r'''Spin separated 1-particle density matrices. The return values include two density matrices: (alpha,alpha), (beta,beta) dm1[p,q] = <q^\dagger p> The convention is based on McWeeney's book, Eq (5.4.20). The contraction between 1-particle Hamiltonian and rdm1 is E = einsum('pq,qp', h1, rdm1) ''' if link_index is None: neleca, nelecb = _unpack_nelec(nelec) link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) link_index = (link_indexa, link_indexb) rdm1a = rdm.make_rdm1_spin1('FCImake_rdm1a', fcivec, fcivec, norb, nelec, link_index) rdm1b = rdm.make_rdm1_spin1('FCImake_rdm1b', fcivec, fcivec, norb, nelec, link_index) return rdm1a, rdm1b
def contract_1e(f1e, fcivec, norb, nelec): if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb else: neleca, nelecb = nelec link_indexa = cistring.gen_linkstr_index(range(norb), neleca) link_indexb = cistring.gen_linkstr_index(range(norb), nelecb) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) ci0 = fcivec.reshape(na, nb) t1 = numpy.zeros((norb, norb, na, nb)) for str0, tab in enumerate(link_indexa): for a, i, str1, sign in tab: t1[a, i, str1] += sign * ci0[str0] for str0, tab in enumerate(link_indexb): for a, i, str1, sign in tab: t1[a, i, :, str1] += sign * ci0[:, str0] fcinew = numpy.dot(f1e.reshape(-1), t1.reshape(-1, na * nb)) return fcinew.reshape(fcivec.shape)