def ao2mo(self, mo): # nmo = mo.shape[1] # ncore = self.ncore # ncas = self.ncas # nocc = ncore + ncas # eri = pyscf.ao2mo.incore.full(self._scf._eri, mo) # eri = pyscf.ao2mo.restore(1, eri, nmo) # eris = lambda:None # eris.j_cp = numpy.einsum('iipp->ip', eri[:ncore,:ncore,:,:]) # eris.k_cp = numpy.einsum('ippi->ip', eri[:ncore,:,:,:ncore]) # eris.vhf =(numpy.einsum('iipq->ipq', eri[:ncore,:ncore,:,:])*2 # -numpy.einsum('ipqi->ipq', eri[:ncore,:,:,:ncore])) # eris.aapp = numpy.array(eri[ncore:nocc,ncore:nocc,:,:]) # eris.appa = numpy.array(eri[ncore:nocc,:,:,ncore:nocc]) ## for update_jk_in_ah # capp = eri[:ncore,ncore:nocc,:,:] # cpap = eri[:ncore,:,ncore:nocc,:] # ccvp = eri[:ncore,:ncore,ncore:,:] # cpcv = eri[:ncore,:,:ncore,ncore:] # cvcp = eri[:ncore,ncore:,:ncore,:] # cPAp = cpap * 4 - capp.transpose(0,3,1,2) - cpap.transpose(0,3,2,1) # cPCv = cpcv * 4 - ccvp.transpose(0,3,1,2) - cvcp.transpose(0,3,2,1) # eris.Iapcv = cPAp.transpose(2,3,0,1)[:,:,:,ncore:] # eris.Icvcv = cPCv.transpose(2,3,0,1).copy() # return eris if hasattr(self._scf, '_cderi'): raise RuntimeError('TODO: density fitting') return mc_ao2mo._ERIS(self, mo, 'incore')
def ao2mo(self, mo): # nmo = mo.shape[1] # ncore = self.ncore # ncas = self.ncas # nocc = ncore + ncas # eri = pyscf.ao2mo.incore.full(self._scf._eri, mo) # eri = pyscf.ao2mo.restore(1, eri, nmo) # eris = lambda:None # eris.j_cp = numpy.einsum('iipp->ip', eri[:ncore,:ncore,:,:]) # eris.k_cp = numpy.einsum('ippi->ip', eri[:ncore,:,:,:ncore]) # eris.vhf_c =(numpy.einsum('iipq->pq', eri[:ncore,:ncore,:,:])*2 # -numpy.einsum('ipqi->pq', eri[:ncore,:,:,:ncore])) # eris.ppaa = numpy.asarray(eri[:,:,ncore:nocc,ncore:nocc], order='C') # eris.papa = numpy.asarray(eri[:,ncore:nocc,:,ncore:nocc], order='C') # return eris if hasattr(self._scf, '_tag_df') and self._scf._tag_df: from pyscf.mcscf import df # a hacky call using dm=[], to make sure all things are initialized if not hasattr(self, '_cderi') or self._cderi is None: self._scf.get_jk(self.mol, []) self._cderi = self._scf._cderi self._naoaux = self._scf._naoaux return df.ao2mo_(self, mo) else: return mc_ao2mo._ERIS(self, mo, method='incore', level=2)
def _init_df (self): lasci.LASCI_HessianOperator._init_df (self) if isinstance (self.las, lasci._DFLASCI): self.cas_type_eris = mc_df._ERIS (self.las, self.mo_coeff, self.with_df) else: self.cas_type_eris = mc_ao2mo._ERIS (self.las, self.mo_coeff, method='incore', level=2) # level=2 -> ppaa, papa only # level=1 computes more stuff; it's only useful if I # want the honest hdiag in get_prec () ncore, ncas = self.ncore, self.ncas nocc = ncore + ncas
def ao2mo_(casscf, mo): t0 = (time.clock(), time.time()) log = logger.Logger(casscf.stdout, casscf.verbose) # using dm=[], a hacky call to dfhf.get_jk, to generate casscf._cderi dfhf.get_jk_(casscf, casscf.mol, []) if log.verbose >= logger.DEBUG1: t1 = log.timer('Generate density fitting integrals', *t0) if hasattr(casscf._scf, '_tag_df') and casscf._scf._tag_df: eris = _ERIS(casscf, mo) else: # Only approximate the orbital rotation, call the 4-center integral # transformation. CASSCF is exact. eris = mc_ao2mo._ERIS(casscf, mo, 'incore', level=2) t0 = (time.clock(), time.time()) mo = numpy.asarray(mo, order='F') nao, nmo = mo.shape ncore = casscf.ncore eris.j_pc = numpy.zeros((nmo,ncore)) k_cp = numpy.zeros((ncore,nmo)) fmmm = _ao2mo._fpointer('AO2MOmmm_nr_s2_iltj') fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv ftrans = _ao2mo._fpointer('AO2MOtranse2_nr_s2') bufs1 = numpy.empty((dfhf.BLOCKDIM,nmo,nmo)) with df.load(casscf._cderi) as feri: for b0, b1 in dfhf.prange(0, casscf._naoaux, dfhf.BLOCKDIM): eri1 = numpy.asarray(feri[b0:b1], order='C') buf = bufs1[:b1-b0] if log.verbose >= logger.DEBUG1: t1 = log.timer('load buf %d:%d'%(b0,b1), *t1) fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p), eri1.ctypes.data_as(ctypes.c_void_p), mo.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(b1-b0), ctypes.c_int(nao), ctypes.c_int(0), ctypes.c_int(nmo), ctypes.c_int(0), ctypes.c_int(nmo), ctypes.c_void_p(0), ctypes.c_int(0)) if log.verbose >= logger.DEBUG1: t1 = log.timer('transform [%d:%d]'%(b0,b1), *t1) bufd = numpy.einsum('kii->ki', buf) eris.j_pc += numpy.einsum('ki,kj->ij', bufd, bufd[:,:ncore]) k_cp += numpy.einsum('kij,kij->ij', buf[:,:ncore], buf[:,:ncore]) if log.verbose >= logger.DEBUG1: t1 = log.timer('j_pc and k_pc', *t1) eri1 = None eris.k_pc = k_cp.T.copy() log.timer('ao2mo density fit part', *t0) return eris
def get_fock(mc, mo_coeff=None, ci=None, eris=None, verbose=None): '''Generalized Fock matrix ''' from pyscf.mcscf import mc_ao2mo if ci is None: ci = mc.ci if mo_coeff is None: mo_coeff = mc.mo_coeff if eris is None: eris = mc_ao2mo._ERIS(mc, mo_coeff, approx=2) ncas = mc.ncas nelecas = mc.nelecas casdm1 = mc.fcisolver.make_rdm1(ci, ncas, nelecas) vj = numpy.einsum('ij,ijpq->pq', casdm1, eris.aapp) vk = numpy.einsum('ij,ipqj->pq', casdm1, eris.appa) h1 = reduce(numpy.dot, (mo_coeff.T, mc.get_hcore(), mo_coeff)) fock = h1 + eris.vhf_c + vj - vk * .5 return fock
def ao2mo(self, mo): t0 = (time.clock(), time.time()) ncore = self.ncore log = pyscf.lib.logger.Logger(self.stdout, self.verbose) # using dm=[], a hacky call to dfhf.get_jk, to generate self._cderi self.get_jk(self.mol, []) if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('Generate density fitting integrals', *t0) eris = mc_ao2mo._ERIS(self, mo, 'incore', level=2) t0 = (time.clock(), time.time()) mo = numpy.asarray(mo, order='F') nao, nmo = mo.shape eris.j_pc = numpy.zeros((nmo,ncore)) k_cp = numpy.zeros((ncore,nmo)) fmmm = _ao2mo._fpointer('AO2MOmmm_nr_s2_iltj') fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv ftrans = _ao2mo._fpointer('AO2MOtranse2_nr_s2kl') bufs1 = numpy.empty((dfhf.BLOCKDIM,nmo,nmo)) with df.load(self._cderi) as feri: for b0, b1 in dfhf.prange(0, self._naoaux, dfhf.BLOCKDIM): eri1 = numpy.array(feri[b0:b1], copy=False) buf = bufs1[:b1-b0] if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('load buf %d:%d'%(b0,b1), *t1) fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p), eri1.ctypes.data_as(ctypes.c_void_p), mo.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(b1-b0), ctypes.c_int(nao), ctypes.c_int(0), ctypes.c_int(nmo), ctypes.c_int(0), ctypes.c_int(nmo), ctypes.c_void_p(0), ctypes.c_int(0)) if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('transform [%d:%d]'%(b0,b1), *t1) bufd = numpy.einsum('kii->ki', buf).copy() #:eris.j_pc += numpy.einsum('ki,kj->ij', bufd, bufd[:,:ncore]) pyscf.lib.dot(bufd.T, numpy.asarray(bufd[:,:ncore],order='C'), 1, eris.j_pc, 1) k_cp += numpy.einsum('kij,kij->ij', buf[:,:ncore], buf[:,:ncore]) if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('j_pc and k_pc', *t1) eri1 = None eris.k_pc = k_cp.T.copy() log.timer('ao2mo density fit part', *t0) return eris
def ao2mo(self, mo): # nmo = mo.shape[1] # ncore = self.ncore # ncas = self.ncas # nocc = ncore + ncas # eri = pyscf.ao2mo.incore.full(self._scf._eri, mo) # eri = pyscf.ao2mo.restore(1, eri, nmo) # eris = lambda:None # eris.j_cp = numpy.einsum('iipp->ip', eri[:ncore,:ncore,:,:]) # eris.k_cp = numpy.einsum('ippi->ip', eri[:ncore,:,:,:ncore]) # eris.vhf_c =(numpy.einsum('iipq->pq', eri[:ncore,:ncore,:,:])*2 # -numpy.einsum('ipqi->pq', eri[:ncore,:,:,:ncore])) # eris.ppaa = numpy.asarray(eri[:,:,ncore:nocc,ncore:nocc], order='C') # eris.papa = numpy.asarray(eri[:,ncore:nocc,:,ncore:nocc], order='C') # return eris return mc_ao2mo._ERIS(self, mo, method='incore', level=2)
def get_fock(mc, mo_coeff=None, ci=None, eris=None, verbose=None): '''Generalized Fock matrix ''' from pyscf.mcscf import mc_ao2mo if ci is None: ci = mc.ci if mo_coeff is None: mo_coeff = mc.mo_coeff if eris is None: eris = mc_ao2mo._ERIS(mc, mo_coeff, level=2) nmo = mo_coeff.shape[1] ncas = mc.ncas nelecas = mc.nelecas casdm1 = mc.fcisolver.make_rdm1(ci, ncas, nelecas) vj = numpy.empty((nmo,nmo)) vk = numpy.empty((nmo,nmo)) for i in range(nmo): vj[i] = numpy.einsum('ij,qij->q', casdm1, eris.ppaa[i]) vk[i] = numpy.einsum('ij,iqj->q', casdm1, eris.papa[i]) h1 = reduce(numpy.dot, (mo_coeff.T, mc.get_hcore(), mo_coeff)) fock = h1 + eris.vhf_c + vj - vk * .5 return fock
def ao2mo(self, mo): ncore = self.ncore #self._cderi = None # FIXME? leave as much memory as possible for mc_ao2mo eris = mc_ao2mo._ERIS(self, mo, 'incore', 2) # using dm=[], a hacky call to dfhf.get_jk, to generate self._cderi t0 = (time.clock(), time.time()) log = pyscf.lib.logger.Logger(self.stdout, self.verbose) self.get_jk(self.mol, []) if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('Generate density fitting integrals', *t0) mo = numpy.asarray(mo, order='F') nao, nmo = mo.shape eris.j_cp = numpy.zeros((ncore,nmo)) eris.k_cp = numpy.zeros((ncore,nmo)) fmmm = _ao2mo._fpointer('AO2MOmmm_nr_s2_iltj') fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv ftrans = _ao2mo._fpointer('AO2MOtranse2_nr_s2kl') with df.load(self._cderi) as feri: for b0, b1 in dfhf.prange(0, self._naoaux, dfhf.BLOCKDIM): eri1 = numpy.array(feri[b0:b1], copy=False) buf = numpy.empty((b1-b0,nmo,nmo)) if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('load buf %d:%d'%(b0,b1), *t1) fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p), eri1.ctypes.data_as(ctypes.c_void_p), mo.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(b1-b0), ctypes.c_int(nao), ctypes.c_int(0), ctypes.c_int(nmo), ctypes.c_int(0), ctypes.c_int(nmo), ctypes.c_void_p(0), ctypes.c_int(0)) if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('transform [%d:%d]'%(b0,b1), *t1) bufd = numpy.einsum('kii->ki', buf).copy() #:eris.j_cp += numpy.einsum('ki,kj->ij', bufd[:,:ncore], bufd) pyscf.lib.dot(bufd[:,:ncore].T.copy(), bufd, 1, eris.j_cp, 1) eris.k_cp += numpy.einsum('kij,kij->ij', buf[:,:ncore], buf[:,:ncore]) if log.verbose >= pyscf.lib.logger.DEBUG1: t1 = log.timer('j_cp and k_cp', *t1) return eris
def get_pdft_veff(self, mo=None, ci=None, incl_coul=False, paaa_only=False): ''' Get the 1- and 2-body MC-PDFT effective potentials for a set of mos and ci vectors Kwargs: mo : ndarray of shape (nao,nmo) A full set of molecular orbital coefficients. Taken from self if not provided ci : list or ndarray CI vectors. Taken from self if not provided incl_coul : logical If true, includes the Coulomb repulsion energy in the 1-body effective potential. In practice they always appear together. paaa_only : logical If true, only the paaa 2-body effective potential elements are evaluated; the rest of ppaa are filled with zeros. Returns: veff1 : ndarray of shape (nao, nao) 1-body effective potential in the AO basis May include classical Coulomb potential term (see incl_coul kwarg) veff2 : pyscf.mcscf.mc_ao2mo._ERIS instance Relevant 2-body effective potential in the MO basis ''' t0 = (time.clock(), time.time()) if mo is None: mo = self.mo_coeff if ci is None: ci = self.ci # If ci is not a list and mc is a state-average solver, use a different fcisolver for make_rdm mc_1root = self if isinstance(self, StateAverageMCSCFSolver) and not isinstance( ci, list): mc_1root = mcscf.CASCI(self._scf, self.ncas, self.nelecas) mc_1root.fcisolver = fci.solver(self._scf.mol, singlet=False, symm=False) mc_1root.mo_coeff = mo mc_1root.ci = ci mc_1root.e_tot = self.e_tot dm1s = np.asarray(mc_1root.make_rdm1s()) adm1s = np.stack(mc_1root.fcisolver.make_rdm1s( ci, self.ncas, self.nelecas), axis=0) adm2 = get_2CDM_from_2RDM( mc_1root.fcisolver.make_rdm12(ci, self.ncas, self.nelecas)[1], adm1s) mo_cas = mo[:, self.ncore:][:, :self.ncas] pdft_veff1, pdft_veff2 = pdft_veff.kernel( self.otfnal, adm1s, adm2, mo, self.ncore, self.ncas, max_memory=self.max_memory, paaa_only=paaa_only) if self.verbose > logger.DEBUG: logger.debug( self, 'Warning: memory-intensive lazy kernel for pdft_veff initiated for ' 'testing purposes; reduce verbosity to decrease memory footprint' ) pdft_veff1_test, _pdft_veff2_test = pdft_veff.lazy_kernel( self.otfnal, dm1s, adm2, mo_cas) old_eri = self._scf._eri self._scf._eri = _pdft_veff2_test with temporary_env(self.mol, incore_anyway=True): pdft_veff2_test = mc_ao2mo._ERIS(self, mo, method='incore') self._scf._eri = old_eri err = linalg.norm(pdft_veff1 - pdft_veff1_test) logger.debug(self, 'veff1 error: {}'.format(err)) err = linalg.norm(pdft_veff2.vhf_c - pdft_veff2_test.vhf_c) logger.debug(self, 'veff2.vhf_c error: {}'.format(err)) err = linalg.norm(pdft_veff2.papa - pdft_veff2_test.papa) logger.debug(self, 'veff2.ppaa error: {}'.format(err)) err = linalg.norm(pdft_veff2.papa - pdft_veff2_test.papa) logger.debug(self, 'veff2.papa error: {}'.format(err)) err = linalg.norm(pdft_veff2.j_pc - pdft_veff2_test.j_pc) logger.debug(self, 'veff2.j_pc error: {}'.format(err)) err = linalg.norm(pdft_veff2.k_pc - pdft_veff2_test.k_pc) logger.debug(self, 'veff2.k_pc error: {}'.format(err)) if incl_coul: pdft_veff1 += self.get_jk(self.mol, dm1s[0] + dm1s[1])[0] logger.timer(self, 'get_pdft_veff', *t0) return pdft_veff1, pdft_veff2
def get_pdft_veff (self, mo=None, ci=None, casdm1s=None, casdm2=None, incl_coul=False, paaa_only=False, aaaa_only=False): ''' Get the 1- and 2-body MC-PDFT effective potentials for a set of mos and ci vectors Kwargs: mo : ndarray of shape (nao,nmo) A full set of molecular orbital coefficients. Taken from self if not provided ci : list or ndarray CI vectors. Taken from self if not provided casdm1s : ndarray of shape (2,ncas,ncas) Spin-separated 1-RDM in the active space. Overrides CI if and only if both this and casdm2 are provided casdm2 : ndarray of shape (ncas,ncas,ncas,ncas) 2-RDM in the active space. Overrides CI if and only if both this and casdm1s are provided incl_coul : logical If true, includes the Coulomb repulsion energy in the 1-body effective potential. In practice they always appear together. paaa_only : logical If true, only the paaa 2-body effective potential elements are evaluated; the rest of ppaa are filled with zeros. aaaa_only : logical If true, only the aaaa 2-body effective potential elements are evaluated; the rest of ppaa are filled with zeros. Returns: veff1 : ndarray of shape (nao, nao) 1-body effective potential in the AO basis May include classical Coulomb potential term (see incl_coul kwarg) veff2 : pyscf.mcscf.mc_ao2mo._ERIS instance Relevant 2-body effective potential in the MO basis ''' t0 = (time.process_time (), time.time ()) if mo is None: mo = self.mo_coeff if ci is None: ci = self.ci ncore, ncas, nelecas = self.ncore, self.ncas, self.nelecas nocc = ncore + ncas if (casdm1s is not None) and (casdm2 is not None): mo_core = mo[:,:ncore] mo_cas = mo[:,ncore:nocc] dm1s = np.dot (mo_cas, casdm1s).transpose (1,0,2) dm1s = np.dot (dm1s, mo_cas.conj ().T) dm1s += (mo_core @ mo_core.conj ().T)[None,:,:] adm1s = casdm1s adm2 = get_2CDM_from_2RDM (casdm2, casdm1s) else: dm_list = self.make_rdms_mcpdft (mo_coeff=mo, ci=ci) dm1s, (adm1s, (adm2, _ss, _os)) = dm_list mo_cas = mo[:,ncore:][:,:ncas] pdft_veff1, pdft_veff2 = pdft_veff.kernel (self.otfnal, adm1s, adm2, mo, ncore, ncas, max_memory=self.max_memory, paaa_only=paaa_only, aaaa_only=aaaa_only) if self.verbose > logger.DEBUG: logger.debug (self, 'Warning: memory-intensive lazy kernel for pdft_veff initiated for ' 'testing purposes; reduce verbosity to decrease memory footprint') pdft_veff1_test, _pdft_veff2_test = pdft_veff.lazy_kernel (self.otfnal, dm1s, adm2, mo_cas) old_eri = self._scf._eri self._scf._eri = _pdft_veff2_test with temporary_env (self.mol, incore_anyway=True): pdft_veff2_test = mc_ao2mo._ERIS (self, mo, method='incore') self._scf._eri = old_eri err = linalg.norm (pdft_veff1 - pdft_veff1_test) logger.debug (self, 'veff1 error: {}'.format (err)) err = linalg.norm (pdft_veff2.vhf_c - pdft_veff2_test.vhf_c) logger.debug (self, 'veff2.vhf_c error: {}'.format (err)) err = linalg.norm (pdft_veff2.papa - pdft_veff2_test.papa) logger.debug (self, 'veff2.ppaa error: {}'.format (err)) err = linalg.norm (pdft_veff2.papa - pdft_veff2_test.papa) logger.debug (self, 'veff2.papa error: {}'.format (err)) err = linalg.norm (pdft_veff2.j_pc - pdft_veff2_test.j_pc) logger.debug (self, 'veff2.j_pc error: {}'.format (err)) err = linalg.norm (pdft_veff2.k_pc - pdft_veff2_test.k_pc) logger.debug (self, 'veff2.k_pc error: {}'.format (err)) if incl_coul: pdft_veff1 += self._scf.get_j (self.mol, dm1s[0] + dm1s[1]) logger.timer (self, 'get_pdft_veff', *t0) return pdft_veff1, pdft_veff2
def cas_natorb(mc, mo_coeff=None, ci=None, eris=None, sort=False, verbose=None): '''Transform active orbitals to natrual orbitals, and update the CI wfn Args: mc : a CASSCF/CASCI object or RHF object sort : bool Sort natural orbitals wrt the occupancy. Be careful with this option since the resultant natural orbitals might have the different symmetry to the irreps indicated by CASSCF.orbsym Returns: A tuple, the first item is natural orbitals, the second is updated CI coefficients, the third is the natural occupancy associated to the natural orbitals. ''' from pyscf.mcscf import mc_ao2mo from pyscf.tools import dump_mat if isinstance(verbose, logger.Logger): log = verbose else: log = logger.Logger(mc.stdout, mc.verbose) if mo_coeff is None: mo_coeff = mc.mo_coeff if ci is None: ci = mc.ci if eris is None: eris = mc_ao2mo._ERIS(mc, mo_coeff, level=2) ncore = mc.ncore ncas = mc.ncas nocc = ncore + ncas nelecas = mc.nelecas casdm1 = mc.fcisolver.make_rdm1(ci, ncas, nelecas) occ, ucas = mc._eig(-casdm1, ncore, nocc) if sort: idx = numpy.argsort(occ) occ = occ[idx] ucas = ucas[:,idx] if hasattr(mc, 'orbsym'): # for casci_symm mc.orbsym[ncore:nocc] = mc.orbsym[ncore:nocc][idx] mc.fcisolver.orbsym = mc.orbsym[ncore:nocc] occ = -occ # where_natorb gives the location of the natural orbital for the input cas # orbitals. gen_strings4orblist map thes sorted strings (on CAS orbital) to # the unsorted determinant strings (on natural orbital). e.g. (3o,2e) system # CAS orbital 1 2 3 # natural orbital 3 1 2 <= by mo_1to1map # CASorb-strings 0b011, 0b101, 0b110 # == (1,2), (1,3), (2,3) # natorb-strings (3,1), (3,2), (1,2) # == 0B101, 0B110, 0B011 <= by gen_strings4orblist # then argsort to translate the string representation to the address # [2(=0B011), 0(=0B101), 1(=0B110)] # to indicate which CASorb-strings address to be loaded in each natorb-strings slot where_natorb = mo_1to1map(ucas) #guide_stringsa = fci.cistring.gen_strings4orblist(where_natorb, nelecas[0]) #guide_stringsb = fci.cistring.gen_strings4orblist(where_natorb, nelecas[1]) #old_det_idxa = numpy.argsort(guide_stringsa) #old_det_idxb = numpy.argsort(guide_stringsb) #ci0 = ci[old_det_idxa[:,None],old_det_idxb] if isinstance(ci, numpy.ndarray): ci0 = fci.addons.reorder(ci, nelecas, where_natorb) elif isinstance(ci, (tuple, list)) and isinstance(ci[0], numpy.ndarray): # for state-average eigenfunctions ci0 = [fci.addons.reorder(x, nelecas, where_natorb) for x in ci] else: log.info('FCI vector not available, so not using old wavefunction as initial guess') ci0 = None # restore phase, to ensure the reordered ci vector is the correct initial guess for i, k in enumerate(where_natorb): if ucas[i,k] < 0: ucas[:,k] *= -1 mo_coeff1 = mo_coeff.copy() mo_coeff1[:,ncore:nocc] = numpy.dot(mo_coeff[:,ncore:nocc], ucas) if log.verbose >= logger.INFO: log.debug('where_natorb %s', str(where_natorb)) log.info('Natural occ %s', str(occ)) log.info('Natural orbital in CAS space') label = mc.mol.spheric_labels(True) dump_mat.dump_rec(log.stdout, mo_coeff1[:,ncore:nocc], label, start=1) if mc._scf.mo_coeff is not None: s = reduce(numpy.dot, (mo_coeff1[:,ncore:nocc].T, mc._scf.get_ovlp(), mc._scf.mo_coeff)) idx = numpy.argwhere(abs(s)>.4) for i,j in idx: log.info('<CAS-nat-orb|mo-hf> %d %d %12.8f', ncore+i+1, j+1, s[i,j]) h1eff =(reduce(numpy.dot, (mo_coeff[:,ncore:nocc].T, mc.get_hcore(), mo_coeff[:,ncore:nocc])) + eris.vhf_c[ncore:nocc,ncore:nocc]) h1eff = reduce(numpy.dot, (ucas.T, h1eff, ucas)) aaaa = numpy.asarray(eris.ppaa[ncore:nocc,ncore:nocc,:,:], order='C') aaaa = ao2mo.incore.full(ao2mo.restore(8, aaaa, ncas), ucas) e_cas, fcivec = mc.fcisolver.kernel(h1eff, aaaa, ncas, nelecas, ci0=ci0) log.debug('In Natural orbital, CI energy = %.12g', e_cas) return mo_coeff1, fcivec, occ