Пример #1
0
    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')
Пример #2
0
    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)
Пример #3
0
 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
Пример #4
0
Файл: df.py Проект: matk86/pyscf
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
Пример #5
0
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
Пример #6
0
        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
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
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
Пример #10
0
        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
Пример #11
0
        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
Пример #12
0
    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
Пример #13
0
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