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_hdiag(t, u, g, hpp, 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) 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 make_hdiag(h1e, eri, norb, nelec): neleca, nelecb = direct_spin1._unpack_nelec(nelec) h1e_a = numpy.ascontiguousarray(h1e[0]) h1e_b = numpy.ascontiguousarray(h1e[1]) g2e_aa = ao2mo.restore(1, eri[0], norb) g2e_ab = ao2mo.restore(1, eri[1], norb) g2e_bb = ao2mo.restore(1, eri[2], norb) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = len(strsa) nb = len(strsb) hdiag = numpy.empty(na*nb) jdiag_aa = numpy.asarray(numpy.einsum('iijj->ij',g2e_aa), order='C') jdiag_ab = numpy.asarray(numpy.einsum('iijj->ij',g2e_ab), order='C') jdiag_bb = numpy.asarray(numpy.einsum('iijj->ij',g2e_bb), order='C') kdiag_aa = numpy.asarray(numpy.einsum('ijji->ij',g2e_aa), order='C') kdiag_bb = numpy.asarray(numpy.einsum('ijji->ij',g2e_bb), order='C') libfci.FCImake_hdiag_uhf(hdiag.ctypes.data_as(ctypes.c_void_p), h1e_a.ctypes.data_as(ctypes.c_void_p), h1e_b.ctypes.data_as(ctypes.c_void_p), jdiag_aa.ctypes.data_as(ctypes.c_void_p), jdiag_ab.ctypes.data_as(ctypes.c_void_p), jdiag_bb.ctypes.data_as(ctypes.c_void_p), kdiag_aa.ctypes.data_as(ctypes.c_void_p), kdiag_bb.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), strsa.ctypes.data_as(ctypes.c_void_p), strsb.ctypes.data_as(ctypes.c_void_p)) return numpy.asarray(hdiag)
def pspace(h1e, eri, norb, nelec, hdiag, np=400): neleca, nelecb = direct_spin1._unpack_nelec(nelec) h1e_a = numpy.ascontiguousarray(h1e[0]) h1e_b = numpy.ascontiguousarray(h1e[1]) g2e_aa = ao2mo.restore(1, eri[0], norb) g2e_ab = ao2mo.restore(1, eri[1], norb) g2e_bb = ao2mo.restore(1, eri[2], norb) link_indexa = cistring.gen_linkstr_index_trilidx(range(norb), neleca) link_indexb = cistring.gen_linkstr_index_trilidx(range(norb), nelecb) nb = link_indexb.shape[0] addr = numpy.argsort(hdiag)[:np] addra = addr // nb addrb = addr % nb stra = numpy.array([cistring.addr2str(norb,neleca,ia) for ia in addra], dtype=numpy.long) strb = numpy.array([cistring.addr2str(norb,nelecb,ib) for ib in addrb], dtype=numpy.long) np = len(addr) h0 = numpy.zeros((np,np)) libfci.FCIpspace_h0tril_uhf(h0.ctypes.data_as(ctypes.c_void_p), h1e_a.ctypes.data_as(ctypes.c_void_p), h1e_b.ctypes.data_as(ctypes.c_void_p), g2e_aa.ctypes.data_as(ctypes.c_void_p), g2e_ab.ctypes.data_as(ctypes.c_void_p), g2e_bb.ctypes.data_as(ctypes.c_void_p), stra.ctypes.data_as(ctypes.c_void_p), strb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(np)) for i in range(np): h0[i,i] = hdiag[addr[i]] h0 = lib.hermi_triu(h0) return addr, h0
def contract_2e_hubbard(u, fcivec, norb, nelec, opt=None): neleca, nelecb = direct_spin1._unpack_nelec(nelec) u_aa, u_ab, u_bb = u strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) na = cistring.num_strings(norb, neleca) nb = cistring.num_strings(norb, nelecb) fcivec = fcivec.reshape(na,nb) fcinew = numpy.zeros_like(fcivec) if u_aa != 0: # u * n_alpha^+ n_alpha for i in range(norb): maska = (strsa & (1<<i)) > 0 fcinew[maska] += u_aa * fcivec[maska] if u_ab != 0: # u * (n_alpha^+ n_beta + n_beta^+ n_alpha) for i in range(norb): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 fcinew[maska[:,None]&maskb] += 2*u_ab * fcivec[maska[:,None]&maskb] if u_bb != 0: # u * n_beta^+ n_beta for i in range(norb): maskb = (strsb & (1<<i)) > 0 fcinew[:,maskb] += u_bb * fcivec[:,maskb] return fcinew
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 _unpack(civec_strs, nelec, ci_strs=None, spin=None): neleca, nelecb = direct_spin1._unpack_nelec(nelec, spin) ci_strs = getattr(civec_strs, '_strs', ci_strs) if ci_strs is not None: strsa, strsb = ci_strs strsa = numpy.asarray(strsa) strsb = numpy.asarray(strsb) ci_strs = (strsa, strsb) return civec_strs, (neleca, nelecb), ci_strs
def _id_wfnsym(cis, norb, nelec, wfnsym): if wfnsym is None: neleca, nelecb = direct_spin1._unpack_nelec(nelec) wfnsym = 0 # Ag, A1 or A for i in cis.orbsym[nelecb:neleca]: wfnsym ^= i elif isinstance(wfnsym, str): wfnsym = symm.irrep_name2id(cis.mol.groupname, wfnsym) % 10 return wfnsym
def make_rdm12(self, civec_strs, norb, nelec, link_index=None, **kwargs): nelec = direct_spin1._unpack_nelec(nelec, self.spin) nelec_tot = sum(nelec) civec_strs = _as_SCIvector_if_not(civec_strs, self._strs) dm2 = make_rdm2(civec_strs, norb, nelec, link_index) if nelec_tot > 1: dm1 = numpy.einsum('iikl->kl', dm2) / (nelec_tot-1) else: dm1 = make_rdm1(civec_strs, norb, nelec, link_index) return dm1, dm2
def make_rdm12s(self, civec_strs, norb, nelec, link_index=None, **kwargs): neleca, nelecb = nelec = direct_spin1._unpack_nelec(nelec, self.spin) civec_strs = _as_SCIvector_if_not(civec_strs, self._strs) dm2aa, dm2ab, dm2bb = make_rdm2s(civec_strs, norb, nelec, link_index) if neleca > 1 and nelecb > 1: dm1a = numpy.einsum('iikl->kl', dm2aa) / (neleca-1) dm1b = numpy.einsum('iikl->kl', dm2bb) / (nelecb-1) else: dm1a, dm1b = make_rdm1s(civec_strs, norb, nelec, link_index) return (dm1a, dm1b), (dm2aa, dm2ab, dm2bb)
def large_ci(self, civec_strs, norb, nelec, tol=.1, return_strs=True): nelec = direct_spin1._unpack_nelec(nelec, self.spin) ci, _, (strsa, strsb) = _unpack(civec_strs, nelec, self._strs) addra, addrb = numpy.where(abs(ci) > tol) if return_strs: strsa = [bin(x) for x in strsa[addra]] strsb = [bin(x) for x in strsb[addrb]] return list(zip(ci[addra,addrb], strsa, strsb)) else: occslsta = cistring._strs2occslst(strsa[addra], norb) occslstb = cistring._strs2occslst(strsb[addrb], norb) return list(zip(ci[addra,addrb], occslsta, occslstb))
def contract_2e_hubbard(u, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) strsa = numpy.asarray(cistring.gen_strings4orblist(range(nsite), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nelecb)) cishape = make_shape(nsite, nelec, nphonon) ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) for i in range(nsite): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 fcinew[maska[:,None]&maskb] += u * ci0[maska[:,None]&maskb] return fcinew.reshape(fcivec.shape)
def kernel_fixed_space(myci, h1e, eri, norb, nelec, ci_strs, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_memory=None, verbose=None, ecore=0, **kwargs): if verbose is None: log = logger.Logger(myci.stdout, myci.verbose) elif isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if myci.verbose >= logger.WARN: myci.check_sanity() nelec = direct_spin1._unpack_nelec(nelec, myci.spin) ci0, nelec, ci_strs = _unpack(ci0, nelec, ci_strs) na = len(ci_strs[0]) nb = len(ci_strs[1]) h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5) h2e = ao2mo.restore(1, h2e, norb) link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) if isinstance(ci0, _SCIvector): if ci0.size == na*nb: ci0 = [ci0.ravel()] else: ci0 = [x.ravel() for x in ci0] else: ci0 = myci.get_init_guess(ci_strs, norb, nelec, nroots, hdiag) def hop(c): hc = myci.contract_2e(h2e, _as_SCIvector(c, ci_strs), norb, nelec, link_index) return hc.reshape(-1) precond = lambda x, e, *args: x/(hdiag-e+1e-4) #e, c = lib.davidson(hop, ci0, precond, tol=myci.conv_tol) e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if nroots > 1: return e+ecore, [_as_SCIvector(ci.reshape(na,nb),ci_strs) for ci in c] else: return e+ecore, _as_SCIvector(c.reshape(na,nb), ci_strs)
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 gen_linkstr(self, norb, nelec, tril=True, spin=None, ci_strs=None): if spin is None: spin = self.spin if ci_strs is None: ci_strs = self._strs neleca, nelecb = direct_spin1._unpack_nelec(nelec, spin) if tril: cd_indexa = cre_des_linkstr_tril(ci_strs[0], norb, neleca) dd_indexa = des_des_linkstr_tril(ci_strs[0], norb, neleca) cd_indexb = cre_des_linkstr_tril(ci_strs[1], norb, nelecb) dd_indexb = des_des_linkstr_tril(ci_strs[1], norb, nelecb) else: cd_indexa = cre_des_linkstr(ci_strs[0], norb, neleca) dd_indexa = des_des_linkstr(ci_strs[0], norb, neleca) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelecb) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelecb) return cd_indexa, dd_indexa, cd_indexb, dd_indexb
def gen_linkstr(self, norb, nelec, tril=True, spin=None, ci_strs=None): if spin is None: spin = self.spin if ci_strs is None: ci_strs = self._strs neleca, nelecb = direct_spin1._unpack_nelec(nelec, spin) if tril: cd_indexa = cre_des_linkstr_tril(ci_strs[0], norb, neleca) dd_indexa = des_des_linkstr_tril(ci_strs[0], norb, neleca) cd_indexb = cre_des_linkstr_tril(ci_strs[1], norb, nelecb) dd_indexb = des_des_linkstr_tril(ci_strs[1], norb, nelecb) else: cd_indexa = cre_des_linkstr(ci_strs[0], norb, neleca) dd_indexa = des_des_linkstr(ci_strs[0], norb, neleca) cd_indexb = cre_des_linkstr(ci_strs[1], norb, nelecb) dd_indexb = des_des_linkstr(ci_strs[1], norb, nelecb) return cd_indexa, dd_indexa, cd_indexb, dd_indexb
def kernel_fixed_space(myci, h1e, eri, norb, nelec, ci_strs, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_memory=None, verbose=None, ecore=0, **kwargs): log = logger.new_logger(myci, verbose) if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if myci.verbose >= logger.WARN: myci.check_sanity() nelec = direct_spin1._unpack_nelec(nelec, myci.spin) ci0, nelec, ci_strs = _unpack(ci0, nelec, ci_strs) na = len(ci_strs[0]) nb = len(ci_strs[1]) h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5) h2e = ao2mo.restore(1, h2e, norb) link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) if isinstance(ci0, _SCIvector): if ci0.size == na*nb: ci0 = [ci0.ravel()] else: ci0 = [x.ravel() for x in ci0] else: ci0 = myci.get_init_guess(ci_strs, norb, nelec, nroots, hdiag) def hop(c): hc = myci.contract_2e(h2e, _as_SCIvector(c, ci_strs), norb, nelec, link_index) return hc.reshape(-1) precond = lambda x, e, *args: x/(hdiag-e+1e-4) #e, c = lib.davidson(hop, ci0, precond, tol=myci.conv_tol) e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if nroots > 1: return e+ecore, [_as_SCIvector(ci.reshape(na,nb),ci_strs) for ci in c] else: return e+ecore, _as_SCIvector(c.reshape(na,nb), ci_strs)
def __init__(self, fcibox, norb, nelec, nroots, idx_root, dtype=np.float64): # I'm not sure I need linkstrl self.linkstrl = fcibox.states_gen_linkstr (norb, nelec, tril=True) self.linkstr = fcibox.states_gen_linkstr (norb, nelec, tril=False) self.fcisolvers = [fcibox.fcisolvers[ix] for ix in idx_root] self.linkstrl = [self.linkstrl[ix] for ix in idx_root] self.linkstr = [self.linkstr[ix] for ix in idx_root] self.norb = norb self.nelec = nelec self.nroots = nroots self.ovlp = np.zeros ((nroots, nroots), dtype=dtype) self.nelec_r = [_unpack_nelec (fcibox._get_nelec (solver, nelec)) for solver in self.fcisolvers] self._h = [[[None for i in range (nroots)] for j in range (nroots)] for s in (0,1)] self._hh = [[[None for i in range (nroots)] for j in range (nroots)] for s in (-1,0,1)] self._phh = [[[None for i in range (nroots)] for j in range (nroots)] for s in (0,1)] self._sm = [[None for i in range (nroots)] for j in range (nroots)] self.dm1 = [[None for i in range (nroots)] for j in range (nroots)] self.dm2 = [[None for i in range (nroots)] for j in range (nroots)]
def contract_2e(eri, fcivec, norb, nelec, link_index=None, orbsym=None, wfnsym=0): if orbsym is None: return direct_spin0.contract_2e(eri, fcivec, norb, nelec, link_index) eri = ao2mo.restore(4, eri, norb) neleca, nelecb = direct_spin1._unpack_nelec(nelec) assert(neleca == nelecb) link_indexa = direct_spin0._unpack(norb, nelec, link_index) na, nlinka = link_indexa.shape[:2] eri_irs, rank_eri, irrep_eri = direct_spin1_symm.reorder_eri(eri, norb, orbsym) totirrep = len(eri_irs) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) aidx, link_indexa = direct_spin1_symm.gen_str_irrep(strsa, orbsym, link_indexa, rank_eri, irrep_eri, totirrep) Tirrep = ctypes.c_void_p*totirrep linka_ptr = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexa]) eri_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in eri_irs]) dimirrep = (ctypes.c_int*totirrep)(*[x.shape[0] for x in eri_irs]) fcivec_shape = fcivec.shape fcivec = fcivec.reshape((na,na), order='C') ci1new = numpy.zeros_like(fcivec) nas = (ctypes.c_int*8)(*[x.size for x in aidx]) ci0 = [] ci1 = [] for ir in range(totirrep): ma, mb = aidx[ir].size, aidx[wfnsym^ir].size ci0.append(numpy.zeros((ma,mb))) ci1.append(numpy.zeros((ma,mb))) if ma > 0 and mb > 0: lib.take_2d(fcivec, aidx[ir], aidx[wfnsym^ir], out=ci0[ir]) ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0]) ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1]) libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs, ctypes.c_int(norb), nas, nas, ctypes.c_int(nlinka), ctypes.c_int(nlinka), linka_ptr, linka_ptr, dimirrep, ctypes.c_int(totirrep), ctypes.c_int(wfnsym)) for ir in range(totirrep): if ci0[ir].size > 0: lib.takebak_2d(ci1new, ci1[ir], aidx[ir], aidx[wfnsym^ir]) return lib.transpose_sum(ci1new, inplace=True).reshape(fcivec_shape)
def check_transformer_cache(self): assert (isinstance(self.smult, (int, np.number))) neleca, nelecb = _unpack_nelec(self.nelec) if isinstance(self.wfnsym, str): wfnsym = symm.irrep_name2id(self.mol.groupname, self.wfnsym) else: wfnsym = self.wfnsym if self.transformer is None: self.transformer = CSFTransformer(self.norb, neleca, nelecb, self.smult, orbsym=self.orbsym, wfnsym=wfnsym) else: self.transformer._update_spin_cache(self.norb, neleca, nelecb, self.smult) self.transformer._update_symm_cache(self.orbsym) self.transformer.wfnsym = wfnsym
def make_ints(las, ci, idx_root): fciboxes = las.fciboxes nfrags = len(fciboxes) nroots = idx_root.size nlas = las.ncas_sub nelelas = [sum(_unpack_nelec(ne)) for ne in las.nelecas_sub] hopping_index, zerop_index, onep_index = lst_hopping_index( fciboxes, nlas, nelelas, idx_root) ints = [] for ifrag in range(nfrags): tdmint = LSTDMint1(fciboxes[ifrag], nlas[ifrag], nelelas[ifrag], nroots, idx_root) t0 = tdmint.kernel(ci[ifrag], hopping_index[ifrag], zerop_index, onep_index) lib.logger.timer( las, 'LAS-state TDM12s fragment {} intermediate crunching'.format( ifrag), *t0) ints.append(tdmint) return hopping_index, ints
def contract_2e(eri, fcivec, norb, nelec, link_index=None, orbsym=None, wfnsym=0): if orbsym is None: return direct_spin0.contract_2e(eri, fcivec, norb, nelec, link_index) eri = ao2mo.restore(4, eri, norb) neleca, nelecb = direct_spin1._unpack_nelec(nelec) assert(neleca == nelecb) link_indexa = direct_spin0._unpack(norb, nelec, link_index) na, nlinka = link_indexa.shape[:2] eri_irs, rank_eri, irrep_eri = direct_spin1_symm.reorder_eri(eri, norb, orbsym) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) aidx, link_indexa = direct_spin1_symm.gen_str_irrep(strsa, orbsym, link_indexa, rank_eri, irrep_eri) Tirrep = ctypes.c_void_p*TOTIRREPS linka_ptr = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexa]) eri_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in eri_irs]) dimirrep = (ctypes.c_int*TOTIRREPS)(*[x.shape[0] for x in eri_irs]) fcivec_shape = fcivec.shape fcivec = fcivec.reshape((na,na), order='C') ci1new = numpy.zeros_like(fcivec) nas = (ctypes.c_int*TOTIRREPS)(*[x.size for x in aidx]) ci0 = [] ci1 = [] for ir in range(TOTIRREPS): ma, mb = aidx[ir].size, aidx[wfnsym^ir].size ci0.append(numpy.zeros((ma,mb))) ci1.append(numpy.zeros((ma,mb))) if ma > 0 and mb > 0: lib.take_2d(fcivec, aidx[ir], aidx[wfnsym^ir], out=ci0[ir]) ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0]) ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1]) libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs, ctypes.c_int(norb), nas, nas, ctypes.c_int(nlinka), ctypes.c_int(nlinka), linka_ptr, linka_ptr, dimirrep, ctypes.c_int(wfnsym)) for ir in range(TOTIRREPS): if ci0[ir].size > 0: lib.takebak_2d(ci1new, ci1[ir], aidx[ir], aidx[wfnsym^ir]) return lib.transpose_sum(ci1new, inplace=True).reshape(fcivec_shape)
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 _guess_nelec_f (fci, norb, nelec, norb_f, h1, h2): # Pick electron distribution by the lowest-energy single determinant nelec = direct_spin1._unpack_nelec (nelec) hdiag = fci.make_hdiag (h1, h2, norb, nelec) ndetb = cistring.num_strings (norb, nelec[1]) addr_dp = np.divmod (np.argmin (hdiag), ndetb) str_dp = [cistring.addr2str (norb, n, c) for n,c in zip (nelec, addr_dp)] nelec_f = [] for n in norb_f: ndet = 2**n c = np.zeros ((ndet, ndet)) det = np.array ([str_dp[0] % ndet, str_dp[1] % ndet], dtype=np.integer) str_dp = [str_dp[0] // ndet, str_dp[1] // ndet] ne = [0,0] for spin in range (2): for iorb in range (n): ne[spin] += int (bool ((det[spin] & (1 << iorb)))) nelec_f.append (ne) return nelec_f
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 ham(las, h1, h2, ci_fr, idx_root, orbsym=None, wfnsym=None): mol = las.mol norb_f = las.ncas_sub nelec_fr = [[ _unpack_nelec(fcibox._get_nelec(solver, nelecas)) for solver, ix in zip(fcibox.fcisolvers, idx_root) if ix ] for fcibox, nelecas in zip(las.fciboxes, las.nelecas_sub)] ci, nelec = ci_outer_product(ci_fr, norb_f, nelec_fr) solver = fci.solver(mol).set(orbsym=orbsym, wfnsym=wfnsym) norb = sum(norb_f) h2eff = solver.absorb_h1e(h1, h2, norb, nelec, 0.5) ham_ci = [solver.contract_2e(h2eff, c, norb, nelec) for c in ci] s2_ci = [contract_ss(c, norb, nelec) for c in ci] ham_eff = np.array([[c.ravel().dot(hc.ravel()) for hc in ham_ci] for c in ci]) s2_eff = np.array([[c.ravel().dot(s2c.ravel()) for s2c in s2_ci] for c in ci]) ovlp_eff = np.array([[bra.ravel().dot(ket.ravel()) for ket in ci] for bra in ci]) return ham_eff, s2_eff, ovlp_eff
def _debug_cispace(xci, label): xci_norm = [np.dot(c.ravel(), c.ravel()) for c in xci] try: xci_ss = self.base.fcisolver.states_spin_square( xci, self.base.ncas, self.base.nelecas)[0] except AttributeError: nelec = sum(_unpack_nelec(self.base.nelecas)) xci_ss = [ spin_square(x, self.base.ncas, ((nelec + m) // 2, (nelec - m) // 2))[0] for x, m in zip(xci, self.spin_states) ] xci_ss = [x / max(y, 1e-8) for x, y in zip(xci_ss, xci_norm)] xci_multip = [np.sqrt(x + .25) - .5 for x in xci_ss] for ix, (norm, ss, multip) in enumerate(zip(xci_norm, xci_ss, xci_multip)): logger.debug( self, ' State {} {} norm = {:.7e} ; <S^2> = {:.7f} ; 2S+1 = {:.7f}' .format(ix, label, norm, ss, multip))
def pspace(h1e, eri, norb, nelec, hdiag=None, np=400): neleca, nelecb = direct_spin1._unpack_nelec(nelec) h1e_a = numpy.ascontiguousarray(h1e[0]) h1e_b = numpy.ascontiguousarray(h1e[1]) g2e_aa = ao2mo.restore(1, eri[0], norb) g2e_ab = ao2mo.restore(1, eri[1], norb) g2e_bb = ao2mo.restore(1, eri[2], norb) link_indexa = cistring.gen_linkstr_index_trilidx(range(norb), neleca) link_indexb = cistring.gen_linkstr_index_trilidx(range(norb), nelecb) nb = link_indexb.shape[0] if hdiag is None: hdiag = make_hdiag(h1e, eri, norb, nelec) if hdiag.size < np: addr = numpy.arange(hdiag.size) else: try: addr = numpy.argpartition(hdiag, np - 1)[:np] except AttributeError: addr = numpy.argsort(hdiag)[:np] addra = addr // nb addrb = addr % nb stra = numpy.array([cistring.addr2str(norb, neleca, ia) for ia in addra], dtype=numpy.long) strb = numpy.array([cistring.addr2str(norb, nelecb, ib) for ib in addrb], dtype=numpy.long) np = len(addr) h0 = numpy.zeros((np, np)) libfci.FCIpspace_h0tril_uhf(h0.ctypes.data_as(ctypes.c_void_p), h1e_a.ctypes.data_as(ctypes.c_void_p), h1e_b.ctypes.data_as(ctypes.c_void_p), g2e_aa.ctypes.data_as(ctypes.c_void_p), g2e_ab.ctypes.data_as(ctypes.c_void_p), g2e_bb.ctypes.data_as(ctypes.c_void_p), stra.ctypes.data_as(ctypes.c_void_p), strb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(np)) for i in range(np): h0[i, i] = hdiag[addr[i]] h0 = lib.hermi_triu(h0) return addr, h0
def las_symm_tuple(las): # This really should be much more modular # Symmetry tuple: neleca, nelecb, irrep statesym = [] s2_states = [] for iroot in range(las.nroots): neleca = 0 nelecb = 0 wfnsym = 0 s = 0 m = [] for fcibox, nelec in zip(las.fciboxes, las.nelecas_sub): solver = fcibox.fcisolvers[iroot] na, nb = _unpack_nelec(fcibox._get_nelec(solver, nelec)) neleca += na nelecb += nb s_frag = (solver.smult - 1) // 2 s += s_frag * (s_frag + 1) m.append((na - nb) // 2) fragsym = getattr(solver, 'wfnsym', 0) or 0 # in case getattr returns "None" if isinstance(fragsym, str): fragsym = symm.irrep_name2id(solver.mol.groupname, fragsym) assert isinstance(fragsym, (int, np.integer)), '{} {}'.format( type(fragsym), fragsym) wfnsym ^= fragsym s += sum([2 * m1 * m2 for m1, m2 in combinations(m, 2)]) s2_states.append(s) statesym.append((neleca, nelecb, wfnsym)) lib.logger.info(las, 'Symmetry analysis of LAS states:') lib.logger.info( las, ' {:2s} {:>16s} {:6s} {:6s} {:6s} {:6s}'.format( 'ix', 'Energy', 'Neleca', 'Nelecb', '<S**2>', 'Wfnsym')) for ix, (e, sy, s2) in enumerate(zip(las.e_states, statesym, s2_states)): neleca, nelecb, wfnsym = sy wfnsym = symm.irrep_id2name(las.mol.groupname, wfnsym) lib.logger.info( las, ' {:2d} {:16.10f} {:6d} {:6d} {:6.3f} {:>6s}'.format( ix, e, neleca, nelecb, s2, wfnsym)) return statesym, np.asarray(s2_states)
def get_dense_heff (psi, x, h, ifrag, nelec=None): uop, norb_f = psi.uop, psi.norb_f xconstr, xcc, xci = psi.unpack (x) uop.set_uniq_amps_(xcc) ci_f = psi.rotate_ci0 (xci) h = psi.constr_h (xconstr, h) ndet = 2**norb_f[ifrag] heff = np.zeros ((ndet,ndet,ndet,ndet), dtype=x.dtype) for ideta, idetb, c in psi.gen_frag_basis (ifrag, ci_f=ci_f, nelec=nelec): psi.log.debug ("dense heff fragment %d: %d,%d / %d,%d", ifrag, ideta, idetb, ndet, ndet) uhuc = uop (c) uhuc = psi.contract_h2 (h, uhuc) uhuc = uop (uhuc, transpose=True) heff[ideta,idetb,:,:] = psi.project_frag (ifrag, uhuc, ci0_f=ci_f) heff = LASUCCEffectiveHamiltonian (heff) if nelec is not None: nelec = _unpack_nelec (nelec) heff, idx = heff.get_number_block (nelec, nelec) return heff, np.squeeze (idx[0]) return heff
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, ecore=0, **kwargs): if nroots is None: nroots = self.nroots if orbsym is not None: self.orbsym, orbsym_bak = orbsym, self.orbsym if wfnsym is None: wfnsym = self.wfnsym if self.verbose >= logger.WARN: self.check_sanity() nelec = direct_spin1._unpack_nelec(nelec, self.spin) wfnsym_bak = self.wfnsym self.wfnsym = self.guess_wfnsym(norb, nelec, ci0, wfnsym, **kwargs) e, c = direct_spin1.kernel_ms1(self, h1e, eri, norb, nelec, ci0, None, tol, lindep, max_cycle, max_space, nroots, davidson_only, pspace_size, ecore=ecore, **kwargs) if orbsym is not None: self.orbsym = orbsym_bak self.wfnsym = wfnsym_bak return e, c
def roots_make_rdm12s(las, ci_fr, idx_root, si, orbsym=None, wfnsym=None): mol = las.mol norb_f = las.ncas_sub nelec_fr = [[ _unpack_nelec(fcibox._get_nelec(solver, nelecas)) for solver, ix in zip(fcibox.fcisolvers, idx_root) if ix ] for fcibox, nelecas in zip(las.fciboxes, las.nelecas_sub)] ci_r, nelec = ci_outer_product(ci_fr, norb_f, nelec_fr) norb = sum(norb_f) solver = fci.solver(mol).set(orbsym=orbsym, wfnsym=wfnsym) nroots = len(ci_r) ci_r = np.tensordot(si.conj().T, np.stack(ci_r, axis=0), axes=1) rdm1s = np.zeros((nroots, 2, norb, norb), dtype=ci_r.dtype) rdm2s = np.zeros((nroots, 2, norb, norb, 2, norb, norb), dtype=ci_r.dtype) for ix, ci in enumerate(ci_r): d1s, d2s = solver.make_rdm12s(ci, norb, nelec) rdm1s[ix, 0, :, :] = d1s[0] rdm1s[ix, 1, :, :] = d1s[1] rdm2s[ix, 0, :, :, 0, :, :] = d2s[0] rdm2s[ix, 0, :, :, 1, :, :] = d2s[1] rdm2s[ix, 1, :, :, 0, :, :] = d2s[1].transpose(2, 3, 0, 1) rdm2s[ix, 1, :, :, 1, :, :] = d2s[2] return rdm1s, rdm2s
def contract_ep(g, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) strsa = numpy.asarray(cistring.gen_strings4orblist(range(nsite), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nelecb)) cishape = make_shape(nsite, nelec, nphonon) na, nb = cishape[:2] ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) phonon_cre = numpy.sqrt(numpy.arange(1,nphonon+1)) for i in range(nsite): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 e_part = numpy.zeros((na,nb)) e_part[maska,:] += 1 e_part[:,maskb] += 1 e_part[:] -= float(neleca+nelecb) / nsite for ip in range(nphonon): slices1 = slices_for_cre(i, nsite, ip) slices0 = slices_for (i, nsite, ip) fcinew[slices1] += numpy.einsum('ij...,ij...->ij...', g*phonon_cre[ip]*e_part, ci0[slices0]) fcinew[slices0] += numpy.einsum('ij...,ij...->ij...', g*phonon_cre[ip]*e_part, ci0[slices1]) return fcinew.reshape(fcivec.shape)
def __init__(self, mc, state=None): self.__dict__.update (mc.__dict__) nmo = mc.mo_coeff.shape[-1] self.ngorb = np.count_nonzero (mc.uniq_var_indices (nmo, mc.ncore, mc.ncas, mc.frozen)) self.nroots = mc.fcisolver.nroots neleca, nelecb = _unpack_nelec (mc.nelecas) self.spin_states = [neleca - nelecb,] * self.nroots self.na_states = [cistring.num_strings (mc.ncas, neleca),] * self.nroots self.nb_states = [cistring.num_strings (mc.ncas, nelecb),] * self.nroots if isinstance (mc.fcisolver, StateAverageMixFCISolver): self.nroots = p0 = 0 for solver in mc.fcisolver.fcisolvers: self.nroots += solver.nroots nea, neb = mc.fcisolver._get_nelec (solver, (neleca, nelecb)) self.spin_states[p0:self.nroots] = (nea - neb for x in range (solver.nroots)) self.na_states[p0:self.nroots] = (cistring.num_strings (mc.ncas, nea) for x in range (solver.nroots)) self.nb_states[p0:self.nroots] = (cistring.num_strings (mc.ncas, neb) for x in range (solver.nroots)) p0 = self.nroots self.nci = sum ([na * nb for na, nb in zip (self.na_states, self.nb_states)]) if state is not None: self.state = state elif hasattr (mc, 'nuc_grad_state'): self.state = mc.nuc_grad_state else: self.state = None self.eris = None self.weights = np.array ([1]) try: self.e_states = np.asarray (mc.e_states) except AttributeError as e: self.e_states = np.asarray (mc.e_tot) if isinstance (mc, StateAverageMCSCFSolver): self.weights = np.asarray (mc.weights) assert (len (self.weights) == self.nroots), '{} {} {}'.format (mc.fcisolver.__class__, self.weights, self.nroots) lagrange.Gradients.__init__(self, mc, self.ngorb+self.nci) self.max_cycle = mc.max_cycle_macro
def make_stdm12s(las, ci_fr, idx_root, orbsym=None, wfnsym=None): mol = las.mol norb_f = las.ncas_sub nelec_fr = [[ _unpack_nelec(fcibox._get_nelec(solver, nelecas)) for solver, ix in zip(fcibox.fcisolvers, idx_root) if ix ] for fcibox, nelecas in zip(las.fciboxes, las.nelecas_sub)] ci_r, nelec = ci_outer_product(ci_fr, norb_f, nelec_fr) norb = sum(norb_f) solver = fci.solver(mol).set(orbsym=orbsym, wfnsym=wfnsym) nroots = len(ci_r) stdm1s = np.zeros((nroots, nroots, 2, norb, norb), dtype=ci_r[0].dtype).transpose(0, 2, 3, 4, 1) stdm2s = np.zeros((nroots, nroots, 2, norb, norb, 2, norb, norb), dtype=ci_r[0].dtype).transpose(0, 2, 3, 4, 5, 6, 7, 1) for i, ci in enumerate(ci_r): rdm1s, rdm2s = solver.make_rdm12s(ci, norb, nelec) stdm1s[i, 0, :, :, i] = rdm1s[0] stdm1s[i, 1, :, :, i] = rdm1s[1] stdm2s[i, 0, :, :, 0, :, :, i] = rdm2s[0] stdm2s[i, 0, :, :, 1, :, :, i] = rdm2s[1] stdm2s[i, 1, :, :, 0, :, :, i] = rdm2s[1].transpose(2, 3, 0, 1) stdm2s[i, 1, :, :, 1, :, :, i] = rdm2s[2] for (i, ci_bra), (j, ci_ket) in combinations(enumerate(ci_r), 2): tdm1s, tdm2s = solver.trans_rdm12s(ci_bra, ci_ket, norb, nelec) # Transpose for 1TDM is backwards because of stupid PySCF convention stdm1s[i, 0, :, :, j] = tdm1s[0].T stdm1s[i, 1, :, :, j] = tdm1s[1].T stdm1s[j, 0, :, :, i] = tdm1s[0] stdm1s[j, 1, :, :, i] = tdm1s[1] for spin, tdm2 in enumerate(tdm2s): p = spin // 2 q = spin % 2 stdm2s[i, p, :, :, q, :, :, j] = tdm2 stdm2s[j, p, :, :, q, :, :, i] = tdm2.transpose(1, 0, 3, 2) return stdm1s, stdm2s
def contract_ep(g, fcivec, nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) strsa = numpy.asarray(cistring.gen_strings4orblist(range(nsite), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(nsite), nelecb)) cishape = make_shape(nsite, nelec, nphonon) na, nb = cishape[:2] ci0 = fcivec.reshape(cishape) fcinew = numpy.zeros(cishape) nbar = float(neleca+nelecb) / nsite phonon_cre = numpy.sqrt(numpy.arange(1,nphonon+1)) for i in range(nsite): maska = (strsa & (1<<i)) > 0 maskb = (strsb & (1<<i)) > 0 e_part = numpy.zeros((na,nb)) e_part[maska,:] += 1 e_part[:,maskb] += 1 e_part[:] -= float(neleca+nelecb) / nsite for ip in range(nphonon): slices1 = slices_for_cre(i, nsite, ip) slices0 = slices_for (i, nsite, ip) fcinew[slices1] += numpy.einsum('ij...,ij...->ij...', g*phonon_cre[ip]*e_part, ci0[slices0]) fcinew[slices0] += numpy.einsum('ij...,ij...->ij...', g*phonon_cre[ip]*e_part, ci0[slices1]) return fcinew.reshape(fcivec.shape)
def kernel(myci, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_memory=None, verbose=None, ecore=0, **kwargs): if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if verbose is None: verbose = logger.Logger(myci.stdout, myci.verbose) tol_residual = None #getattr(fci, 'conv_tol_residual', None) myci.dump_flags() nelec = direct_spin1._unpack_nelec(nelec, myci.spin) eri = ao2mo.restore(1, eri, norb) eri = eri.ravel() logger.info(myci, 'CI in the selected space') # Initial guess if ci0 is None: t_start = time.time() if (myci.model == 'fci'): dets = cistring.gen_full_space(range(norb), nelec) ndets = dets.shape[0] if (myci.noise): numpy.random.seed() ci0 = [cistring.as_SCIvector(numpy.random.uniform(low=1e-3,high=1e-2,size=ndets), dets)] ci0[0][0] = 0.99 ci0[0] *= 1./numpy.linalg.norm(ci0[0]) else: ci0 = [cistring.as_SCIvector(numpy.zeros(ndets), dets)] ci0[0][0] = 1.0 else: raise RuntimeError('''Unknown CI model''') t_current = time.time() - t_start #logger.info(myci, 'Initial CI vector = %s', ci0[0][:]) logger.info(myci, 'Timing for generating strings: %10.3f', t_current) else: assert(nroots == len(ci0)) def hop(c): hc = myci.contract_2e((h1e, eri), cistring.as_SCIvector(c, ci_strs), norb, nelec, hdiag) return hc.ravel() precond = lambda x, e, *args: x/(hdiag-e+myci.level_shift) ci_strs = ci0[0]._strs logger.info(myci, 'Number of CI configurations: %d', ci_strs.shape[0]) t_start = time.time() hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) t_current = time.time() - t_start logger.info(myci, 'Timing for diagonal hamiltonian: %10.3f', t_current) t_start = time.time() with lib.with_omp_threads(myci.threads): #e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, # max_cycle=max_cycle, max_space=max_space, nroots=nroots, # max_memory=max_memory, verbose=verbose, **kwargs) # e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=verbose, follow_state=True, tol_residual=tol_residual, **kwargs) t_current = time.time() - t_start logger.info(myci, 'Timing for solving the eigenvalue problem: %10.3f', t_current) if not isinstance(c, (tuple, list)): c = [c] e = [e] logger.info(myci, 'CI E = %s', numpy.array(e)+ecore) #myci.eci = e+ecore #myci.ci = e #for i in range(nroots): # norm = numpy.einsum('i,i->', ci0[i][:], ci0[i][:]) # s = myci.spin_square(ci0[i], norb, nelec) # logger.info(myci, 'E(CI) = %10.5f, CI E = %10.5f, Norm = %1.3f, Spin = %s'\ # % (numpy.array(e[i]), numpy.array(e[i])+ecore, norm, s)) # #logger.info(myci, 'CI E = %s', numpy.array(e)+ecore) # #logger.info(mc,"* Norm info for state %d : %s" % (i,norm)) # #logger.info(mc,"* Spin info for state %d : %s" % (i,s)) return (numpy.array(e)+ecore), [cistring.as_SCIvector(ci, ci_strs) for ci in c]
def debug_lagrange(self, Lvec, bvec, Aop, Adiag, iroot=None, mo=None, ci=None, **kwargs): if iroot is None: iroot = self.iroot if mo is None: mo = self.base.mo_coeff if ci is None: ci = self.base.ci lib.logger.info( self, '{} gradient: iroot = {}'.format(self.base.__class__.__name__, iroot)) ngorb = self.ngorb nci = self.nci nroots = self.nroots ndet = nci // nroots ncore = self.base.ncore ncas = self.base.ncas nelecas = self.base.nelecas nocc = ncore + ncas nlag = self.nlag ci = np.asarray(self.base.ci).reshape(nroots, -1) err = Aop(Lvec) + bvec eorb = self.base.unpack_uniq_var(err[:ngorb]) eci = err[ngorb:].reshape(nroots, -1) borb = self.base.unpack_uniq_var(bvec[:ngorb]) bci = bvec[ngorb:].reshape(nroots, -1) Lorb = self.base.unpack_uniq_var(Lvec[:ngorb]) Lci = Lvec[ngorb:].reshape(nroots, ndet) Aci = Adiag[ngorb:].reshape(nroots, ndet) Lci_ci_ovlp = ( np.asarray(ci).reshape(nroots, -1).conjugate() @ Lci.T).T Lci_Lci_ovlp = (Lci.conjugate() @ Lci.T).T eci_ci_ovlp = ( np.asarray(ci).reshape(nroots, -1).conjugate() @ eci.T).T bci_ci_ovlp = ( np.asarray(ci).reshape(nroots, -1).conjugate() @ bci.T).T ci_ci_ovlp = ci.conjugate() @ ci.T lib.logger.debug( self, "{} gradient RHS, inactive-active orbital rotations:\n{}".format( self.base.__class__.__name__, borb[:ncore, ncore:nocc])) lib.logger.debug( self, "{} gradient RHS, inactive-external orbital rotations:\n{}".format( self.base.__class__.__name__, borb[:ncore, nocc:])) lib.logger.debug( self, "{} gradient RHS, active-external orbital rotations:\n{}".format( self.base.__class__.__name__, borb[ncore:nocc, nocc:])) lib.logger.debug( self, "{} gradient residual, inactive-active orbital rotations:\n{}". format(self.base.__class__.__name__, eorb[:ncore, ncore:nocc])) lib.logger.debug( self, "{} gradient residual, inactive-external orbital rotations:\n{}". format(self.base.__class__.__name__, eorb[:ncore, nocc:])) lib.logger.debug( self, "{} gradient residual, active-external orbital rotations:\n{}". format(self.base.__class__.__name__, eorb[ncore:nocc, nocc:])) lib.logger.debug( self, "{} gradient Lagrange factor, inactive-active orbital rotations:\n{}" .format(self.base.__class__.__name__, Lorb[:ncore, ncore:nocc])) lib.logger.debug( self, "{} gradient Lagrange factor, inactive-external orbital rotations:\n{}" .format(self.base.__class__.__name__, Lorb[:ncore, nocc:])) lib.logger.debug( self, "{} gradient Lagrange factor, active-external orbital rotations:\n{}" .format(self.base.__class__.__name__, Lorb[ncore:nocc, nocc:])) ''' lib.logger.debug (self, "{} gradient RHS, inactive-inactive orbital rotations (redundant!):\n{}".format ( self.base.__class__.__name__, borb[:ncore,:ncore])) lib.logger.debug (self, "{} gradient RHS, active-active orbital rotations (redundant!):\n{}".format ( self.base.__class__.__name__, borb[ncore:nocc,ncore:nocc])) lib.logger.debug (self, "{} gradient RHS, external-external orbital rotations (redundant!):\n{}".format ( self.base.__class__.__name__, borb[nocc:,nocc:])) lib.logger.debug (self, "{} gradient Lagrange factor, inactive-inactive orbital rotations (redundant!):\n{}".format ( self.base.__class__.__name__, Lorb[:ncore,:ncore])) lib.logger.debug (self, "{} gradient Lagrange factor, active-active orbital rotations (redundant!):\n{}".format ( self.base.__class__.__name__, Lorb[ncore:nocc,ncore:nocc])) lib.logger.debug (self, "{} gradient Lagrange factor, external-external orbital rotations (redundant!):\n{}".format ( self.base.__class__.__name__, Lorb[nocc:,nocc:])) ''' lib.logger.debug( self, "{} gradient Lagrange factor, CI part overlap with true CI SA space:\n{}" .format(self.base.__class__.__name__, Lci_ci_ovlp)) lib.logger.debug( self, "{} gradient Lagrange factor, CI part self overlap matrix:\n{}". format(self.base.__class__.__name__, Lci_Lci_ovlp)) lib.logger.debug( self, "{} gradient Lagrange factor, CI vector self overlap matrix:\n{}". format(self.base.__class__.__name__, ci_ci_ovlp)) lib.logger.debug( self, "{} gradient Lagrange factor, CI part response overlap with SA space:\n{}" .format(self.base.__class__.__name__, bci_ci_ovlp)) lib.logger.debug( self, "{} gradient Lagrange factor, CI part residual overlap with SA space:\n{}" .format(self.base.__class__.__name__, eci_ci_ovlp)) neleca, nelecb = _unpack_nelec(nelecas) spin = neleca - nelecb + 1 csf = CSFTransformer(ncas, neleca, nelecb, spin) ecsf = csf.vec_det2csf(eci, normalize=False, order='C') err_norm_det = linalg.norm(err) err_norm_csf = linalg.norm(np.append(eorb, ecsf.ravel())) lib.logger.debug( self, "{} gradient: determinant residual = {}, CSF residual = {}".format( self.base.__class__.__name__, err_norm_det, err_norm_csf)) ci_lbls, ci_csf = csf.printable_largest_csf(ci, 10, isdet=True, normalize=True, order='C') bci_lbls, bci_csf = csf.printable_largest_csf(bci, 10, isdet=True, normalize=False, order='C') eci_lbls, eci_csf = csf.printable_largest_csf(eci, 10, isdet=True, normalize=False, order='C') Lci_lbls, Lci_csf = csf.printable_largest_csf(Lci, 10, isdet=True, normalize=False, order='C') Aci_lbls, Aci_csf = csf.printable_largest_csf(Aci, 10, isdet=True, normalize=False, order='C') ncsf = bci_csf.shape[1] for iroot in range(self.nroots): lib.logger.debug( self, "{} gradient Lagrange factor, CI part root {} spin square: {}". format(self.base.__class__.__name__, iroot, spin_square0(Lci[iroot], ncas, nelecas))) lib.logger.debug(self, "Base CI vector") for icsf in range(ncsf): lib.logger.debug( self, '{} {}'.format(ci_lbls[iroot, icsf], ci_csf[iroot, icsf])) lib.logger.debug(self, "CI gradient:") for icsf in range(ncsf): lib.logger.debug( self, '{} {}'.format(bci_lbls[iroot, icsf], bci_csf[iroot, icsf])) lib.logger.debug(self, "CI residual:") for icsf in range(ncsf): lib.logger.debug( self, '{} {}'.format(eci_lbls[iroot, icsf], eci_csf[iroot, icsf])) lib.logger.debug(self, "CI Lagrange vector:") for icsf in range(ncsf): lib.logger.debug( self, '{} {}'.format(Lci_lbls[iroot, icsf], Lci_csf[iroot, icsf])) lib.logger.debug(self, "Diagonal of Hessian matrix CI part:") for icsf in range(ncsf): lib.logger.debug( self, '{} {}'.format(Aci_lbls[iroot, icsf], Aci_csf[iroot, icsf])) '''
def kernel(fci, h1e, eri, norb, nelec, smult=None, idx_sym=None, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, pspace_size=None, max_memory=None, orbsym=None, wfnsym=None, ecore=0, transformer=None, **kwargs): t0 = (time.process_time (), time.time ()) if 'verbose' in kwargs: verbose = kwargs['verbose'] kwargs.pop ('verbose') else: verbose = lib.logger.Logger (stdout=fci.stdout, verbose=fci.verbose) if (isinstance (verbose, lib.logger.Logger) and verbose.verbose >= lib.logger.WARN) or (isinstance (verbose, int) and verbose >= lib.logger.WARN): fci.check_sanity() if nroots is None: nroots = fci.nroots if pspace_size is None: pspace_size = fci.pspace_size if davidson_only is None: davidson_only = fci.davidson_only if transformer is None: transformer = fci.transformer nelec = _unpack_nelec(nelec, fci.spin) neleca, nelecb = nelec t0 = lib.logger.timer (fci, "csf.kernel: throat-clearing", *t0) hdiag_det = fci.make_hdiag (h1e, eri, norb, nelec) t0 = lib.logger.timer (fci, "csf.kernel: hdiag_det", *t0) hdiag_csf = fci.make_hdiag_csf (h1e, eri, norb, nelec, hdiag_det=hdiag_det) t0 = lib.logger.timer (fci, "csf.kernel: hdiag_csf", *t0) ncsf_all = count_all_csfs (norb, neleca, nelecb, smult) if idx_sym is None: ncsf_sym = ncsf_all else: ncsf_sym = np.count_nonzero (idx_sym) nroots = min(ncsf_sym, nroots) if nroots is not None: assert (ncsf_sym >= nroots), "Can't find {} roots among only {} CSFs".format (nroots, ncsf_sym) link_indexa, link_indexb = _unpack(norb, nelec, None) na = link_indexa.shape[0] nb = link_indexb.shape[0] t0 = lib.logger.timer (fci, "csf.kernel: throat-clearing", *t0) addr, h0 = fci.pspace(h1e, eri, norb, nelec, idx_sym=idx_sym, hdiag_det=hdiag_det, hdiag_csf=hdiag_csf, npsp=max(pspace_size,nroots)) lib.logger.debug (fci, 'csf.kernel: error of hdiag_csf: %s', np.amax (np.abs (hdiag_csf[addr]-np.diag (h0)))) t0 = lib.logger.timer (fci, "csf.kernel: make pspace", *t0) if pspace_size > 0: pw, pv = fci.eig (h0) else: pw = pv = None if pspace_size >= ncsf_sym and not davidson_only: if ncsf_sym == 1: civec = transformer.vec_csf2det (pv[:,0].reshape (1,1)) return pw[0]+ecore, civec elif nroots > 1: civec = np.empty((nroots,ncsf_all)) civec[:,addr] = pv[:,:nroots].T civec = transformer.vec_csf2det (civec) return pw[:nroots]+ecore, [c.reshape(na,nb) for c in civec] elif abs(pw[0]-pw[1]) > 1e-12: civec = np.empty((ncsf_all)) civec[addr] = pv[:,0] civec = transformer.vec_csf2det (civec) return pw[0]+ecore, civec.reshape(na,nb) t0 = lib.logger.timer (fci, "csf.kernel: throat-clearing", *t0) if idx_sym is None: precond = fci.make_precond(hdiag_csf, pw, pv, addr) else: addr_bool = np.zeros (ncsf_all, dtype=np.bool) addr_bool[addr] = True precond = fci.make_precond(hdiag_csf[idx_sym], pw, pv, addr_bool[idx_sym]) t0 = lib.logger.timer (fci, "csf.kernel: make preconditioner", *t0) ''' fci.eci, fci.ci = \ kernel_ms1(fci, h1e, eri, norb, nelec, ci0, None, tol, lindep, max_cycle, max_space, nroots, davidson_only, pspace_size, ecore=ecore, **kwargs) ''' h2e = fci.absorb_h1e(h1e, eri, norb, nelec, .5) t0 = lib.logger.timer (fci, "csf.kernel: h2e", *t0) def hop(x): x_det = transformer.vec_csf2det (x) hx = fci.contract_2e(h2e, x_det, norb, nelec, (link_indexa,link_indexb)) return transformer.vec_det2csf (hx, normalize=False).ravel () t0 = lib.logger.timer (fci, "csf.kernel: make hop", *t0) if ci0 is None: if hasattr(fci, 'get_init_guess'): def ci0 (): return transformer.vec_det2csf (fci.get_init_guess(norb, nelec, nroots, hdiag_csf)) else: def ci0(): # lazy initialization to reduce memory footprint x0 = [] for i in range(nroots): x = np.zeros(ncsf_sym) x[addr[i]] = 1 x0.append(x) return x0 else: if isinstance(ci0, np.ndarray) and ci0.size == na*nb: ci0 = [transformer.vec_det2csf (ci0.ravel ())] else: nrow = len (ci0) ci0 = np.asarray (ci0).reshape (nrow, -1, order='C') ci0 = np.ascontiguousarray (ci0) ci0 = transformer.vec_det2csf (ci0.ravel ()) ci0 = [c for c in ci0.reshape (nrow, -1)] t0 = lib.logger.timer (fci, "csf.kernel: ci0 handling", *t0) if tol is None: tol = fci.conv_tol if lindep is None: lindep = fci.lindep if max_cycle is None: max_cycle = fci.max_cycle if max_space is None: max_space = fci.max_space if max_memory is None: max_memory = fci.max_memory tol_residual = getattr(fci, 'conv_tol_residual', None) #with lib.with_omp_threads(fci.threads): #e, c = lib.davidson(hop, ci0, precond, tol=fci.conv_tol, lindep=fci.lindep) e, c = fci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=verbose, follow_state=True, tol_residual=tol_residual, **kwargs) t0 = lib.logger.timer (fci, "csf.kernel: running fci.eig", *t0) c = transformer.vec_csf2det (c, order='C') t0 = lib.logger.timer (fci, "csf.kernel: transforming final ci vector", *t0) if nroots > 1: return e+ecore, [ci.reshape(na,nb) for ci in c] else: return e+ecore, c.reshape(na,nb)
def trans_rdm1(self, cibra, ciket, norb, nelec, link_index=None): nelec = direct_spin1._unpack_nelec(nelec, self.spin) cibra = _as_SCIvector_if_not(cibra, self._strs) ciket = _as_SCIvector_if_not(ciket, self._strs) return trans_rdm1(cibra, ciket, norb, nelec, link_index)
def large_ci(self, civec_strs, norb, nelec, tol=.1): nelec = direct_spin1._unpack_nelec(nelec, self.spin) ci, _, (strsa, strsb) = _unpack(civec_strs, nelec, self._strs) return [(ci[i,j], bin(strsa[i]), bin(strsb[j])) for i,j in numpy.argwhere(abs(ci) > tol)]
def make_rdm1(self, civec_strs, norb, nelec, link_index=None): nelec = direct_spin1._unpack_nelec(nelec, self.spin) rdm1a, rdm1b = self.make_rdm1s(civec_strs, norb, nelec, link_index) return rdm1a + rdm1b
def make_shape(nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) na = cistring.num_strings(nsite, neleca) nb = cistring.num_strings(nsite, nelecb) return (na, nb) + (nphonon + 1, ) * nsite
def make_rdm2(self, civec_strs, norb, nelec, link_index=None, **kwargs): nelec = direct_spin1._unpack_nelec(nelec, self.spin) civec_strs = _as_SCIvector_if_not(civec_strs, self._strs) return make_rdm2(civec_strs, norb, nelec, link_index)
def get_init_guess(norb, nelec, nroots, hdiag, orbsym, wfnsym=0): neleca, nelecb = direct_spin1._unpack_nelec(nelec) strsa = numpy.asarray(cistring.gen_strings4orblist(range(norb), neleca)) strsb = numpy.asarray(cistring.gen_strings4orblist(range(norb), nelecb)) return _get_init_guess(strsa, strsb, nroots, hdiag, orbsym, wfnsym)
def trans_rdm1(self, cibra, ciket, norb, nelec, link_index=None): nelec = direct_spin1._unpack_nelec(nelec, self.spin) cibra = _as_SCIvector_if_not(cibra, self._strs) ciket = _as_SCIvector_if_not(ciket, self._strs) return trans_rdm1(cibra, ciket, norb, nelec, link_index)
def kernel_float_space(myci, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_iter=None, max_memory=None, verbose=None, ecore=0, return_integrals=False, eri_sorted=None, jk=None, jk_sorted=None, **kwargs): if verbose is None: log = logger.Logger(myci.stdout, myci.verbose) elif isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if max_iter is None: max_iter = myci.max_iter if myci.verbose >= logger.WARN: myci.check_sanity() log.info('\nStarting heat-bath CI algorithm...\n') log.info('Selection threshold: %8.5e', myci.select_cutoff) log.info('CI coefficient cutoff: %8.5e', myci.ci_coeff_cutoff) log.info('Energy convergence tolerance: %8.5e', tol) log.info('Number of determinants tolerance: %8.5e', myci.conv_ndet_tol) log.info('Number of electrons: %s', nelec) log.info('Number of orbitals: %3d', norb) log.info('Number of roots: %3d', nroots) nelec = direct_spin1._unpack_nelec(nelec, myci.spin) eri = ao2mo.restore(1, eri, norb) # Avoid resorting the integrals by storing them in memory eri = eri.ravel() if eri_sorted is None and jk is None and jk_sorted is None: log.debug("\nSorting two-electron integrals...") t_start = time.time() eri_sorted = abs(eri).argsort()[::-1] jk = eri.reshape([norb]*4) jk = jk - jk.transpose(2,1,0,3) jk = jk.ravel() jk_sorted = abs(jk).argsort()[::-1] t_current = time.time() - t_start log.debug('Timing for sorting the integrals: %10.3f', t_current) # Initial guess if ci0 is None: hf_str = numpy.hstack([orblst2str(range(nelec[0]), norb), orblst2str(range(nelec[1]), norb)]).reshape(1,-1) ci0 = [as_SCIvector(numpy.ones(1), hf_str)] else: assert(nroots == len(ci0)) ci0 = myci.enlarge_space(ci0, h1e, eri, jk, eri_sorted, jk_sorted, norb, nelec) def hop(c): hc = myci.contract_2e((h1e, eri), as_SCIvector(c, ci_strs), norb, nelec, hdiag) return hc.ravel() precond = lambda x, e, *args: x/(hdiag-e+myci.level_shift) e_last = 0 float_tol = 3e-4 conv = False for icycle in range(max_iter): ci_strs = ci0[0]._strs float_tol = max(float_tol*.3, tol*1e2) log.info('\nMacroiteration %d', icycle) log.info('Number of CI configurations: %d', ci_strs.shape[0]) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) t_start = time.time() e, ci0 = myci.eig(hop, ci0, precond, tol=float_tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if not isinstance(ci0, (tuple, list)): ci0 = [ci0] e = [e] t_current = time.time() - t_start log.debug('Timing for solving the eigenvalue problem: %10.3f', t_current) ci0 = [as_SCIvector(c, ci_strs) for c in ci0] de, e_last = min(e)-e_last, min(e) log.info('Cycle %d E = %s dE = %.8g', icycle, numpy.array(e)+ecore, de) if abs(de) < tol*1e3: conv = True break last_ci0_size = float(len(ci_strs)) t_start = time.time() ci0 = myci.enlarge_space(ci0, h1e, eri, jk, eri_sorted, jk_sorted, norb, nelec) t_current = time.time() - t_start log.debug('Timing for selecting configurations: %10.3f', t_current) if (((1 - myci.conv_ndet_tol) < len(ci0[0]._strs)/last_ci0_size < (1 + myci.conv_ndet_tol))): conv = True break ci_strs = ci0[0]._strs log.info('\nExtra CI in the final selected space') log.info('Number of CI configurations: %d', ci_strs.shape[0]) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if not isinstance(c, (tuple, list)): c = [c] e = [e] log.info('\nSelected CI E = %s', numpy.array(e)+ecore) if (return_integrals): return (numpy.array(e)+ecore), [as_SCIvector(ci, ci_strs) for ci in c], eri_sorted, jk, jk_sorted else: return (numpy.array(e)+ecore), [as_SCIvector(ci, ci_strs) for ci in c]
def contract_2e(eri, fcivec, norb, nelec, link_index=None, orbsym=None, wfnsym=0): if orbsym is None: return direct_spin1.contract_2e(eri, fcivec, norb, nelec, link_index) eri = ao2mo.restore(4, eri, norb) neleca, nelecb = direct_spin1._unpack_nelec(nelec) link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, link_index) na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] eri_irs, rank_eri, irrep_eri = reorder_eri(eri, norb, orbsym) strsa = cistring.gen_strings4orblist(range(norb), neleca) aidx, link_indexa = gen_str_irrep(strsa, orbsym, link_indexa, rank_eri, irrep_eri) if neleca == nelecb: bidx, link_indexb = aidx, link_indexa else: strsb = cistring.gen_strings4orblist(range(norb), nelecb) bidx, link_indexb = gen_str_irrep(strsb, orbsym, link_indexb, rank_eri, irrep_eri) Tirrep = ctypes.c_void_p * TOTIRREPS linka_ptr = Tirrep( *[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexa]) linkb_ptr = Tirrep( *[x.ctypes.data_as(ctypes.c_void_p) for x in link_indexb]) eri_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in eri_irs]) dimirrep = (ctypes.c_int * TOTIRREPS)(*[x.shape[0] for x in eri_irs]) fcivec_shape = fcivec.shape fcivec = fcivec.reshape((na, nb), order='C') ci1new = numpy.zeros_like(fcivec) nas = (ctypes.c_int * TOTIRREPS)(*[x.size for x in aidx]) nbs = (ctypes.c_int * TOTIRREPS)(*[x.size for x in bidx]) # aa, ab ci0 = [] ci1 = [] for ir in range(TOTIRREPS): ma, mb = aidx[ir].size, bidx[wfnsym ^ ir].size ci0.append(numpy.zeros((ma, mb))) ci1.append(numpy.zeros((ma, mb))) if ma > 0 and mb > 0: lib.take_2d(fcivec, aidx[ir], bidx[wfnsym ^ ir], out=ci0[ir]) ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0]) ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1]) libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs, ctypes.c_int(norb), nas, nbs, ctypes.c_int(nlinka), ctypes.c_int(nlinkb), linka_ptr, linkb_ptr, dimirrep, ctypes.c_int(wfnsym)) for ir in range(TOTIRREPS): if ci0[ir].size > 0: lib.takebak_2d(ci1new, ci1[ir], aidx[ir], bidx[wfnsym ^ ir]) # bb, ba ci0T = [] for ir in range(TOTIRREPS): mb, ma = bidx[ir].size, aidx[wfnsym ^ ir].size ci0T.append(numpy.zeros((mb, ma))) if ma > 0 and mb > 0: lib.transpose(ci0[wfnsym ^ ir], out=ci0T[ir]) ci0, ci0T = ci0T, None ci1 = [numpy.zeros_like(x) for x in ci0] ci0_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci0]) ci1_ptrs = Tirrep(*[x.ctypes.data_as(ctypes.c_void_p) for x in ci1]) libfci.FCIcontract_2e_symm1(eri_ptrs, ci0_ptrs, ci1_ptrs, ctypes.c_int(norb), nbs, nas, ctypes.c_int(nlinkb), ctypes.c_int(nlinka), linkb_ptr, linka_ptr, dimirrep, ctypes.c_int(wfnsym)) for ir in range(TOTIRREPS): if ci0[ir].size > 0: lib.takebak_2d(ci1new, lib.transpose(ci1[ir]), aidx[wfnsym ^ ir], bidx[ir]) return ci1new.reshape(fcivec_shape)
def pspace (fci, h1e, eri, norb, nelec, transformer, hdiag_det=None, hdiag_csf=None, npsp=200): ''' Note that getting pspace for npsp CSFs is substantially more costly than getting it for npsp determinants, until I write code than can evaluate Hamiltonian matrix elements of CSFs directly. On the other hand a pspace of determinants contains many redundant degrees of freedom for the same reason. Therefore I have reduced the default pspace size by a factor of 2.''' if norb > 63: raise NotImplementedError('norb > 63') t0 = (time.process_time (), time.time ()) neleca, nelecb = _unpack_nelec(nelec) h1e = np.ascontiguousarray(h1e) eri = ao2mo.restore(1, eri, norb) nb = cistring.num_strings(norb, nelecb) if hdiag_det is None: hdiag_det = fci.make_hdiag(h1e, eri, norb, nelec) if hdiag_csf is None: hdiag_csf = fci.make_hdiag_csf(h1e, eri, norb, nelec, hdiag_det=hdiag_det) csf_addr = np.arange (hdiag_csf.size, dtype=np.int) if transformer.wfnsym is None: ncsf_sym = hdiag_csf.size else: idx_sym = transformer.confsym[transformer.econf_csf_mask] == transformer.wfnsym ncsf_sym = np.count_nonzero (idx_sym) csf_addr = csf_addr[idx_sym] if ncsf_sym > npsp: try: csf_addr = csf_addr[np.argpartition(hdiag_csf[csf_addr], npsp-1)[:npsp]] except AttributeError: csf_addr = csf_addr[np.argsort(hdiag_csf[csf_addr])[:npsp]] # To build econf_addr = np.unique (transformer.econf_csf_mask[csf_addr]) det_addr = np.concatenate ([np.nonzero (transformer.econf_det_mask == conf)[0] for conf in econf_addr]) lib.logger.debug (fci, ("csf.pspace: Lowest-energy %s CSFs correspond to %s configurations" " which are spanned by %s determinants"), npsp, econf_addr.size, det_addr.size) addra, addrb = divmod(det_addr, nb) stra = cistring.addrs2str(norb, neleca, addra) strb = cistring.addrs2str(norb, nelecb, addrb) npsp_det = len(det_addr) h0 = np.zeros((npsp_det,npsp_det)) h1e_ab = unpack_h1e_ab (h1e) h1e_a = np.ascontiguousarray(h1e_ab[0]) h1e_b = np.ascontiguousarray(h1e_ab[1]) g2e = ao2mo.restore(1, eri, norb) g2e_ab = g2e_bb = g2e_aa = g2e _debug_g2e (fci, g2e, eri, norb) # Exploring g2e nan bug; remove later? t0 = lib.logger.timer (fci, "csf.pspace: index manipulation", *t0) libfci.FCIpspace_h0tril_uhf(h0.ctypes.data_as(ctypes.c_void_p), h1e_a.ctypes.data_as(ctypes.c_void_p), h1e_b.ctypes.data_as(ctypes.c_void_p), g2e_aa.ctypes.data_as(ctypes.c_void_p), g2e_ab.ctypes.data_as(ctypes.c_void_p), g2e_bb.ctypes.data_as(ctypes.c_void_p), stra.ctypes.data_as(ctypes.c_void_p), strb.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(norb), ctypes.c_int(npsp_det)) t0 = lib.logger.timer (fci, "csf.pspace: pspace Hamiltonian in determinant basis", *t0) for i in range(npsp_det): h0[i,i] = hdiag_det[det_addr[i]] h0 = lib.hermi_triu(h0) try: if fci.verbose >= lib.logger.DEBUG: evals_before = scipy.linalg.eigh (h0)[0] except ValueError as e: lib.logger.debug (fci, ("ERROR: h0 has {} infs, {} nans; h1e_a has {} infs, {} nans; " "h1e_b has {} infs, {} nans; g2e has {} infs, {} nans, norb = {}, npsp_det = {}").format ( np.count_nonzero (np.isinf (h0)), np.count_nonzero (np.isnan (h0)), np.count_nonzero (np.isinf (h1e_a)), np.count_nonzero (np.isnan (h1e_a)), np.count_nonzero (np.isinf (h1e_b)), np.count_nonzero (np.isnan (h1e_b)), np.count_nonzero (np.isinf (g2e)), np.count_nonzero (np.isnan (g2e)), norb, npsp_det)) evals_before = np.zeros (npsp_det) h0, csf_addr = transformer.mat_det2csf_confspace (h0, econf_addr) t0 = lib.logger.timer (fci, "csf.pspace: transform pspace Hamiltonian into CSF basis", *t0) if fci.verbose >= lib.logger.DEBUG: lib.logger.debug2 (fci, "csf.pspace: eigenvalues of h0 before transformation %s", evals_before) evals_after = scipy.linalg.eigh (h0)[0] lib.logger.debug2 (fci, "csf.pspace: eigenvalues of h0 after transformation %s", evals_after) idx = [np.argmin (np.abs (evals_before - ev)) for ev in evals_after] resid = evals_after - evals_before[idx] lib.logger.debug2 (fci, "csf.pspace: best h0 eigenvalue matching differences after transformation: %s", resid) lib.logger.debug (fci, "csf.pspace: if the transformation of h0 worked the following number will be zero: %s", np.max (np.abs(resid))) # We got extra CSFs from building the configurations most of the time. if csf_addr.size > npsp: try: csf_addr_2 = np.argpartition(np.diag (h0), npsp-1)[:npsp] except AttributeError: csf_addr_2 = np.argsort(np.diag (h0))[:npsp] csf_addr = csf_addr[csf_addr_2] h0 = h0[np.ix_(csf_addr_2,csf_addr_2)] npsp_csf = csf_addr.size lib.logger.debug (fci, "csf_solver.pspace: asked for %s-CSF pspace; found %s CSFs", npsp, npsp_csf) t0 = lib.logger.timer (fci, "csf.pspace wrapup", *t0) return csf_addr, h0
def make_shape(nsite, nelec, nphonon): neleca, nelecb = _unpack_nelec(nelec) na = cistring.num_strings(nsite, neleca) nb = cistring.num_strings(nsite, nelecb) return (na,nb)+(nphonon+1,)*nsite
def kernel_float_space(myci, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_memory=None, verbose=None, ecore=0, **kwargs): if verbose is None: log = logger.Logger(myci.stdout, myci.verbose) elif isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if myci.verbose >= logger.WARN: myci.check_sanity() nelec = direct_spin1._unpack_nelec(nelec, myci.spin) h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5) h2e = ao2mo.restore(1, h2e, norb) # TODO: initial guess from CISD if isinstance(ci0, _SCIvector): if ci0.size == len(ci0._strs[0]) * len(ci0._strs[1]): ci0 = [ci0.ravel()] else: ci0 = [x.ravel() for x in ci0] else: ci_strs = (numpy.asarray([int('1' * nelec[0], 2)]), numpy.asarray([int('1' * nelec[1], 2)])) ci0 = _as_SCIvector(numpy.ones((1, 1)), ci_strs) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) if ci0.size < nroots: log.warn(''' Selected-CI space generated from HF ground state (by double exciting) is not enough for excited states. H**O->LUMO excitations are included in the initial guess. NOTE: This may introduce excited states of different symmetry.\n''') corea = '1' * (nelec[0] - 1) coreb = '1' * (nelec[1] - 1) ci_strs = (numpy.asarray([ int('1' + corea, 2), int('10' + corea, 2) ]), numpy.asarray([int('1' + coreb, 2), int('10' + coreb, 2)])) ci0 = _as_SCIvector(numpy.ones((2, 2)), ci_strs) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) if ci0.size < nroots: raise RuntimeError('Not enough selected-CI space for %d states' % nroots) ci_strs = ci0._strs hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) ci0 = myci.get_init_guess(ci_strs, norb, nelec, nroots, hdiag) def hop(c): hc = myci.contract_2e(h2e, _as_SCIvector(c, ci_strs), norb, nelec, link_index) return hc.ravel() precond = lambda x, e, *args: x / (hdiag - e + myci.level_shift) namax = cistring.num_strings(norb, nelec[0]) nbmax = cistring.num_strings(norb, nelec[1]) e_last = 0 float_tol = myci.start_tol tol_decay_rate = myci.tol_decay_rate conv = False for icycle in range(norb): ci_strs = ci0[0]._strs float_tol = max(float_tol * tol_decay_rate, tol * 1e2) log.debug('cycle %d ci.shape %s float_tol %g', icycle, (len(ci_strs[0]), len(ci_strs[1])), float_tol) ci0 = [c.ravel() for c in ci0] link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) #e, ci0 = lib.davidson(hop, ci0.reshape(-1), precond, tol=float_tol) e, ci0 = myci.eig(hop, ci0, precond, tol=float_tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if nroots > 1: ci0 = [_as_SCIvector(c, ci_strs) for c in ci0] de, e_last = min(e) - e_last, min(e) log.info('cycle %d E = %s dE = %.8g', icycle, e + ecore, de) else: ci0 = [_as_SCIvector(ci0, ci_strs)] de, e_last = e - e_last, e log.info('cycle %d E = %.15g dE = %.8g', icycle, e + ecore, de) if ci0[0].shape == (namax, nbmax) or abs(de) < tol * 1e3: conv = True break last_ci0_size = float(len(ci_strs[0])), float(len(ci_strs[1])) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) na = len(ci0[0]._strs[0]) nb = len(ci0[0]._strs[1]) if ((.99 < na / last_ci0_size[0] < 1.01) and (.99 < nb / last_ci0_size[1] < 1.01)): conv = True break ci_strs = ci0[0]._strs log.debug('Extra CI in selected space %s', (len(ci_strs[0]), len(ci_strs[1]))) ci0 = [c.ravel() for c in ci0] link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) na = len(ci_strs[0]) nb = len(ci_strs[1]) if nroots > 1: for i, ei in enumerate(e + ecore): log.info('Selected CI state %d E = %.15g', i, ei) return e + ecore, [ _as_SCIvector(ci.reshape(na, nb), ci_strs) for ci in c ] else: log.info('Selected CI E = %.15g', e + ecore) return e + ecore, _as_SCIvector(c.reshape(na, nb), ci_strs)
def spin_square(self, civec_strs, norb, nelec): nelec = direct_spin1._unpack_nelec(nelec, self.spin) return spin_square(_as_SCIvector_if_not(civec_strs, self._strs), norb, nelec)
def make_rdm1(self, civec_strs, norb, nelec, link_index=None): nelec = direct_spin1._unpack_nelec(nelec, self.spin) rdm1a, rdm1b = self.make_rdm1s(civec_strs, norb, nelec, link_index) return rdm1a + rdm1b
mol.verbose = lib.logger.DEBUG mol.output = 'sa_lasscf_slow_ham.log' mol.build() mf = scf.RHF(mol).run() tol = 1e-6 if len(sys.argv) < 2 else float(sys.argv[1]) las = LASSCF(mf, (4, 4), (4, 4)).set(conv_tol_grad=tol) mo = las.localize_init_guess((list(range(3)), list(range(9, 12))), mo_coeff=mf.mo_coeff) las.state_average_(weights=[0.5, 0.5], spins=[[0, 0], [2, -2]]) h2eff_sub, veff = las.kernel(mo)[-2:] e_states = las.e_states ncore, ncas, nocc = las.ncore, las.ncas, las.ncore + las.ncas mo_coeff = las.mo_coeff mo_core = mo_coeff[:, :ncore] mo_cas = mo_coeff[:, ncore:nocc] e0 = las._scf.energy_nuc() + 2 * (( (las._scf.get_hcore() + veff.c / 2) @ mo_core) * mo_core).sum() h1 = mo_cas.conj().T @ (las._scf.get_hcore() + veff.c) @ mo_cas h2 = h2eff_sub[ncore:nocc].reshape(ncas * ncas, ncas * (ncas + 1) // 2) h2 = lib.numpy_helper.unpack_tril(h2).reshape(ncas, ncas, ncas, ncas) nelec_fr = [] for fcibox, nelec in zip(las.fciboxes, las.nelecas_sub): ne = sum(nelec) nelec_fr.append([ _unpack_nelec(fcibox._get_nelec(solver, ne)) for solver in fcibox.fcisolvers ]) ham_eff = slow_ham(las.mol, h1, h2, las.ci, las.ncas_sub, nelec_fr)[0] print(las.converged, e_states - (e0 + np.diag(ham_eff)))
def make_rdm2(self, civec_strs, norb, nelec, link_index=None, **kwargs): nelec = direct_spin1._unpack_nelec(nelec, self.spin) civec_strs = _as_SCIvector_if_not(civec_strs, self._strs) return make_rdm2(civec_strs, norb, nelec, link_index)
def kernel_float_space(myci, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_memory=None, verbose=None, ecore=0, **kwargs): if verbose is None: log = logger.Logger(myci.stdout, myci.verbose) elif isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if myci.verbose >= logger.WARN: myci.check_sanity() nelec = direct_spin1._unpack_nelec(nelec, myci.spin) h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, .5) h2e = ao2mo.restore(1, h2e, norb) # TODO: initial guess from CISD if isinstance(ci0, _SCIvector): if ci0.size == len(ci0._strs[0])*len(ci0._strs[1]): ci0 = [ci0.ravel()] else: ci0 = [x.ravel() for x in ci0] else: if isinstance(nelec, (int, numpy.integer)): nelecb = nelec//2 neleca = nelec - nelecb nelec = neleca, nelecb ci_strs = (numpy.asarray([int('1'*nelec[0], 2)]), numpy.asarray([int('1'*nelec[1], 2)])) ci0 = _as_SCIvector(numpy.ones((1,1)), ci_strs) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) if ci0.size < nroots: log.warn(''' Selected-CI space generated from HF ground state (by double exciting) is not enough for excited states. H**O->LUMO excitations are included in the initial guess. NOTE: This may introduce excited states of different symmetry.\n''') corea = '1' * (nelec[0]-1) coreb = '1' * (nelec[1]-1) ci_strs = (numpy.asarray([int('1'+corea, 2), int('10'+corea, 2)]), numpy.asarray([int('1'+coreb, 2), int('10'+coreb, 2)])) ci0 = _as_SCIvector(numpy.ones((2,2)), ci_strs) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) if ci0.size < nroots: raise RuntimeError('Not enough selected-CI space for %d states' % nroots) ci_strs = ci0._strs hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) ci0 = myci.get_init_guess(ci_strs, norb, nelec, nroots, hdiag) def hop(c): hc = myci.contract_2e(h2e, _as_SCIvector(c, ci_strs), norb, nelec, link_index) return hc.ravel() precond = lambda x, e, *args: x/(hdiag-e+myci.level_shift) namax = cistring.num_strings(norb, nelec[0]) nbmax = cistring.num_strings(norb, nelec[1]) e_last = 0 float_tol = 3e-4 conv = False for icycle in range(norb): ci_strs = ci0[0]._strs float_tol = max(float_tol*.3, tol*1e2) log.debug('cycle %d ci.shape %s float_tol %g', icycle, (len(ci_strs[0]), len(ci_strs[1])), float_tol) ci0 = [c.ravel() for c in ci0] link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) #e, ci0 = lib.davidson(hop, ci0.reshape(-1), precond, tol=float_tol) e, ci0 = myci.eig(hop, ci0, precond, tol=float_tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if nroots > 1: ci0 = [_as_SCIvector(c, ci_strs) for c in ci0] de, e_last = min(e)-e_last, min(e) log.info('cycle %d E = %s dE = %.8g', icycle, e+ecore, de) else: ci0 = [_as_SCIvector(ci0, ci_strs)] de, e_last = e-e_last, e log.info('cycle %d E = %.15g dE = %.8g', icycle, e+ecore, de) if ci0[0].shape == (namax,nbmax) or abs(de) < tol*1e3: conv = True break last_ci0_size = float(len(ci_strs[0])), float(len(ci_strs[1])) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) na = len(ci0[0]._strs[0]) nb = len(ci0[0]._strs[1]) if ((.99 < na/last_ci0_size[0] < 1.01) and (.99 < nb/last_ci0_size[1] < 1.01)): conv = True break ci_strs = ci0[0]._strs log.debug('Extra CI in selected space %s', (len(ci_strs[0]), len(ci_strs[1]))) ci0 = [c.ravel() for c in ci0] link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) na = len(ci_strs[0]) nb = len(ci_strs[1]) if nroots > 1: for i, ei in enumerate(e+ecore): log.info('Selected CI state %d E = %.15g', i, ei) return e+ecore, [_as_SCIvector(ci.reshape(na,nb),ci_strs) for ci in c] else: log.info('Selected CI E = %.15g', e+ecore) return e+ecore, _as_SCIvector(c.reshape(na,nb), ci_strs)
def kernel_float_space( myci, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_memory=None, verbose=None, ecore=0, **kwargs ): if verbose is None: log = logger.Logger(myci.stdout, myci.verbose) elif isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if myci.verbose >= logger.WARN: myci.check_sanity() nelec = direct_spin1._unpack_nelec(nelec, myci.spin) h2e = direct_spin1.absorb_h1e(h1e, eri, norb, nelec, 0.5) h2e = ao2mo.restore(1, h2e, norb) # TODO: initial guess from CISD if isinstance(ci0, _SCIvector): if ci0.size == len(ci0._strs[0]) * len(ci0._strs[1]): ci0 = [ci0.ravel()] else: ci0 = [x.ravel() for x in ci0] else: if isinstance(nelec, (int, numpy.integer)): nelecb = nelec // 2 neleca = nelec - nelecb nelec = neleca, nelecb ci_strs = (numpy.asarray([int("1" * nelec[0], 2)]), numpy.asarray([int("1" * nelec[1], 2)])) ci0 = _as_SCIvector(numpy.ones((1, 1)), ci_strs) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) ci_strs = ci0._strs hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) ci0 = myci.get_init_guess(ci_strs, norb, nelec, nroots, hdiag) def hop(c): hc = myci.contract_2e(h2e, _as_SCIvector(c, ci_strs), norb, nelec, link_index) return hc.ravel() precond = lambda x, e, *args: x / (hdiag - e + myci.level_shift) namax = cistring.num_strings(norb, nelec[0]) nbmax = cistring.num_strings(norb, nelec[1]) e_last = 0 float_tol = 3e-4 conv = False for icycle in range(norb): ci_strs = ci0[0]._strs float_tol = max(float_tol * 0.3, tol * 1e2) log.debug("cycle %d ci.shape %s float_tol %g", icycle, (len(ci_strs[0]), len(ci_strs[1])), float_tol) ci0 = [c.ravel() for c in ci0] link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) # e, ci0 = lib.davidson(hop, ci0.reshape(-1), precond, tol=float_tol) e, ci0 = myci.eig( hop, ci0, precond, tol=float_tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs ) if nroots > 1: ci0 = [_as_SCIvector(c, ci_strs) for c in ci0] de, e_last = min(e) - e_last, min(e) log.info("cycle %d E = %s dE = %.8g", icycle, e + ecore, de) else: ci0 = [_as_SCIvector(ci0, ci_strs)] de, e_last = e - e_last, e log.info("cycle %d E = %.15g dE = %.8g", icycle, e + ecore, de) if ci0[0].shape == (namax, nbmax) or abs(de) < tol * 1e3: conv = True break last_ci0_size = float(len(ci_strs[0])), float(len(ci_strs[1])) ci0 = myci.enlarge_space(ci0, h2e, norb, nelec) na = len(ci0[0]._strs[0]) nb = len(ci0[0]._strs[1]) if (0.99 < na / last_ci0_size[0] < 1.01) and (0.99 < nb / last_ci0_size[1] < 1.01): conv = True break ci_strs = ci0[0]._strs log.debug("Extra CI in selected space %s", (len(ci_strs[0]), len(ci_strs[1]))) ci0 = [c.ravel() for c in ci0] link_index = _all_linkstr_index(ci_strs, norb, nelec) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) e, c = myci.eig( hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs ) log.info("Select CI E = %.15g", e + ecore) na = len(ci_strs[0]) nb = len(ci_strs[1]) if nroots > 1: return e + ecore, [_as_SCIvector(ci.reshape(na, nb), ci_strs) for ci in c] else: return e + ecore, _as_SCIvector(c.reshape(na, nb), ci_strs)
def kernel_float_space(myci, h1e, eri, norb, nelec, ci0=None, tol=None, lindep=None, max_cycle=None, max_space=None, nroots=None, davidson_only=None, max_iter=None, max_memory=None, verbose=None, ecore=0, return_integrals=False, eri_sorted=None, jk=None, jk_sorted=None, **kwargs): if verbose is None: log = logger.Logger(myci.stdout, myci.verbose) elif isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(myci.stdout, verbose) if tol is None: tol = myci.conv_tol if lindep is None: lindep = myci.lindep if max_cycle is None: max_cycle = myci.max_cycle if max_space is None: max_space = myci.max_space if max_memory is None: max_memory = myci.max_memory if nroots is None: nroots = myci.nroots if max_iter is None: max_iter = myci.max_iter if myci.verbose >= logger.WARN: myci.check_sanity() log.info('\nStarting heat-bath CI algorithm...\n') log.info('Selection threshold: %8.5e', myci.select_cutoff) log.info('CI coefficient cutoff: %8.5e', myci.ci_coeff_cutoff) log.info('Energy convergence tolerance: %8.5e', tol) log.info('Number of determinants tolerance: %8.5e', myci.conv_ndet_tol) log.info('Number of electrons: %s', nelec) log.info('Number of orbitals: %3d', norb) log.info('Number of roots: %3d', nroots) nelec = direct_spin1._unpack_nelec(nelec, myci.spin) eri = ao2mo.restore(1, eri, norb) # Avoid resorting the integrals by storing them in memory eri = eri.ravel() if eri_sorted is None and jk is None and jk_sorted is None: log.debug("\nSorting two-electron integrals...") t_start = time.time() eri_sorted = abs(eri).argsort()[::-1] jk = eri.reshape([norb]*4) jk = jk - jk.transpose(2,1,0,3) jk = jk.ravel() jk_sorted = abs(jk).argsort()[::-1] t_current = time.time() - t_start log.debug('Timing for sorting the integrals: %10.3f', t_current) # Initial guess if ci0 is None: hf_str = numpy.hstack([orblst2str(range(nelec[0]), norb), orblst2str(range(nelec[1]), norb)]).reshape(1,-1) ci0 = [as_SCIvector(numpy.ones(1), hf_str)] else: assert(nroots == len(ci0)) ci0 = myci.enlarge_space(ci0, h1e, eri, jk, eri_sorted, jk_sorted, norb, nelec) def hop(c): hc = myci.contract_2e((h1e, eri), as_SCIvector(c, ci_strs), norb, nelec, hdiag) return hc.ravel() precond = lambda x, e, *args: x/(hdiag-e+myci.level_shift) e_last = 0 float_tol = 3e-4 conv = False for icycle in range(max_iter): ci_strs = ci0[0]._strs float_tol = max(float_tol*.3, tol*1e2) log.info('\nMacroiteration %d', icycle) log.info('Number of CI configurations: %d', ci_strs.shape[0]) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) t_start = time.time() e, ci0 = myci.eig(hop, ci0, precond, tol=float_tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if not isinstance(ci0, (tuple, list)): ci0 = [ci0] e = [e] t_current = time.time() - t_start log.debug('Timing for solving the eigenvalue problem: %10.3f', t_current) ci0 = [as_SCIvector(c, ci_strs) for c in ci0] de, e_last = min(e)-e_last, min(e) log.info('Cycle %d E = %s dE = %.8g', icycle, numpy.array(e)+ecore, de) if abs(de) < tol*1e3: conv = True break last_ci0_size = float(len(ci_strs)) t_start = time.time() ci0 = myci.enlarge_space(ci0, h1e, eri, jk, eri_sorted, jk_sorted, norb, nelec) t_current = time.time() - t_start log.debug('Timing for selecting configurations: %10.3f', t_current) if (((1 - myci.conv_ndet_tol) < len(ci0[0]._strs)/last_ci0_size < (1 + myci.conv_ndet_tol))): conv = True break ci_strs = ci0[0]._strs log.info('\nExtra CI in the final selected space') log.info('Number of CI configurations: %d', ci_strs.shape[0]) hdiag = myci.make_hdiag(h1e, eri, ci_strs, norb, nelec) e, c = myci.eig(hop, ci0, precond, tol=tol, lindep=lindep, max_cycle=max_cycle, max_space=max_space, nroots=nroots, max_memory=max_memory, verbose=log, **kwargs) if not isinstance(c, (tuple, list)): c = [c] e = [e] log.info('\nSelected CI E = %s', numpy.array(e)+ecore) if (return_integrals): return (numpy.array(e)+ecore), [as_SCIvector(ci, ci_strs) for ci in c], eri_sorted, jk, jk_sorted else: return (numpy.array(e)+ecore), [as_SCIvector(ci, ci_strs) for ci in c]
def spin_square(self, civec_strs, norb, nelec): nelec = direct_spin1._unpack_nelec(nelec, self.spin) return spin_square(_as_SCIvector_if_not(civec_strs, self._strs), norb, nelec)