def contract_1e(f1e, fcivec, norb, nelec, link_index=None): fcivec = numpy.asarray(fcivec, order='C') link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, link_index) na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] assert (fcivec.size == na * nb) ci1 = numpy.zeros_like(fcivec) f1e_tril = pyscf.lib.pack_tril(f1e[0]) libfci.FCIcontract_a_1e(f1e_tril.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)) f1e_tril = pyscf.lib.pack_tril(f1e[1]) libfci.FCIcontract_b_1e(f1e_tril.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(f1e, fcivec, norb, nelec, link_index=None): fcivec = numpy.asarray(fcivec, order='C') link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, link_index) na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] assert(fcivec.size == na*nb) ci1 = numpy.zeros_like(fcivec) f1e_tril = pyscf.lib.pack_tril(f1e[0]) libfci.FCIcontract_a_1e(f1e_tril.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)) f1e_tril = pyscf.lib.pack_tril(f1e[1]) libfci.FCIcontract_b_1e(f1e_tril.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, orbsym=None): fcivec = numpy.asarray(fcivec, order='C') if orbsym is None: return direct_spin1.contract_2e(eri, fcivec, norb, nelec, link_index) eri = pyscf.ao2mo.restore(4, eri, norb) link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, link_index) na, nlinka = link_indexa.shape[:2] nb, nlinkb = link_indexb.shape[:2] assert(fcivec.size == na*nb) ci1 = numpy.empty_like(fcivec) eri, link_indexa, dimirrep = reorder4irrep(eri, norb, link_indexa, orbsym) link_indexb = reorder4irrep(eri, norb, link_indexb, orbsym)[1] dimirrep = numpy.array(dimirrep, dtype=numpy.int32) libfci.FCIcontract_2e_spin1_symm(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), dimirrep.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(len(dimirrep))) return ci1
def contract_2e(eri, fcivec, norb, nelec, link_index=None): fcivec = numpy.asarray(fcivec, order='C') g2e_aa = pyscf.ao2mo.restore(4, eri[0], norb) g2e_ab = pyscf.ao2mo.restore(4, eri[1], norb) g2e_bb = pyscf.ao2mo.restore(4, eri[2], norb) link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, 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_uhf2e(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), 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): fcivec = numpy.asarray(fcivec, order='C') g2e_aa = pyscf.ao2mo.restore(4, eri[0], norb) g2e_ab = pyscf.ao2mo.restore(4, eri[1], norb) g2e_bb = pyscf.ao2mo.restore(4, eri[2], norb) link_indexa, link_indexb = direct_spin1._unpack(norb, nelec, 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_uhf2e(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), 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, 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 = _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 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 = _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 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)