Пример #1
0
def grad_elec(mfg, mo_energy=None, mo_coeff=None, mo_occ=None):
    t0 = (time.clock(), time.time())
    mf = mfg._scf
    mol = mfg.mol
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_occ is None:    mo_occ = mf.mo_occ
    if mo_coeff is None:  mo_coeff = mf.mo_coeff
    h1 = mfg.get_hcore(mol)
    s1 = mfg.get_ovlp(mol)
    dm0 = mf.make_rdm1(mf.mo_coeff, mf.mo_occ)
    vhf = mfg.get_veff(mol, dm0)
    log.timer(mfg, 'gradients of 2e part', *t0)
    f1 = h1 + vhf
    dme0 = mfg.make_rdm1e(mf.mo_energy, mf.mo_coeff, mf.mo_occ)
    gs = numpy.empty((mol.natm,3))
    for ia in range(mol.natm):
# h1, s1, vhf are \nabla <i|h|j>, the nuclear gradients = -\nabla
        f =-(mfg.matblock_by_atom(mol, ia, f1) + mfg._grad_rinv(mol, ia))
        s = -mfg.matblock_by_atom(mol, ia, s1)
        v = numpy.einsum('ij,kji->k', dm0, f) \
          - numpy.einsum('ij,kji->k', dme0, s)
        gs[ia] = 2 * v.real
    log.debug(mfg, 'gradients of electronic part')
    log.debug(mfg, str(gs))
    return gs
Пример #2
0
        def kernel(self, mo_coeff=None, mo_occ=None):
            if mo_coeff is None:
                mo_coeff = self.mo_coeff
            if mo_occ is None:
                mo_occ = self.mo_occ
            cput0 = (time.clock(), time.time())

            self.build(self.mol)
            self.dump_flags()

            if mo_coeff is None or mo_occ is None:
                logger.debug(self, 'Initial guess orbitals not given. '
                             'Generating initial guess from %s density matrix',
                             self.init_guess)
                dm = mf.get_init_guess(self.mol, self.init_guess)
                mo_coeff, mo_occ = self.from_dm(dm)
            # save initial guess because some methods may access them
            self.mo_coeff = mo_coeff
            self.mo_occ = mo_occ

            self.converged, self.e_tot, \
                    self.mo_energy, self.mo_coeff, self.mo_occ = \
                    kernel(self, mo_coeff, mo_occ, conv_tol=self.conv_tol,
                           conv_tol_grad=self.conv_tol_grad,
                           max_cycle=self.max_cycle,
                           callback=self.callback, verbose=self.verbose)

            logger.timer(self, 'Second order SCF', *cput0)
            self._finalize()
            return self.e_tot
Пример #3
0
def solve_mo1(sscobj, mo_energy=None, mo_coeff=None, mo_occ=None,
              h1=None, s1=None, with_cphf=None):
    cput1 = (time.clock(), time.time())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    if mo_energy is None: mo_energy = sscobj._scf.mo_energy
    if mo_coeff  is None: mo_coeff = sscobj._scf.mo_coeff
    if mo_occ    is None: mo_occ = sscobj._scf.mo_occ
    if with_cphf is None: with_cphf = sscobj.cphf

    mol = sscobj.mol
    if h1 is None:
        atmlst = sorted(set([j for i,j in sscobj.nuc_pair]))
        h1 = numpy.asarray(make_h1_pso(mol, mo_coeff, mo_occ, atmlst))

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(sscobj._scf, mo_coeff, mo_occ)
        mo1, mo_e1 = cphf.solve(vind, mo_energy, mo_occ, h1, None,
                                sscobj.max_cycle_cphf, sscobj.conv_tol,
                                verbose=log)
    else:
        e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ>0], mo_energy[mo_occ==0])
        mo1 = h1 * (1 / e_ai)
        mo_e1 = None
    logger.timer(sscobj, 'solving mo1 eqn', *cput1)
    return mo1, mo_e1
Пример #4
0
    def init_amps(self, eris=None):
        time0 = time.clock(), time.time()
        if eris is None:
            eris = self.ao2mo(self.mo_coeff)
        nocca, noccb = self.nocc

        fova = eris.focka[:nocca,nocca:]
        fovb = eris.fockb[:noccb,noccb:]
        mo_ea_o = eris.mo_energy[0][:nocca]
        mo_ea_v = eris.mo_energy[0][nocca:]
        mo_eb_o = eris.mo_energy[1][:noccb]
        mo_eb_v = eris.mo_energy[1][noccb:]
        eia_a = lib.direct_sum('i-a->ia', mo_ea_o, mo_ea_v)
        eia_b = lib.direct_sum('i-a->ia', mo_eb_o, mo_eb_v)

        t1a = fova.conj() / eia_a
        t1b = fovb.conj() / eia_b

        eris_ovov = np.asarray(eris.ovov)
        eris_OVOV = np.asarray(eris.OVOV)
        eris_ovOV = np.asarray(eris.ovOV)
        t2aa = eris_ovov.transpose(0,2,1,3) / lib.direct_sum('ia+jb->ijab', eia_a, eia_a)
        t2ab = eris_ovOV.transpose(0,2,1,3) / lib.direct_sum('ia+jb->ijab', eia_a, eia_b)
        t2bb = eris_OVOV.transpose(0,2,1,3) / lib.direct_sum('ia+jb->ijab', eia_b, eia_b)
        t2aa = t2aa - t2aa.transpose(0,1,3,2)
        t2bb = t2bb - t2bb.transpose(0,1,3,2)
        e  =      np.einsum('iJaB,iaJB', t2ab, eris_ovOV)
        e += 0.25*np.einsum('ijab,iajb', t2aa, eris_ovov)
        e -= 0.25*np.einsum('ijab,ibja', t2aa, eris_ovov)
        e += 0.25*np.einsum('ijab,iajb', t2bb, eris_OVOV)
        e -= 0.25*np.einsum('ijab,ibja', t2bb, eris_OVOV)
        self.emp2 = e.real
        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2)
        logger.timer(self, 'init mp2', *time0)
        return self.emp2, (t1a,t1b), (t2aa,t2ab,t2bb)
Пример #5
0
    def shielding(self, mo1=None):
        cput0 = (time.clock(), time.time())
        self.dump_flags()
        if self.verbose >= logger.WARN:
            self.check_sanity()

        t0 = (time.clock(), time.time())
        unit_ppm = nist.ALPHA**2 * 1e6
        msc_dia = self.dia() * unit_ppm
        t0 = logger.timer(self, 'h11', *t0)
        msc_para, para_pos, para_neg, para_occ = \
                [x*unit_ppm for x in self.para(mo10=mo1)]
        e11 = msc_para + msc_dia

        logger.timer(self, 'NMR shielding', *cput0)
        if self.verbose > logger.QUIET:
            for i, atm_id in enumerate(self.shielding_nuc):
                rhf_nmr._write(self.stdout, e11[i],
                               '\ntotal shielding of atom %d %s'
                               % (atm_id, self.mol.atom_symbol(atm_id)))
                rhf_nmr._write(self.stdout, msc_dia[i], 'dia-magnetism')
                rhf_nmr._write(self.stdout, msc_para[i], 'para-magnetism')
                if self.verbose >= logger.INFO:
                    rhf_nmr._write(self.stdout, para_occ[i], 'occ part of para-magnetism')
                    rhf_nmr._write(self.stdout, para_pos[i], 'vir-pos part of para-magnetism')
                    rhf_nmr._write(self.stdout, para_neg[i], 'vir-neg part of para-magnetism')
        return e11
Пример #6
0
    def shielding(self, mo1=None):
        cput0 = (time.clock(), time.time())
        self.dump_flags()
        if self.verbose >= logger.WARN:
            self.check_sanity()

        facppm = 1e6/param.LIGHTSPEED**2
        t0 = (time.clock(), time.time())
        msc_dia = self.dia() * facppm
        t0 = logger.timer(self, 'h11', *t0)
        msc_para, para_pos, para_neg, para_occ = \
                [x*facppm for x in self.para(mo10=mo1)]
        e11 = msc_para + msc_dia

        logger.timer(self, 'NMR shielding', *cput0)
        if self.verbose > param.VERBOSE_QUIET:
            for i, atm_id in enumerate(self.shielding_nuc):
                rhf_nmr._write(self.stdout, e11[i],
                               '\ntotal shielding of atom %d %s'
                               % (atm_id, self.mol.atom_symbol(atm_id-1)))
                rhf_nmr._write(self.stdout, msc_dia[i], 'dia-magnetism')
                rhf_nmr._write(self.stdout, msc_para[i], 'para-magnetism')
                if self.verbose >= param.VERBOSE_INFO:
                    rhf_nmr._write(self.stdout, para_occ[i], 'occ part of para-magnetism')
                    rhf_nmr._write(self.stdout, para_pos[i], 'vir-pos part of para-magnetism')
                    rhf_nmr._write(self.stdout, para_neg[i], 'vir-neg part of para-magnetism')
            self.stdout.flush()
        return e11
Пример #7
0
    def init_amps(self, eris):
        time0 = time.clock(), time.time()
        nocc = self.nocc()
        nvir = self.nmo() - nocc
        nkpts = self.nkpts
        t1 = numpy.zeros((nkpts, nocc, nvir), dtype=numpy.complex128)
        t2 = numpy.zeros((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir), dtype=numpy.complex128)
        woovv = numpy.empty((nkpts, nkpts, nkpts, nocc, nocc, nvir, nvir), dtype=numpy.complex128)
        self.emp2 = 0
        foo = eris.fock[:, :nocc, :nocc].copy()
        fvv = eris.fock[:, nocc:, nocc:].copy()
        eris_oovv = eris.oovv.copy()
        eia = numpy.zeros((nocc, nvir))
        eijab = numpy.zeros((nocc, nocc, nvir, nvir))

        kconserv = self.kconserv
        for ki in range(nkpts):
            for kj in range(nkpts):
                for ka in range(nkpts):
                    kb = kconserv[ki, ka, kj]
                    eia = np.diagonal(foo[ki]).reshape(-1, 1) - np.diagonal(fvv[ka])
                    ejb = np.diagonal(foo[kj]).reshape(-1, 1) - np.diagonal(fvv[kb])
                    eijab = lib.direct_sum("ia,jb->ijab", eia, ejb)
                    woovv[ki, kj, ka] = 2 * eris_oovv[ki, kj, ka] - eris_oovv[ki, kj, kb].transpose(0, 1, 3, 2)
                    t2[ki, kj, ka] = eris_oovv[ki, kj, ka] / eijab

        t2 = numpy.conj(t2)
        self.emp2 = numpy.einsum("pqrijab,pqrijab", t2, woovv).real
        self.emp2 /= nkpts
        logger.info(self, "Init t2, MP2 energy = %.15g", self.emp2)
        logger.timer(self, "init mp2", *time0)
        return self.emp2, t1, t2
Пример #8
0
    def scf(self, dm0=None):
        cput0 = (time.clock(), time.time())
        mol = self.mol
        self.build(mol)
        self.dump_flags()
        self.converged, self.hf_energy, \
                self.mo_energy, self.mo_coeff, self.mo_occ \
                = hf.kernel(self, self.conv_tol, dm0=dm0,
                            callback=self.callback)

        logger.timer(self, 'SCF', *cput0)
        self.dump_energy(self.hf_energy, self.converged)

        # sort MOs wrt orbital energies, it should be done last.
        o_sort = numpy.argsort(self.mo_energy[self.mo_occ>0])
        v_sort = numpy.argsort(self.mo_energy[self.mo_occ==0])
        self.mo_energy = numpy.hstack((self.mo_energy[self.mo_occ>0][o_sort], \
                                       self.mo_energy[self.mo_occ==0][v_sort]))
        self.mo_coeff = numpy.hstack((self.mo_coeff[:,self.mo_occ>0][:,o_sort], \
                                      self.mo_coeff[:,self.mo_occ==0][:,v_sort]))
        nocc = len(o_sort)
        self.mo_occ[:nocc] = self.mo_occ[self.mo_occ>0][o_sort]
        self.mo_occ[nocc:] = 0

        #if self.verbose >= logger.INFO:
        #    self.analyze(self.verbose)
        return self.hf_energy
Пример #9
0
    def shielding(self, mo1=None):
        cput0 = (time.clock(), time.time())
        self.check_sanity()
        self.dump_flags()

        unit_ppm = nist.ALPHA**2 * 1e6
        msc_dia = self.dia(self.gauge_orig)

        if mo1 is None:
            self.mo10, self.mo_e10 = self.solve_mo1()
            mo1 = self.mo10
        msc_para, para_vir, para_occ = self.para(mo10=mo1)

        msc_dia *= unit_ppm
        msc_para *= unit_ppm
        para_vir *= unit_ppm
        para_occ *= unit_ppm
        e11 = msc_para + msc_dia

        logger.timer(self, 'NMR shielding', *cput0)
        if self.verbose >= logger.NOTE:
            for i, atm_id in enumerate(self.shielding_nuc):
                _write(self.stdout, e11[i],
                       '\ntotal shielding of atom %d %s' \
                       % (atm_id, self.mol.atom_symbol(atm_id)))
                _write(self.stdout, msc_dia[i], 'dia-magnetic contribution')
                _write(self.stdout, msc_para[i], 'para-magnetic contribution')
                if self.verbose >= logger.INFO:
                    _write(self.stdout, para_occ[i], 'occ part of para-magnetism')
                    _write(self.stdout, para_vir[i], 'vir part of para-magnetism')
        return e11
Пример #10
0
 def get_jk(self, mol=None, dm=None, hermi=1):
     if mol is None: mol = self.mol
     if dm is None: dm = self.make_rdm1()
     t0 = (time.clock(), time.time())
     vj, vk = get_jk(mol, dm, hermi, self.opt)
     logger.timer(self, 'vj and vk', *t0)
     return vj, vk
Пример #11
0
    def get_jk(self, mol=None, dm=None, hermi=1):
        if mol is None: mol = self.mol
        if dm is None: dm = self.make_rdm1()
        t0 = (time.clock(), time.time())
        verbose_bak, mol.verbose = mol.verbose, self.verbose
        stdout_bak,  mol.stdout  = mol.stdout , self.stdout
        if self.direct_scf and self.opt[0] is None:
            self.opt = self.init_direct_scf(mol)
        opt_llll, opt_ssll, opt_ssss, opt_gaunt = self.opt

        vj, vk = get_jk_coulomb(mol, dm, hermi, self._coulomb_now,
                                opt_llll, opt_ssll, opt_ssss)

        if self.with_breit:
            if 'SSSS' in self._coulomb_now.upper() or not self.with_ssss:
                vj1, vk1 = _call_veff_gaunt_breit(mol, dm, hermi, opt_gaunt, True)
                logger.info(self, 'Add Breit term')
                vj += vj1
                vk += vk1
        elif self.with_gaunt and 'SS' in self._coulomb_now.upper():
            logger.info(self, 'Add Gaunt term')
            vj1, vk1 = _call_veff_gaunt_breit(mol, dm, hermi, opt_gaunt, False)
            vj += vj1
            vk += vk1

        mol.verbose = verbose_bak
        mol.stdout  = stdout_bak
        logger.timer(self, 'vj and vk', *t0)
        return vj, vk
Пример #12
0
    def get_jk_(self, cell=None, dm=None, hermi=1, kpt=None, kpt_band=None):
        '''Get Coulomb (J) and exchange (K) following :func:`scf.hf.RHF.get_jk_`.

        Note the incore version, which initializes an _eri array in memory.
        '''
        if cell is None: cell = self.cell
        if dm is None: dm = self.make_rdm1()
        if kpt is None: kpt = self.kpt

        cpu0 = (time.clock(), time.time())
        vj, vk = get_jk(self, cell, dm, hermi, self.opt, kpt, kpt_band)
        # TODO: Check incore, direct_scf, _eri's, etc
        #if self._eri is not None or cell.incore_anyway or self._is_mem_enough():
        #    print "self._is_mem_enough() =", self._is_mem_enough()
        #    if self._eri is None:
        #        logger.debug(self, 'Building PBC AO integrals incore')
        #        if kpt is not None and pyscf.lib.norm(kpt) > 1.e-15:
        #            raise RuntimeError("Non-zero kpts not implemented for incore eris")
        #        self._eri = ao2mo.get_ao_eri(cell)
        #    if np.iscomplexobj(dm) or np.iscomplexobj(self._eri):
        #        vj, vk = dot_eri_dm_complex(self._eri, dm, hermi)
        #    else:
        #        vj, vk = pyscf.scf.hf.dot_eri_dm(self._eri, dm, hermi)
        #else:
        #    if self.direct_scf:
        #        self.opt = self.init_direct_scf(cell)
        #    vj, vk = get_jk(cell, dm, hermi, self.opt, kpt)
        logger.timer(self, 'vj and vk', *cpu0)
        return vj, vk
Пример #13
0
    def init_amps(self, eris):
        time0 = time.clock(), time.time()
        nocc = self.nocc()
        nvir = self.nmo() - nocc
        nkpts = self.nkpts
        t1 = numpy.zeros((nkpts,nocc,nvir), dtype=numpy.complex128)
        t2 = numpy.zeros((nkpts,nkpts,nkpts,nocc,nocc,nvir,nvir), dtype=numpy.complex128)
        self.emp2 = 0
        foo = eris.fock[:,:nocc,:nocc].copy()
        fvv = eris.fock[:,nocc:,nocc:].copy()
        eris_oovv = eris.oovv.copy()
        eia = numpy.zeros((nocc,nvir))
        eijab = numpy.zeros((nocc,nocc,nvir,nvir))

        kconserv = tools.get_kconserv(self._scf.cell,self.kpts)
        for ki in range(nkpts):
          for kj in range(nkpts):
            for ka in range(nkpts):
                kb = kconserv[ki,ka,kj]
                for i in range(nocc):
                    for a in range(nvir):
                        eia[i,a] = foo[ki,i,i] - fvv[ka,a,a]
                        for j in range(nocc):
                            for b in range(nvir):
                                eijab[i,j,a,b] = ( foo[ki,i,i] + foo[kj,j,j]
                                                 - fvv[ka,a,a] - fvv[kb,b,b] )
                                t2[ki,kj,ka,i,j,a,b] = eris_oovv[ki,kj,ka,i,j,a,b]/eijab[i,j,a,b]

        t2 = numpy.conj(t2)
        self.emp2 = 0.25*numpy.einsum('pqrijab,pqrijab',t2,eris_oovv).real
        self.emp2 /= nkpts
        logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2.real)
        logger.timer(self, 'init mp2', *time0)
        print "MP2 energy =", self.emp2
        return self.emp2, t1, t2
Пример #14
0
    def scf(self, dm0=None):
        '''main routine for SCF

        Kwargs:
            dm0 : ndarray
                If given, it will be used as the initial guess density matrix

        Examples:

        >>> import numpy
        >>> from pyscf import gto, scf
        >>> mol = gto.M(atom='H 0 0 0; F 0 0 1.1')
        >>> mf = scf.hf.SCF(mol)
        >>> dm_guess = numpy.eye(mol.nao_nr())
        >>> mf.kernel(dm_guess)
        converged SCF energy = -98.5521904482821
        -98.552190448282104
        '''
        cput0 = (time.clock(), time.time())

        self.build()
        self.dump_flags()
        self.converged, self.hf_energy, \
                self.mo_energy, self.mo_coeff, self.mo_occ = \
                kernel(self, self.conv_tol, dm0=dm0, callback=self.callback)

        logger.timer(self, 'SCF', *cput0)
        self.dump_energy(self.hf_energy, self.converged)
        #if self.verbose >= logger.INFO:
        #    self.analyze(self.verbose)
        return self.hf_energy
Пример #15
0
    def solve_mo1(self, mo_energy=None, mo_occ=None, h1=None, s1=None):
        cput1 = (time.clock(), time.time())
        log = logger.Logger(self.stdout, self.verbose)
        if mo_energy is None:
            mo_energy = self._scf.mo_energy
        if mo_occ is None:
            mo_occ = self._scf.mo_occ

        mol = self.mol
        if h1 is None:
            mo_coeff = self._scf.mo_coeff
            dm0 = self._scf.make_rdm1(mo_coeff, mo_occ)
            h1 = _mat_ao2mo(self.make_h10(mol, dm0), mo_coeff, mo_occ)
        if s1 is None:
            s1 = _mat_ao2mo(self.make_s10(mol), mo_coeff, mo_occ)

        cput1 = log.timer("first order Fock matrix", *cput1)
        if self.cphf:
            mo10, mo_e10 = cphf.solve(
                self.get_vind, mo_energy, mo_occ, h1, s1, self.max_cycle_cphf, self.conv_tol, verbose=log
            )
        else:
            mo10, mo_e10 = solve_mo1(mo_energy, mo_occ, h1, s1)
        logger.timer(self, "solving mo1 eqn", *cput1)
        return mo10, mo_e10
Пример #16
0
Файл: hf.py Проект: eronca/pyscf
    def get_jk(self, cell=None, dm=None, hermi=1, kpt=None, kpt_band=None):
        '''Get Coulomb (J) and exchange (K) following :func:`scf.hf.RHF.get_jk_`.

        Note the incore version, which initializes an _eri array in memory.
        '''
        if cell is None: cell = self.cell
        if dm is None: dm = self.make_rdm1()
        if kpt is None: kpt = self.kpt

        cpu0 = (time.clock(), time.time())

        if (kpt_band is None and
            (self.exxdiv == 'ewald' or self.exxdiv is None) and
            (self._eri is not None or cell.incore_anyway or self._is_mem_enough())):
            if self._eri is None:
                logger.debug(self, 'Building PBC AO integrals incore')
                self._eri = self.with_df.get_ao_eri(kpt, compact=True)
            vj, vk = dot_eri_dm(self._eri, dm, hermi)

            if self.exxdiv == 'ewald':
                from pyscf.pbc.df.df_jk import _ewald_exxdiv_for_G0
                # G=0 is not inculded in the ._eri integrals
                _ewald_exxdiv_for_G0(self.cell, kpt, [dm], [vk])
        else:
            vj, vk = self.with_df.get_jk(dm, hermi, kpt, kpt_band,
                                         exxdiv=self.exxdiv)

        logger.timer(self, 'vj and vk', *cpu0)
        return vj, vk
Пример #17
0
Файл: hf.py Проект: sunqm/pyscf
    def get_j(self, cell=None, dm=None, hermi=1, kpt=None, kpts_band=None):
        r'''Compute J matrix for the given density matrix and k-point (kpt).
        When kpts_band is given, the J matrices on kpts_band are evaluated.

            J_{pq} = \sum_{rs} (pq|rs) dm[s,r]

        where r,s are orbitals on kpt. p and q are orbitals on kpts_band
        if kpts_band is given otherwise p and q are orbitals on kpt.
        '''
        #return self.get_jk(cell, dm, hermi, kpt, kpts_band)[0]
        if cell is None: cell = self.cell
        if dm is None: dm = self.make_rdm1()
        if kpt is None: kpt = self.kpt

        cpu0 = (time.clock(), time.time())
        dm = np.asarray(dm)
        nao = dm.shape[-1]

        if (kpts_band is None and
            (self._eri is not None or cell.incore_anyway or
             (not self.direct_scf and self._is_mem_enough()))):
            if self._eri is None:
                logger.debug(self, 'Building PBC AO integrals incore')
                self._eri = self.with_df.get_ao_eri(kpt, compact=True)
            vj, vk = mol_hf.dot_eri_dm(self._eri, dm.reshape(-1,nao,nao), hermi)
        else:
            vj = self.with_df.get_jk(dm.reshape(-1,nao,nao), hermi,
                                     kpt, kpts_band, with_k=False)[0]
        logger.timer(self, 'vj', *cpu0)
        return _format_jks(vj, dm, kpts_band)
Пример #18
0
 def init_amps(self, eris):
     time0 = time.clock(), time.time()
     mo_e = eris.fock.diagonal()
     nocc = self.nocc()
     nvir = mo_e.size - nocc
     t1 = np.zeros((nocc,nvir), eris.dtype)
     #eia = mo_e[:nocc,None] - mo_e[None,nocc:]
     #t1 = eris.fock[:nocc,nocc:] / eia
     t2 = np.zeros((nocc,nocc,nvir,nvir), eris.dtype)
     self.emp2 = 0
     foo = eris.fock[:nocc,:nocc]
     fvv = eris.fock[nocc:,nocc:]
     eia = np.zeros((nocc,nvir))
     eijab = np.zeros((nocc,nocc,nvir,nvir))
     for i in range(nocc):
         for a in range(nvir):
             eia[i,a] = (foo[i,i] - fvv[a,a]).real
             for j in range(nocc):
                 for b in range(nvir):
                     eijab[i,j,a,b] = ( foo[i,i] + foo[j,j]
                                      - fvv[a,a] - fvv[b,b] ).real
                     t2[i,j,a,b] = eris.oovv[i,j,a,b]/eijab[i,j,a,b]
     eris_oovv = _cp(eris.oovv)
     self.emp2 = 0.25*einsum('ijab,ijab',t2,eris_oovv.conj()).real
     logger.info(self, 'Init t2, MP2 energy = %.15g', self.emp2)
     logger.timer(self, 'init mp2', *time0)
     return self.emp2, t1, t2
Пример #19
0
 def get_jk(self, mol=None, dm=None, hermi=0):
     if mol is None: mol = self.mol
     if dm is None: dm = self._scf.make_rdm1()
     cpu0 = (time.clock(), time.time())
     #TODO: direct_scf opt
     vj, vk = get_jk(mol, dm)
     logger.timer(self, 'vj and vk', *cpu0)
     return vj, vk
Пример #20
0
 def get_jk(self, cell=None, dm_kpts=None, hermi=1, kpts=None, kpt_band=None):
     if cell is None: cell = self.cell
     if kpts is None: kpts = self.kpts
     if dm_kpts is None: dm_kpts = self.make_rdm1()
     cpu0 = (time.clock(), time.time())
     vj, vk = self.with_df.get_jk(dm_kpts, hermi, kpts, kpt_band,
                                  exxdiv=self.exxdiv)
     logger.timer(self, 'vj and vk', *cpu0)
     return vj, vk
Пример #21
0
 def get_j(self, cell=None, dm_kpts=None, hermi=1, kpts=None, kpt_band=None):
     if cell is None: cell = self.cell
     if kpts is None: kpts = self.kpts
     if dm_kpts is None: dm_kpts = self.make_rdm1()
     cpu0 = (time.clock(), time.time())
     vj = self.with_df.get_jk(dm_kpts, hermi, kpts, kpt_band,
                              with_k=False)[0]
     logger.timer(self, 'vj', *cpu0)
     return vj
Пример #22
0
def write_chk(mc, root, chkfile):

    t0 = (time.clock(), time.time())
    fh5 = h5py.File(chkfile, "w")

    if mc.fcisolver.nroots > 1:
        mc.mo_coeff, _, mc.mo_energy = mc.canonicalize(mc.mo_coeff, ci=root)

    fh5["mol"] = format(mc.mol.pack())
    fh5["mc/mo"] = mc.mo_coeff
    fh5["mc/ncore"] = mc.ncore
    fh5["mc/ncas"] = mc.ncas
    nvirt = mc.mo_coeff.shape[1] - mc.ncas - mc.ncore
    fh5["mc/nvirt"] = nvirt
    fh5["mc/nelecas"] = mc.nelecas
    fh5["mc/root"] = root
    fh5["mc/orbe"] = mc.mo_energy
    if hasattr(mc, "orbsym"):
        fh5.create_dataset("mc/orbsym", data=mc.orbsym)
    else:
        fh5.create_dataset("mc/orbsym", data=[])

    mo_core = mc.mo_coeff[:, : mc.ncore]
    mo_cas = mc.mo_coeff[:, mc.ncore : mc.ncore + mc.ncas]
    mo_virt = mc.mo_coeff[:, mc.ncore + mc.ncas :]
    core_dm = numpy.dot(mo_core, mo_core.T) * 2
    core_vhf = mc.get_veff(mc.mol, core_dm)
    h1e_Sr = reduce(numpy.dot, (mo_virt.T, mc.get_hcore() + core_vhf, mo_cas))
    h1e_Si = reduce(numpy.dot, (mo_cas.T, mc.get_hcore() + core_vhf, mo_core))
    fh5["h1e_Si"] = h1e_Si
    fh5["h1e_Sr"] = h1e_Sr
    h1e = mc.h1e_for_cas()
    fh5["h1e"] = h1e[0]

    if mc._scf._eri is None:
        from pyscf.scf import _vhf

        eri = _vhf.int2e_sph(mc.mol._atm, mol._bas, mol._env)
    else:
        eri = mc._scf._eri

    # FIXME
    # add outcore later

    h2e = ao2mo.incore.general(eri, [mo_cas, mo_cas, mo_cas, mo_cas], compact=False)
    h2e = h2e.reshape(mc.ncas, mc.ncas, mc.ncas, mc.ncas)
    fh5["h2e"] = h2e
    h2e_Sr = ao2mo.incore.general(eri, [mo_virt, mo_cas, mo_cas, mo_cas], compact=False)
    h2e_Sr = h2e_Sr.reshape(nvirt, mc.ncas, mc.ncas, mc.ncas)
    fh5["h2e_Sr"] = h2e_Sr
    h2e_Si = ao2mo.incore.general(eri, [mo_cas, mo_core, mo_cas, mo_cas], compact=False)
    h2e_Si = h2e_Si.reshape(mc.ncas, mc.ncore, mc.ncas, mc.ncas)
    fh5["h2e_Si"] = h2e_Si

    fh5.close()

    logger.timer(mc, "Write MPS NEVPT integral", *t0)
Пример #23
0
 def get_jk_(self, mol=None, dm=None, hermi=1):
     if mol is None: mol = self.mol
     if dm is None: dm = self.make_rdm1()
     t0 = (time.clock(), time.time())
     if self.direct_scf and self.opt is None:
         self.opt = self.init_direct_scf(mol)
     vj, vk = get_jk(mol, dm, hermi, self.opt)
     logger.timer(self, 'vj and vk', *t0)
     return vj, vk
Пример #24
0
 def get_jk(self, cell=None, dm_kpts=None, hermi=1, kpt=None, kpt_band=None):
     # Must use 'kpt' kwarg
     if cell is None: cell = self.cell
     if kpt is None: kpt = self.kpts
     kpts = kpt
     if dm_kpts is None: dm_kpts = self.make_rdm1()
     cpu0 = (time.clock(), time.time())
     vj, vk = get_jk(self, cell, dm_kpts, kpts, kpt_band)
     logger.timer(self, 'vj and vk', *cpu0)
     return vj, vk
Пример #25
0
 def get_jk(self, mol=None, dm=None, hermi=1):
     '''Compute J, K matrices for the given density matrix.
     See :func:`scf.hf.get_jk`
     '''
     if mol is None: mol = self.mol
     if dm is None: dm = self.make_rdm1()
     cpu0 = (time.clock(), time.time())
     vj, vk = get_jk(mol, dm, hermi, self.opt)
     logger.timer(self, 'vj and vk', *cpu0)
     return vj, vk
Пример #26
0
def get_veff(ks, cell=None, dm=None, dm_last=0, vhf_last=0, hermi=1,
             kpts=None, kpt_band=None):
    '''Coulomb + XC functional for UKS.  See pyscf/pbc/dft/uks.py
    :func:`get_veff` fore more details.
    '''
    if cell is None: cell = ks.cell
    if dm is None: dm = ks.make_rdm1()
    if kpts is None: kpts = ks.kpts
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.build()
        small_rho_cutoff = ks.small_rho_cutoff
        t0 = logger.timer(ks, 'setting up grids', *t0)
    else:
        small_rho_cutoff = 0

    dm = np.asarray(dm)
    nao = dm.shape[-1]
    # ndim = 4 : dm.shape = (alpha_beta, nkpts, nao, nao)
    ground_state = (dm.ndim == 4 and kpt_band is None)
    nkpts = len(kpts)

    if hermi == 2:  # because rho = 0
        n, ks._exc, vx = 0, 0, 0
    else:
        n, ks._exc, vx = ks._numint.nr_uks(cell, ks.grids, ks.xc, dm, 1,
                                           kpts, kpt_band)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    hyb = ks._numint.hybrid_coeff(ks.xc, spin=(cell.spin>0)+1)
    if abs(hyb) < 1e-10:
        vj = ks.get_j(cell, dm, hermi, kpts, kpt_band)
        vhf = lib.asarray([vj[0]+vj[1]] * 2)
    else:
        vj, vk = ks.get_jk(cell, dm, hermi, kpts, kpt_band)
        vhf = pbcuhf._makevhf(vj, vk*hyb)

        if ground_state:
            ks._exc -= (np.einsum('Kij,Kji', dm[0], vk[0]) +
                        np.einsum('Kij,Kji', dm[1], vk[1])).real * .5 * hyb * (1./nkpts)

    if ground_state:
        ks._ecoul = np.einsum('Kij,Kji', dm[0]+dm[1], vj[0]+vj[1]).real * .5 * (1./nkpts)

    if small_rho_cutoff > 1e-20 and ground_state:
        # Filter grids the first time setup grids
        idx = ks._numint.large_rho_indices(cell, dm, ks.grids,
                                           small_rho_cutoff, kpts)
        logger.debug(ks, 'Drop grids %d',
                     ks.grids.weights.size - np.count_nonzero(idx))
        ks.grids.coords  = np.asarray(ks.grids.coords [idx], order='C')
        ks.grids.weights = np.asarray(ks.grids.weights[idx], order='C')
        ks._numint.non0tab = None
    return vhf + vx
Пример #27
0
def write_chk(mc,root,chkfile):

    t0 = (time.clock(), time.time())
    fh5 = h5py.File(chkfile,'w')

    if mc.fcisolver.nroots > 1:
        mc.mo_coeff,_, mc.mo_energy = mc.canonicalize(mc.mo_coeff,ci=root)


    fh5['mol']        =       format(mc.mol.pack())
    fh5['mc/mo']      =       mc.mo_coeff 
    fh5['mc/ncore']   =       mc.ncore    
    fh5['mc/ncas']    =       mc.ncas     
    nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore
    fh5['mc/nvirt']   =       nvirt    
    fh5['mc/nelecas'] =       mc.nelecas 
    fh5['mc/root']    =       root
    fh5['mc/orbe']    =       mc.mo_energy
    if hasattr(mc, 'orbsym'):
        fh5.create_dataset('mc/orbsym',data=mc.orbsym)
    else :
        fh5.create_dataset('mc/orbsym',data=[])

    mo_core = mc.mo_coeff[:,:mc.ncore]
    mo_cas  = mc.mo_coeff[:,mc.ncore:mc.ncore+mc.ncas]
    mo_virt = mc.mo_coeff[:,mc.ncore+mc.ncas:]
    core_dm = numpy.dot(mo_core,mo_core.T) *2
    core_vhf = mc.get_veff(mc.mol,core_dm)
    h1e_Sr =  reduce(numpy.dot, (mo_virt.T,mc.get_hcore()+core_vhf , mo_cas))
    h1e_Si =  reduce(numpy.dot, (mo_cas.T, mc.get_hcore()+core_vhf , mo_core))
    fh5['h1e_Si']     =       h1e_Si   
    fh5['h1e_Sr']     =       h1e_Sr   
    h1e = mc.h1e_for_cas()
    fh5['h1e']        =       h1e[0]

    if mc._scf._eri is None:
        h2e = ao2mo.outcore.general_iofree(mc.mol, (mo_cas,mo_cas,mo_cas,mo_cas),compact=False).reshape(mc.ncas,mc.ncas,mc.ncas,mc.ncas) 
        fh5['h2e'] = h2e
        h2e_Sr = ao2mo.outcore.general_iofree(mc.mol,(mo_virt,mo_cas,mo_cas,mo_cas),compact=False).reshape(nvirt,mc.ncas,mc.ncas,mc.ncas)
        fh5['h2e_Sr'] = h2e_Sr
        h2e_Si = ao2mo.outcore.general_iofree(mc.mol,(mo_cas,mo_core,mo_cas,mo_cas),compact=False).reshape(mc.ncas,mc.ncore,mc.ncas,mc.ncas)
        fh5['h2e_Si'] = h2e_Si

    else:
        eri = mc._scf._eri
        h2e = ao2mo.incore.general(eri,[mo_cas,mo_cas,mo_cas,mo_cas],compact=False).reshape(mc.ncas,mc.ncas,mc.ncas,mc.ncas)
        fh5['h2e'] = h2e
        h2e_Sr = ao2mo.incore.general(eri,[mo_virt,mo_cas,mo_cas,mo_cas],compact=False).reshape(nvirt,mc.ncas,mc.ncas,mc.ncas)
        fh5['h2e_Sr'] = h2e_Sr
        h2e_Si = ao2mo.incore.general(eri,[mo_cas,mo_core,mo_cas,mo_cas],compact=False).reshape(mc.ncas,mc.ncore,mc.ncas,mc.ncas)
        fh5['h2e_Si'] = h2e_Si

    fh5.close()

    logger.timer(mc,'Write MPS NEVPT integral', *t0)
Пример #28
0
 def get_jk(self, mol=None, dm=None, hermi=1):
     if mol is None: mol = self.mol
     if dm is None: dm = self.make_rdm1()
     cpu0 = (time.clock(), time.time())
     if self.direct_scf and self.opt is None:
         self.opt = self.init_direct_scf(mol)
     dm = numpy.asarray(dm)
     nao = dm.shape[-1]
     vj, vk = get_jk(mol, dm.reshape(-1,nao,nao), hermi, self.opt)
     logger.timer(self, 'vj and vk', *cpu0)
     return vj.reshape(dm.shape), vk.reshape(dm.shape)
Пример #29
0
 def get_j(self, cell=None, dm=None, hermi=1, kpt=None, kpt_band=None):
     '''Compute J matrix for the given density matrix.
     '''
     #return self.get_jk(cell, dm, hermi, kpt, kpt_band)[0]
     if cell is None: cell = self.cell
     if dm is None: dm = self.make_rdm1()
     if kpt is None: kpt = self.kpt
     cpu0 = (time.clock(), time.time())
     vj = get_j(cell, dm, hermi, self.opt, kpt, kpt_band)
     logger.timer(self, 'vj', *cpu0)
     return vj
Пример #30
0
 def get_jk(self, mol=None, dm=None, hermi=1):
     if mol is None: mol = self.mol
     if dm is None: dm = self.make_rdm1()
     cpu0 = (time.clock(), time.time())
     if self._eri is not None or self._is_mem_enough():
         if self._eri is None:
             self._eri = _vhf.int2e_sph(mol._atm, mol._bas, mol._env)
         vj, vk = hf.dot_eri_dm(self._eri, dm, hermi)
     else:
         vj, vk = hf.get_jk(mol, dm, hermi, self.opt)
     logger.timer(self, 'vj and vk', *cpu0)
     return vj, vk
Пример #31
0
def get_veff(ks_grad, dm=None, kpts=None):
    mf = ks_grad.base
    cell = ks_grad.cell
    if dm is None: dm = mf.make_rdm1()
    if kpts is None: kpts = mf.kpts
    t0 = (logger.process_clock(), logger.perf_counter())

    ni = mf._numint
    if ks_grad.grids is not None:
        grids = ks_grad.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=cell.spin)

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, ks_grad.max_memory * .9 - mem_now)
    if ks_grad.grid_response:
        raise NotImplementedError
    else:
        vxc = get_vxc(ni,
                      cell,
                      grids,
                      mf.xc,
                      dm,
                      kpts,
                      max_memory=max_memory,
                      verbose=ks_grad.verbose)
    t0 = logger.timer(ks_grad, 'vxc', *t0)
    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vj = ks_grad.get_j(dm, kpts)
        vxc += vj
    else:
        vj, vk = ks_grad.get_jk(dm, kpts)
        vk *= hyb
        if abs(omega) > 1e-10:  # For range separated Coulomb operator
            with cell.with_range_coulomb(omega):
                vk += ks_grad.get_k(dm, kpts) * (alpha - hyb)
        vxc += vj - vk * .5

    return vxc
Пример #32
0
def calc_optim_veig(dscf, target_dm, 
                    target_dec=None, gvx=None, 
                    nstep=1, force_factor=1., **optim_args):
    clfn = gen_coul_loss(dscf, fock=dscf.get_fock(vhf=dscf.get_veff0()))
    dm = dscf.make_rdm1()
    if dm.ndim == 3 and isinstance(dscf, scf.uhf.UHF):
        dm = dm.sum(0)
    t_dm = torch.from_numpy(dm).requires_grad_()
    t_eig = t_make_eig(t_dm, dscf._t_ovlp_shells).requires_grad_()
    t_ec = dscf.net(t_eig.to(dscf.device))
    t_veig = torch.autograd.grad(t_ec, t_eig)[0].requires_grad_()
    t_lde = torch.from_numpy(target_dec) if target_dec is not None else None
    t_gvx = torch.from_numpy(gvx) if gvx is not None else None
    # build closure
    def closure():
        [t_vc] = torch.autograd.grad(
            t_eig, t_dm, t_veig, retain_graph=True, create_graph=True)
        loss, dldv = clfn(t_vc.detach().numpy(), target_dm)
        grad = torch.autograd.grad(
            t_vc, t_veig, torch.from_numpy(dldv), only_inputs=True)[0]
        # build closure for force loss
        if t_lde is not None and t_gvx is not None:
            t_pde = torch.tensordot(t_gvx, t_veig)
            lossde = force_factor * torch.sum((t_pde - t_lde)**2)
            grad = grad + torch.autograd.grad(lossde, t_veig, only_inputs=True)[0]
            loss = loss + lossde
        t_veig.grad = grad
        return loss
    # do the optimization
    optim = torch.optim.LBFGS([t_veig], **optim_args)
    tic = (time.process_time(), time.perf_counter())
    for _ in range(nstep):
        optim.step(closure)
        tic = logger.timer(dscf, 'LBFGS step', *tic)
    logger.note(dscf, f"optimized loss for veig = {closure()}")        
    return t_veig.detach().numpy()
Пример #33
0
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional for UKS.  See pyscf/dft/rks.py
    :func:`get_veff` fore more details.
    '''
    if mol is None: mol = ks.mol
    if dm is None: dm = ks.make_rdm1()
    if not isinstance(dm, numpy.ndarray):
        dm = numpy.asarray(dm)
    if dm.ndim == 2:  # RHF DM
        dm = numpy.asarray((dm * .5, dm * .5))
    ks.initialize_grids(mol, dm)

    t0 = (logger.process_clock(), logger.perf_counter())

    ground_state = (dm.ndim == 3 and dm.shape[0] == 2)

    ni = ks._numint
    if hermi == 2:  # because rho = 0
        n, exc, vxc = (0, 0), 0, 0
    else:
        max_memory = ks.max_memory - lib.current_memory()[0]
        n, exc, vxc = ni.nr_uks(mol,
                                ks.grids,
                                ks.xc,
                                dm,
                                max_memory=max_memory)
        if ks.nlc:
            assert 'VV10' in ks.nlc.upper()
            _, enlc, vnlc = ni.nr_rks(mol,
                                      ks.nlcgrids,
                                      ks.xc + '__' + ks.nlc,
                                      dm[0] + dm[1],
                                      max_memory=max_memory)
            exc += enlc
            vxc += vnlc
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    #enabling range-separated hybrids
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(ks.xc, spin=mol.spin)

    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vk = None
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vj', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj = ks.get_j(mol, ddm[0] + ddm[1], hermi)
            vj += vhf_last.vj
        else:
            vj = ks.get_j(mol, dm[0] + dm[1], hermi)
        vxc += vj
    else:
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vk', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = ks.get_k(mol, ddm, hermi, omega)
                vklr *= (alpha - hyb)
                vk += vklr
            vj = vj[0] + vj[1] + vhf_last.vj
            vk += vhf_last.vk
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
            vj = vj[0] + vj[1]
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = ks.get_k(mol, dm, hermi, omega)
                vklr *= (alpha - hyb)
                vk += vklr
        vxc += vj - vk

        if ground_state:
            exc -= (numpy.einsum('ij,ji', dm[0], vk[0]).real +
                    numpy.einsum('ij,ji', dm[1], vk[1]).real) * .5
    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm[0] + dm[1], vj).real * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=vj, vk=vk)
    return vxc
Пример #34
0
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional for GKS.
    '''
    if mol is None: mol = self.mol
    if dm is None: dm = ks.make_rdm1()
    t0 = (time.clock(), time.time())

    ground_state = (isinstance(dm, numpy.ndarray) and dm.ndim == 2)

    assert (hermi == 1)
    dm = numpy.asarray(dm)
    nso = dm.shape[-1]
    nao = nso // 2
    dm_a = dm[..., :nao, :nao].real
    dm_b = dm[..., nao:, nao:].real

    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        if ks.small_rho_cutoff > 1e-20 and ground_state:
            ks.grids = rks.prune_small_rho_grids_(ks, mol, dm_a + dm_b,
                                                  ks.grids)
        t0 = logger.timer(ks, 'setting up grids', *t0)
    if ks.nlc != '':
        if ks.nlcgrids.coords is None:
            ks.nlcgrids.build(with_non0tab=True)
            if ks.small_rho_cutoff > 1e-20 and ground_state:
                ks.nlcgrids = rks.prune_small_rho_grids_(
                    ks, mol, dm_a + dm_b, ks.nlcgrids)
            t0 = logger.timer(ks, 'setting up nlc grids', *t0)

    max_memory = ks.max_memory - lib.current_memory()[0]
    ni = ks._numint
    n, exc, vxc = ni.nr_uks(mol,
                            ks.grids,
                            ks.xc, (dm_a, dm_b),
                            max_memory=max_memory)
    if ks.nlc != '':
        assert ('VV10' in ks.nlc.upper())
        _, enlc, vnlc = ni.nr_rks(mol,
                                  ks.nlcgrids,
                                  ks.xc + '__' + ks.nlc,
                                  dm_a + dm_b,
                                  max_memory=max_memory)
        exc += enlc
        vxc += vnlc
    logger.debug(ks, 'nelec by numeric integration = %s', n)
    t0 = logger.timer(ks, 'vxc', *t0)
    if vxc.ndim == 4:
        raise NotImplementedError
    vxc = numpy.asarray(scipy.linalg.block_diag(*vxc), dtype=dm.dtype)

    #enabling range-separated hybrids
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(ks.xc, spin=mol.spin)

    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vk = None
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vj', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj = ks.get_j(mol, ddm, hermi)
            vj += vhf_last.vj
        else:
            vj = ks.get_j(mol, dm, hermi)
        vxc += vj
    else:
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vk', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = _get_k_lr(mol, ddm, omega, hermi)
                vklr *= (alpha - hyb)
                vk += vklr
            vj += vhf_last.vj
            vk += vhf_last.vk
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = _get_k_lr(mol, dm, omega, hermi)
                vklr *= (alpha - hyb)
                vk += vklr
        vxc += vj - vk

        if ground_state:
            exc -= numpy.einsum('ij,ji', dm, vk).real * .5
    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm, vj).real * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=vj, vk=vk)
    return vxc
Пример #35
0
def r_get_jk(dfobj, dms, hermi=1, with_j=True, with_k=True):
    '''Relativistic density fitting JK'''
    t0 = (time.clock(), time.time())
    mol = dfobj.mol
    c1 = .5 / lib.param.LIGHT_SPEED
    tao = mol.tmap()
    ao_loc = mol.ao_loc_2c()
    n2c = ao_loc[-1]

    def fjk(dm):
        dm = numpy.asarray(dm, dtype=numpy.complex128)
        fmmm = libri.RIhalfmmm_r_s2_bra_noconj
        fdrv = _ao2mo.libao2mo.AO2MOr_e2_drv
        ftrans = libri.RItranse2_r_s2
        vj = numpy.zeros_like(dm)
        vk = numpy.zeros_like(dm)
        fcopy = libri.RImmm_r_s2_transpose
        rargs = (ctypes.c_int(n2c), (ctypes.c_int * 4)(0, n2c, 0, 0),
                 tao.ctypes.data_as(ctypes.c_void_p),
                 ao_loc.ctypes.data_as(ctypes.c_void_p),
                 ctypes.c_int(mol.nbas))
        dmll = numpy.asarray(dm[:n2c, :n2c], order='C')
        dmls = numpy.asarray(dm[:n2c, n2c:], order='C') * c1
        dmsl = numpy.asarray(dm[n2c:, :n2c], order='C') * c1
        dmss = numpy.asarray(dm[n2c:, n2c:], order='C') * c1**2
        for erill, eriss in dfobj.loop():
            naux, nao_pair = erill.shape
            buf = numpy.empty((naux, n2c, n2c), dtype=numpy.complex)
            buf1 = numpy.empty((naux, n2c, n2c), dtype=numpy.complex)

            fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p),
                 erill.ctypes.data_as(ctypes.c_void_p),
                 dmll.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(naux),
                 *rargs)  # buf == (P|LL)
            rho = numpy.einsum('kii->k', buf)

            fdrv(ftrans, fcopy, buf1.ctypes.data_as(ctypes.c_void_p),
                 erill.ctypes.data_as(ctypes.c_void_p),
                 dmll.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(naux),
                 *rargs)  # buf1 == (P|LL)
            vk[:n2c, :n2c] += numpy.dot(
                buf1.reshape(-1, n2c).T, buf.reshape(-1, n2c))

            fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p),
                 eriss.ctypes.data_as(ctypes.c_void_p),
                 dmls.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(naux),
                 *rargs)  # buf == (P|LS)
            vk[:n2c, n2c:] += numpy.dot(
                buf1.reshape(-1, n2c).T, buf.reshape(-1, n2c)) * c1

            fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p),
                 eriss.ctypes.data_as(ctypes.c_void_p),
                 dmss.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(naux),
                 *rargs)  # buf == (P|SS)
            rho += numpy.einsum('kii->k', buf)
            vj[:n2c, :n2c] += lib.unpack_tril(numpy.dot(rho, erill), 1)
            vj[n2c:, n2c:] += lib.unpack_tril(numpy.dot(rho, eriss), 1) * c1**2

            fdrv(ftrans, fcopy, buf1.ctypes.data_as(ctypes.c_void_p),
                 eriss.ctypes.data_as(ctypes.c_void_p),
                 dmss.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(naux),
                 *rargs)  # buf == (P|SS)
            vk[n2c:, n2c:] += numpy.dot(
                buf1.reshape(-1, n2c).T, buf.reshape(-1, n2c)) * c1**2

            if hermi != 1:
                fdrv(ftrans, fmmm, buf.ctypes.data_as(ctypes.c_void_p),
                     erill.ctypes.data_as(ctypes.c_void_p),
                     dmsl.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(naux),
                     *rargs)  # buf == (P|SL)
                vk[n2c:, :n2c] += numpy.dot(
                    buf1.reshape(-1, n2c).T, buf.reshape(-1, n2c)) * c1
        if hermi == 1:
            vk[n2c:, :n2c] = vk[:n2c, n2c:].T.conj()
        return vj, vk

    if isinstance(dms, numpy.ndarray) and dms.ndim == 2:
        vj, vk = fjk(dms)
    else:
        vjk = [fjk(dm) for dm in dms]
        vj = numpy.array([x[0] for x in vjk])
        vk = numpy.array([x[1] for x in vjk])
    logger.timer(dfobj, 'vj and vk', *t0)
    return vj, vk
Пример #36
0
def get_veff(ks_grad, mol=None, dm=None):
    '''Coulomb + XC functional
    '''
    if mol is None: mol = ks_grad.mol
    if dm is None: dm = ks_grad.base.make_rdm1()
    t0 = (time.clock(), time.time())

    mf = ks_grad.base
    ni = mf._numint
    if ks_grad.grids is not None:
        grids = ks_grad.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    if mf.nlc != '':
        raise NotImplementedError
    #enabling range-separated hybrids
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin)

    mem_now = lib.current_memory()[0]
    max_memory = max(2000, ks_grad.max_memory * .9 - mem_now)
    if ks_grad.grid_response:
        exc, vxc = rks_grad.get_vxc_full_response(ni,
                                                  mol,
                                                  grids,
                                                  mf.xc,
                                                  dm,
                                                  max_memory=max_memory,
                                                  verbose=ks_grad.verbose)
        logger.debug1(ks_grad, 'sum(grids response) %s', exc.sum(axis=0))
    else:
        exc, vxc = rks_grad.get_vxc(ni,
                                    mol,
                                    grids,
                                    mf.xc,
                                    dm,
                                    max_memory=max_memory,
                                    verbose=ks_grad.verbose)
    t0 = logger.timer(ks_grad, 'vxc', *t0)

    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vj = ks_grad.get_j(mol, dm)
        vxc += vj
        if ks_grad.auxbasis_response:
            e1_aux = vj.aux
    else:
        vj, vk = ks_grad.get_jk(mol, dm)
        if ks_grad.auxbasis_response:
            vk_aux = vk.aux * hyb
        vk *= hyb
        if abs(omega) > 1e-10:  # For range separated Coulomb operator
            raise NotImplementedError
            vk_lr = ks_grad.get_k(mol, dm, omega=omega)
            vk += vk_lr * (alpha - hyb)
            if ks_grad.auxbasis_response:
                vk_aux += vk_lr.aux * (alpha - hyb)
        vxc += vj - vk * .5
        if ks_grad.auxbasis_response:
            e1_aux = vj.aux - vk_aux * .5

    if ks_grad.auxbasis_response:
        logger.debug1(ks_grad, 'sum(auxbasis response) %s', e1_aux.sum(axis=0))
        vxc = lib.tag_array(vxc, exc1_grid=exc, aux=e1_aux)
    else:
        vxc = lib.tag_array(vxc, exc1_grid=exc)
    return vxc
Пример #37
0
    def get_jk(self,
               dm_kpts,
               hermi=1,
               kpts=None,
               kpts_band=None,
               with_j=True,
               with_k=True,
               omega=None,
               exxdiv=None):
        if omega is not None:  # J/K for RSH functionals
            # TODO: call AFTDF.get_jk function
            raise NotImplementedError

        # Does not support to specify arbitrary kpts
        if kpts is not None and abs(kpts - self.kpts).max() > 1e-7:
            raise RuntimeError('kpts error')
        kpts = self.kpts

        if kpts_band is not None:
            raise NotImplementedError

        cpu0 = (time.clock(), time.time())
        if self.supmol is None:
            self.build()

        nkpts = kpts.shape[0]
        vhfopt = self.vhfopt
        supmol = self.supmol
        bvkcell = self.bvkcell
        phase = self.phase
        cell = self.cell_rs
        nao = cell.nao
        orig_nao = self.cell.nao

        # * dense_bvk_ao_loc are the AOs which appear in supmol (some basis
        # are removed)
        # * sparse_ao_loc has dimension (Nk,nbas), corresponding to the
        # bvkcell with all basis
        dense_bvk_ao_loc = bvkcell.ao_loc
        sparse_ao_loc = nao * np.arange(nkpts)[:, None] + cell.ao_loc[:-1]
        sparse_ao_loc = np.append(sparse_ao_loc.ravel(), nao * nkpts)
        nbands = nkpts

        if dm_kpts.ndim != 4:
            dm = dm_kpts.reshape(-1, nkpts, orig_nao, orig_nao)
        else:
            dm = dm_kpts
        n_dm = dm.shape[0]

        rs_c_coeff = cell._contr_coeff
        sc_dm = lib.einsum('nkij,pi,qj->nkpq', dm, rs_c_coeff, rs_c_coeff)
        # Utilized symmetry sc_dm[R,S] = sc_dm[S-R] = sc_dm[(S-R)%N]
        #:sc_dm = lib.einsum('Rk,nkuv,Sk->nRuSv', phase, sc_dm, phase.conj())
        sc_dm = lib.einsum('k,Sk,nkuv->nSuv', phase[0], phase.conj(), sc_dm)
        dm_translation = k2gamma.double_translation_indices(
            self.bvk_kmesh).astype(np.int32)
        dm_imag_max = abs(sc_dm.imag).max()
        is_complex_dm = dm_imag_max > 1e-6
        if is_complex_dm:
            if dm_imag_max < 1e-2:
                logger.warn(
                    self, 'DM in (BvK) cell has small imaginary part.  '
                    'It may be a signal of symmetry broken in k-point symmetry'
                )
            sc_dm = np.vstack([sc_dm.real, sc_dm.imag])
        else:
            sc_dm = sc_dm.real
        sc_dm = np.asarray(sc_dm.reshape(-1, nkpts, nao, nao), order='C')
        n_sc_dm = sc_dm.shape[0]

        dm_cond = [
            lib.condense('NP_absmax', d, sparse_ao_loc,
                         sparse_ao_loc[:cell.nbas + 1]) for d in sc_dm
        ]
        dm_cond = np.asarray(np.max(dm_cond, axis=0), order='C')
        libpbc.CVHFset_dm_cond(vhfopt._this,
                               dm_cond.ctypes.data_as(ctypes.c_void_p),
                               dm_cond.size)
        dm_cond = None

        bvk_nbas = bvkcell.nbas
        shls_slice = (0, cell.nbas, 0, bvk_nbas, 0, bvk_nbas, 0, bvk_nbas)

        if hermi:
            fdot_suffix = 's2kl'
        else:
            fdot_suffix = 's1'
        if with_j and with_k:
            fdot = 'PBCVHF_contract_jk_' + fdot_suffix
            vs = np.zeros((2, n_sc_dm, nao, nkpts, nao))
        elif with_j:
            fdot = 'PBCVHF_contract_j_' + fdot_suffix
            vs = np.zeros((1, n_sc_dm, nao, nkpts, nao))
        else:  # with_k
            fdot = 'PBCVHF_contract_k_' + fdot_suffix
            vs = np.zeros((1, n_sc_dm, nao, nkpts, nao))

        drv = libpbc.PBCVHF_direct_drv
        drv(getattr(libpbc, fdot), vs.ctypes.data_as(ctypes.c_void_p),
            sc_dm.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(n_dm),
            ctypes.c_int(nkpts), ctypes.c_int(nbands), ctypes.c_int(cell.nbas),
            self.ovlp_mask.ctypes.data_as(ctypes.c_void_p),
            self.bvk_cell_id.ctypes.data_as(ctypes.c_void_p),
            self.cell0_shl_id.ctypes.data_as(ctypes.c_void_p),
            supmol._images_loc.ctypes.data_as(ctypes.c_void_p),
            (ctypes.c_int * 8)(*shls_slice),
            dense_bvk_ao_loc.ctypes.data_as(ctypes.c_void_p),
            dm_translation.ctypes.data_as(ctypes.c_void_p), vhfopt._cintopt,
            vhfopt._this, supmol._atm.ctypes.data_as(ctypes.c_void_p),
            ctypes.c_int(supmol.natm),
            supmol._bas.ctypes.data_as(ctypes.c_void_p),
            ctypes.c_int(supmol.nbas),
            supmol._env.ctypes.data_as(ctypes.c_void_p))

        if is_complex_dm:
            vs = vs[:, :n_dm] + vs[:, n_dm:] * 1j

        if with_j and with_k:
            vj, vk = vs
        elif with_j:
            vj, vk = vs[0], None
        else:
            vj, vk = None, vs[0]
        cpu1 = logger.timer(self, 'short range part vj and vk', *cpu0)

        lr_c_coeff = self.lr_aft.cell._contr_coeff
        lr_dm = lib.einsum('nkij,pi,qj->nkpq', dm, lr_c_coeff, lr_c_coeff)
        # For rho product other than diffused-diffused block, construct LR
        # parts in terms of full ERIs and SR ERIs
        vj1, vk1 = self.lr_aft.get_jk(lr_dm,
                                      hermi,
                                      kpts,
                                      kpts_band,
                                      with_j,
                                      with_k,
                                      exxdiv=exxdiv)
        cpu1 = logger.timer(self, 'AFT-vj and AFT-vk', *cpu1)

        # expRk is almost the same to phase, except a normalization factor
        expRk = np.exp(1j * np.dot(self.bvkmesh_Ls, kpts.T))

        if with_j:
            vj = lib.einsum('npRq,pi,qj,Rk->nkij', vj, rs_c_coeff, rs_c_coeff,
                            expRk)
            vj += lib.einsum('nkpq,pi,qj->nkij', vj1, lr_c_coeff, lr_c_coeff)
            if self.purify and kpts_band is None:
                vj = _purify(vj, phase)
            if gamma_point(kpts) and dm_kpts.dtype == np.double:
                vj = vj.real
            if hermi:
                vj = (vj + vj.conj().transpose(0, 1, 3, 2)) * .5
            vj = vj.reshape(dm_kpts.shape)

        if with_k:
            vk = lib.einsum('npRq,pi,qj,Rk->nkij', vk, rs_c_coeff, rs_c_coeff,
                            expRk)
            vk += lib.einsum('nkpq,pi,qj->nkij', vk1, lr_c_coeff, lr_c_coeff)
            if self.purify and kpts_band is None:
                vk = _purify(vk, phase)
            if gamma_point(kpts) and dm_kpts.dtype == np.double:
                vk = vk.real
            if hermi:
                vk = (vk + vk.conj().transpose(0, 1, 3, 2)) * .5
            vk = vk.reshape(dm_kpts.shape)

        return vj, vk
Пример #38
0
def get_jk(mf_grad,
           mol=None,
           dm=None,
           hermi=0,
           with_j=True,
           with_k=True,
           ishf=True):
    t0 = (time.clock(), time.time())
    if mol is None: mol = mf_grad.mol
    if dm is None: dm = mf_grad.base.make_rdm1()

    with_df = mf_grad.base.with_df
    auxmol = with_df.auxmol
    if auxmol is None:
        auxmol = df.addons.make_auxmol(with_df.mol, with_df.auxbasis)
    pmol = mol + auxmol
    ao_loc = mol.ao_loc
    nbas = mol.nbas
    nauxbas = auxmol.nbas

    get_int3c_s1 = _int3c_wrapper(mol, auxmol, 'int3c2e', 's1')
    get_int3c_s2 = _int3c_wrapper(mol, auxmol, 'int3c2e', 's2ij')
    get_int3c_ip1 = _int3c_wrapper(mol, auxmol, 'int3c2e_ip1', 's1')
    get_int3c_ip2 = _int3c_wrapper(mol, auxmol, 'int3c2e_ip2', 's2ij')

    nao = mol.nao
    naux = auxmol.nao
    dms = numpy.asarray(dm)
    out_shape = dms.shape[:-2] + (3, ) + dms.shape[-2:]
    dms = dms.reshape(-1, nao, nao)
    nset = dms.shape[0]

    idx = numpy.arange(nao)
    idx = idx * (idx + 1) // 2 + idx
    dm_tril = dms + dms.transpose(0, 2, 1)
    dm_tril = lib.pack_tril(dm_tril)
    dm_tril[:, idx] *= .5

    auxslices = auxmol.aoslice_by_atom()
    aux_loc = auxmol.ao_loc
    max_memory = mf_grad.max_memory - lib.current_memory()[0]
    blksize = int(min(max(max_memory * .5e6 / 8 / (nao**2 * 3), 20), naux,
                      240))
    ao_ranges = balance_partition(aux_loc, blksize)

    if not with_k:

        # (i,j|P)
        rhoj = numpy.empty((nset, naux))
        for shl0, shl1, nL in ao_ranges:
            int3c = get_int3c_s2((0, nbas, 0, nbas, shl0, shl1))  # (i,j|P)
            p0, p1 = aux_loc[shl0], aux_loc[shl1]
            rhoj[:, p0:p1] = lib.einsum('wp,nw->np', int3c, dm_tril)
            int3c = None

        # (P|Q)
        int2c = auxmol.intor('int2c2e', aosym='s1')
        rhoj = scipy.linalg.solve(int2c, rhoj.T, sym_pos=True).T
        int2c = None

        # (d/dX i,j|P)
        vj = numpy.zeros((nset, 3, nao, nao))
        for shl0, shl1, nL in ao_ranges:
            int3c = get_int3c_ip1((0, nbas, 0, nbas, shl0, shl1))  # (i,j|P)
            p0, p1 = aux_loc[shl0], aux_loc[shl1]
            vj += lib.einsum('xijp,np->nxij', int3c, rhoj[:, p0:p1])
            int3c = None

        if mf_grad.auxbasis_response:
            # (i,j|d/dX P)
            vjaux = numpy.empty((nset, nset, 3, naux))
            for shl0, shl1, nL in ao_ranges:
                int3c = get_int3c_ip2(
                    (0, nbas, 0, nbas, shl0, shl1))  # (i,j|P)
                p0, p1 = aux_loc[shl0], aux_loc[shl1]
                vjaux[:, :, :, p0:p1] = lib.einsum('xwp,mw,np->mnxp', int3c,
                                                   dm_tril, rhoj[:, p0:p1])
                int3c = None

            # (d/dX P|Q)
            int2c_e1 = auxmol.intor('int2c2e_ip1', aosym='s1')
            vjaux -= lib.einsum('xpq,mp,nq->mnxp', int2c_e1, rhoj, rhoj)

            vjaux = numpy.array([
                -vjaux[:, :, :, p0:p1].sum(axis=3)
                for p0, p1 in auxslices[:, 2:]
            ])
            if ishf:
                vjaux = vjaux.sum((1, 2))
            else:
                vjaux = numpy.ascontiguousarray(vjaux.transpose(1, 2, 0, 3))
            vj = lib.tag_array(-vj.reshape(out_shape), aux=numpy.array(vjaux))
        else:
            vj = -vj.reshape(out_shape)
        logger.timer(mf_grad, 'df vj', *t0)
        return vj, None

    if hasattr(dm, 'mo_coeff') and hasattr(dm, 'mo_occ'):
        mo_coeff = dm.mo_coeff
        mo_occ = dm.mo_occ
    elif ishf:
        mo_coeff = mf_grad.base.mo_coeff
        mo_occ = mf_grad.base.mo_occ
        if isinstance(mf_grad.base, scf.rohf.ROHF):
            mo_coeff = numpy.vstack((mo_coeff, mo_coeff))
            mo_occa = numpy.array(mo_occ > 0, dtype=numpy.double)
            mo_occb = numpy.array(mo_occ == 2, dtype=numpy.double)
            assert (mo_occa.sum() + mo_occb.sum() == mo_occ.sum())
            mo_occ = numpy.vstack((mo_occa, mo_occb))
    else:
        s0 = mol.intor('int1e_ovlp')
        mo_occ = []
        mo_coeff = []
        for dm in dms:
            sdms = reduce(lib.dot, (s0, dm, s0))
            n, c = scipy.linalg.eigh(sdms, b=s0)
            mo_occ.append(n)
            mo_coeff.append(c)
        mo_occ = numpy.stack(mo_occ, axis=0)
    nmo = mo_occ.shape[-1]

    mo_coeff = numpy.asarray(mo_coeff).reshape(-1, nao, nmo)
    mo_occ = numpy.asarray(mo_occ).reshape(-1, nmo)
    rhoj = numpy.zeros((nset, naux))
    f_rhok = lib.H5TmpFile()
    orbor = []
    orbol = []
    nocc = []
    orbor_stack = numpy.zeros((nao, 0), dtype=mo_coeff.dtype, order='F')
    orbol_stack = numpy.zeros((nao, 0), dtype=mo_coeff.dtype, order='F')
    offs = 0
    for i in range(nset):
        idx = numpy.abs(mo_occ[i]) > 1e-8
        nocc.append(numpy.count_nonzero(idx))
        c = mo_coeff[i][:, idx]
        orbol_stack = numpy.append(orbol_stack, c, axis=1)
        orbol.append(orbol_stack[:, offs:offs + nocc[-1]])
        cn = lib.einsum('pi,i->pi', c, mo_occ[i][idx])
        orbor_stack = numpy.append(orbor_stack, cn, axis=1)
        orbor.append(orbor_stack[:, offs:offs + nocc[-1]])
        offs += nocc[-1]

    # (P|Q)
    int2c = scipy.linalg.cho_factor(auxmol.intor('int2c2e', aosym='s1'))

    t1 = (time.clock(), time.time())
    max_memory = mf_grad.max_memory - lib.current_memory()[0]
    blksize = max_memory * .5e6 / 8 / (naux * nao)
    mol_ao_ranges = balance_partition(ao_loc, blksize)
    nsteps = len(mol_ao_ranges)
    t2 = t1
    for istep, (shl0, shl1, nd) in enumerate(mol_ao_ranges):
        int3c = get_int3c_s1((0, nbas, shl0, shl1, 0, nauxbas))
        t2 = logger.timer_debug1(mf_grad, 'df grad intor (P|mn)', *t2)
        p0, p1 = ao_loc[shl0], ao_loc[shl1]
        for i in range(nset):
            # MRH 05/21/2020: De-vectorize this because array contiguity -> parallel scaling
            v = lib.dot(int3c.reshape(nao, -1, order='F').T,
                        orbor[i]).reshape(naux, (p1 - p0) * nocc[i])
            t2 = logger.timer_debug1(mf_grad,
                                     'df grad einsum (P|mn) u_ni N_i = v_Pmi',
                                     *t2)
            rhoj[i] += numpy.dot(v, orbol[i][p0:p1].ravel())
            t2 = logger.timer_debug1(mf_grad,
                                     'df grad einsum v_Pmi u_mi = rho_P', *t2)
            v = scipy.linalg.cho_solve(int2c, v)
            t2 = logger.timer_debug1(mf_grad,
                                     'df grad cho_solve (P|Q) D_Qmi = v_Pmi',
                                     *t2)
            f_rhok['%s/%s' % (i, istep)] = v.reshape(naux, p1 - p0, -1)
            t2 = logger.timer_debug1(
                mf_grad,
                'df grad cache D_Pmi (m <-> i transpose upon retrieval)', *t2)
        int3c = v = None

    rhoj = scipy.linalg.cho_solve(int2c, rhoj.T).T
    int2c = None
    t1 = logger.timer_debug1(
        mf_grad, 'df grad vj and vk AO (P|Q) D_Q = (P|mn) D_mn solve', *t1)

    def load(set_id, p0, p1):
        buf = numpy.empty((p1 - p0, nocc[set_id], nao))
        col1 = 0
        for istep in range(nsteps):
            dat = f_rhok['%s/%s' % (set_id, istep)][p0:p1]
            col0, col1 = col1, col1 + dat.shape[1]
            buf[:p1 - p0, :, col0:col1] = dat.transpose(0, 2, 1)
        return buf

    vj = numpy.zeros((nset, 3, nao, nao))
    vk = numpy.zeros((nset, 3, nao, nao))
    # (d/dX i,j|P)
    fmmm = _ao2mo.libao2mo.AO2MOmmm_bra_nr_s1  # MO output index slower than AO output index; input AOs are asymmetric
    fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv  # comp and aux indices are slower
    ftrans = _ao2mo.libao2mo.AO2MOtranse2_nr_s1  # input is not tril_packed
    null = lib.c_null_ptr()
    t2 = t1
    for shl0, shl1, nL in ao_ranges:
        int3c = get_int3c_ip1((0, nbas, 0, nbas, shl0,
                               shl1)).transpose(0, 3, 2,
                                                1)  # (P|mn'), row-major order
        t2 = logger.timer_debug1(mf_grad, "df grad intor (P|mn')", *t2)
        p0, p1 = aux_loc[shl0], aux_loc[shl1]
        for i in range(nset):
            # MRH 05/21/2020: De-vectorize this because array contiguity -> parallel scaling
            vj[i, 0] += numpy.dot(rhoj[i, p0:p1],
                                  int3c[0].reshape(p1 - p0,
                                                   -1)).reshape(nao, nao).T
            vj[i, 1] += numpy.dot(rhoj[i, p0:p1],
                                  int3c[1].reshape(p1 - p0,
                                                   -1)).reshape(nao, nao).T
            vj[i, 2] += numpy.dot(rhoj[i, p0:p1],
                                  int3c[2].reshape(p1 - p0,
                                                   -1)).reshape(nao, nao).T
            t2 = logger.timer_debug1(mf_grad,
                                     "df grad einsum rho_P (P|mn') rho_P", *t2)
            tmp = numpy.empty((3, p1 - p0, nocc[i], nao),
                              dtype=orbol_stack.dtype)
            fdrv(
                ftrans,
                fmmm,  # xPmn u_mi -> xPin
                tmp.ctypes.data_as(ctypes.c_void_p),
                int3c.ctypes.data_as(ctypes.c_void_p),
                orbol[i].ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(3 * (p1 - p0)),
                ctypes.c_int(nao),
                (ctypes.c_int * 4)(0, nocc[i], 0, nao),
                null,
                ctypes.c_int(0))
            t2 = logger.timer_debug1(mf_grad,
                                     "df grad einsum (P|mn') u_mi = dg_Pin",
                                     *t2)
            rhok = load(i, p0, p1)
            vk[i] += lib.einsum('xpoi,pok->xik', tmp, rhok)
            t2 = logger.timer_debug1(mf_grad,
                                     "df grad einsum D_Pim dg_Pin = v_ij", *t2)
            rhok = tmp = None
        int3c = None
    t1 = logger.timer_debug1(mf_grad, 'df grad vj and vk AO (P|mn) D_P eval',
                             *t1)

    if mf_grad.auxbasis_response:
        # Cache (P|uv) D_ui c_vj. Must be include both upper and lower triangles
        # over nset.
        max_memory = mf_grad.max_memory - lib.current_memory()[0]
        blksize = int(
            min(max(max_memory * .5e6 / 8 / (nao * max(nocc)), 20), naux))
        rhok_oo = []
        for i, j in product(range(nset), repeat=2):
            tmp = numpy.empty((naux, nocc[i], nocc[j]))
            for p0, p1 in lib.prange(0, naux, blksize):
                rhok = load(i, p0, p1).reshape((p1 - p0) * nocc[i], nao)
                tmp[p0:p1] = lib.dot(rhok,
                                     orbol[j]).reshape(p1 - p0, nocc[i],
                                                       nocc[j])
            rhok_oo.append(tmp)
            rhok = tmp = None
        t1 = logger.timer_debug1(
            mf_grad, 'df grad vj and vk aux d_Pim u_mj = d_Pij eval', *t1)

        vjaux = numpy.zeros((nset, nset, 3, naux))
        vkaux = numpy.zeros((nset, nset, 3, naux))
        # (i,j|d/dX P)
        t2 = t1
        fmmm = _ao2mo.libao2mo.AO2MOmmm_bra_nr_s2  # MO output index slower than AO output index; input AOs are symmetric
        fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv  # comp and aux indices are slower
        ftrans = _ao2mo.libao2mo.AO2MOtranse2_nr_s2  # input is tril_packed
        null = lib.c_null_ptr()
        for shl0, shl1, nL in ao_ranges:
            int3c = get_int3c_ip2((0, nbas, 0, nbas, shl0, shl1))  # (i,j|P)
            t2 = logger.timer_debug1(mf_grad, "df grad intor (P'|mn)", *t2)
            p0, p1 = aux_loc[shl0], aux_loc[shl1]
            drhoj = lib.dot(
                int3c.transpose(0, 2, 1).reshape(3 * (p1 - p0), -1),
                dm_tril.T).reshape(3, p1 - p0, -1)  # xpij,mij->xpm
            vjaux[:, :, :, p0:p1] = lib.einsum('xpm,np->mnxp', drhoj,
                                               rhoj[:, p0:p1])
            t2 = logger.timer_debug1(
                mf_grad, "df grad einsum rho_P (P'|mn) D_mn = v_P", *t2)
            tmp = [
                numpy.empty((3, p1 - p0, nocc_i, nao), dtype=orbor_stack.dtype)
                for nocc_i in nocc
            ]
            assert (orbor_stack.flags.f_contiguous), '{} {}'.format(
                orbor_stack.shape, orbor_stack.strides)
            for orb, buf, nocc_i in zip(orbol, tmp, nocc):
                fdrv(
                    ftrans,
                    fmmm,  # gPmn u_ni -> gPim
                    buf.ctypes.data_as(ctypes.c_void_p),
                    int3c.ctypes.data_as(ctypes.c_void_p),
                    orb.ctypes.data_as(ctypes.c_void_p),
                    ctypes.c_int(3 * (p1 - p0)),
                    ctypes.c_int(nao),
                    (ctypes.c_int * 4)(0, nocc_i, 0, nao),
                    null,
                    ctypes.c_int(0))
            int3c = [[
                lib.dot(buf.reshape(-1, nao),
                        orb).reshape(3, p1 - p0, -1, norb)
                for orb, norb in zip(orbor, nocc)
            ] for buf in tmp]  # pim,mj,j -> pij
            t2 = logger.timer_debug1(
                mf_grad, "df grad einsum (P'|mn) u_mi u_nj N_j = v_Pmn", *t2)
            for i, j in product(range(nset), repeat=2):
                k = (i * nset) + j
                tmp = rhok_oo[k][p0:p1]
                vkaux[i, j, :, p0:p1] += lib.einsum('xpij,pij->xp',
                                                    int3c[i][j], tmp)
                t2 = logger.timer_debug1(mf_grad,
                                         "df grad einsum d_Pij v_Pij = v_P",
                                         *t2)
        int3c = tmp = None
        t1 = logger.timer_debug1(mf_grad, "df grad vj and vk aux (P'|mn) eval",
                                 *t1)

        # (d/dX P|Q)
        int2c_e1 = auxmol.intor('int2c2e_ip1')
        vjaux -= lib.einsum('xpq,mp,nq->mnxp', int2c_e1, rhoj, rhoj)
        for i, j in product(range(nset), repeat=2):
            k = (i * nset) + j
            l = (j * nset) + i
            tmp = lib.einsum('pij,qji->pq', rhok_oo[k], rhok_oo[l])
            vkaux[i, j] -= lib.einsum('xpq,pq->xp', int2c_e1, tmp)
        t1 = logger.timer_debug1(mf_grad, "df grad vj and vk aux (P'|Q) eval",
                                 *t1)

        vjaux = numpy.array([
            -vjaux[:, :, :, p0:p1].sum(axis=3) for p0, p1 in auxslices[:, 2:]
        ])
        vkaux = numpy.array([
            -vkaux[:, :, :, p0:p1].sum(axis=3) for p0, p1 in auxslices[:, 2:]
        ])
        if ishf:
            vjaux = vjaux.sum((1, 2))
            idx = numpy.array(list(range(nset))) * (nset + 1)
            vkaux = vkaux.reshape((nset**2, 3, mol.natm))[idx, :, :].sum(0)
        else:
            vjaux = numpy.ascontiguousarray(vjaux.transpose(1, 2, 0, 3))
            vkaux = numpy.ascontiguousarray(vkaux.transpose(1, 2, 0, 3))
        vj = lib.tag_array(-vj.reshape(out_shape), aux=numpy.array(vjaux))
        vk = lib.tag_array(-vk.reshape(out_shape), aux=numpy.array(vkaux))
    else:
        vj = -vj.reshape(out_shape)
        vk = -vk.reshape(out_shape)
    logger.timer(mf_grad, 'df grad vj and vk', *t0)
    return vj, vk
Пример #39
0
def write_chk(mc,root,chkfile):

    t0 = (time.clock(), time.time())
    fh5 = h5py.File(chkfile,'w')

    if mc.fcisolver.nroots > 1:
        mc.mo_coeff,_, mc.mo_energy = mc.canonicalize(mc.mo_coeff,ci=root)


    fh5['mol']        =       mc.mol.dumps()
    fh5['mc/mo']      =       mc.mo_coeff
    fh5['mc/ncore']   =       mc.ncore
    fh5['mc/ncas']    =       mc.ncas
    nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore
    fh5['mc/nvirt']   =       nvirt
    fh5['mc/nelecas'] =       mc.nelecas
    fh5['mc/root']    =       root
    fh5['mc/orbe']    =       mc.mo_energy
    fh5['mc/nroots']   =       mc.fcisolver.nroots
    fh5['mc/wfnsym']   =       mc.fcisolver.wfnsym
    if hasattr(mc.mo_coeff, 'orbsym'):
        fh5.create_dataset('mc/orbsym',data=mc.mo_coeff.orbsym)
    else :
        fh5.create_dataset('mc/orbsym',data=[])

    if hasattr(mc.mo_coeff, 'orbsym') and mc.mol.symmetry:
        orbsym = numpy.asarray(mc.mo_coeff.orbsym)
        pair_irrep = orbsym.reshape(-1,1) ^ orbsym
    else:
        pair_irrep = None

    ncore = mc.ncore
    nocc = mc.ncore + mc.ncas
    mo_core = mc.mo_coeff[:,:mc.ncore]
    mo_cas  = mc.mo_coeff[:,mc.ncore:mc.ncore+mc.ncas]
    mo_virt = mc.mo_coeff[:,mc.ncore+mc.ncas:]
    core_dm = numpy.dot(mo_core,mo_core.T) *2
    core_vhf = mc.get_veff(mc.mol,core_dm)
    h1e_Sr =  reduce(numpy.dot, (mo_virt.T,mc.get_hcore()+core_vhf , mo_cas))
    h1e_Si =  reduce(numpy.dot, (mo_cas.T, mc.get_hcore()+core_vhf , mo_core))
    h1e, e_core = mc.h1e_for_cas()
    if pair_irrep is not None:
        h1e_Sr[pair_irrep[nocc:,ncore:nocc] != 0] = 0
        h1e_Si[pair_irrep[ncore:nocc,:ncore] != 0] = 0
        h1e[pair_irrep[ncore:nocc,ncore:nocc] != 0] = 0
    fh5['h1e_Si']     =       h1e_Si
    fh5['h1e_Sr']     =       h1e_Sr
    fh5['h1e']        =       h1e
    fh5['e_core']     =       e_core

    if mc._scf._eri is None:
        h2e_t = ao2mo.general(mc.mol, (mc.mo_coeff,mo_cas,mo_cas,mo_cas), compact=False)
        h2e_t = h2e_t.reshape(-1,mc.ncas,mc.ncas,mc.ncas)
        if pair_irrep is not None:
            sym_forbid = (pair_irrep[:,ncore:nocc].reshape(-1,1) !=
                          pair_irrep[ncore:nocc,ncore:nocc].ravel()).reshape(h2e_t.shape)
            h2e_t[sym_forbid] = 0
        h2e =h2e_t[mc.ncore:mc.ncore+mc.ncas,:,:,:]
        fh5['h2e'] = h2e

        h2e_Sr =h2e_t[mc.ncore+mc.ncas:,:,:,:]
        fh5['h2e_Sr'] = h2e_Sr

        h2e_Si =numpy.transpose(h2e_t[:mc.ncore,:,:,:], (1,0,2,3))
        fh5['h2e_Si'] = h2e_Si

    else:
        eri = mc._scf._eri
        h2e_t = ao2mo.general(eri, [mc.mo_coeff,mo_cas,mo_cas,mo_cas], compact=False)
        h2e_t = h2e_t.reshape(-1,mc.ncas,mc.ncas,mc.ncas)
        if pair_irrep is not None:
            sym_forbid = (pair_irrep[:,ncore:nocc].reshape(-1,1) !=
                          pair_irrep[ncore:nocc,ncore:nocc].ravel()).reshape(h2e_t.shape)
            h2e_t[sym_forbid] = 0
        h2e =h2e_t[mc.ncore:mc.ncore+mc.ncas,:,:,:]
        fh5['h2e'] = h2e

        h2e_Sr =h2e_t[mc.ncore+mc.ncas:,:,:,:]
        fh5['h2e_Sr'] = h2e_Sr

        h2e_Si =numpy.transpose(h2e_t[:mc.ncore,:,:,:], (1,0,2,3))
        fh5['h2e_Si'] = h2e_Si

    fh5.close()

    logger.timer(mc,'Write MPS NEVPT integral', *t0)
Пример #40
0
def get_veff(ks,
             cell=None,
             dm=None,
             dm_last=0,
             vhf_last=0,
             hermi=1,
             kpts=None,
             kpts_band=None):
    '''Coulomb + XC functional

    .. note::
        This is a replica of pyscf.dft.rks.get_veff with kpts added.
        This function will change the ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Returns:
        Veff : (nkpts, nao, nao) or (*, nkpts, nao, nao) ndarray
        Veff = J + Vxc.
    '''
    if cell is None: cell = ks.cell
    if dm is None: dm = ks.make_rdm1()
    if kpts is None: kpts = ks.kpts
    t0 = (time.clock(), time.time())

    # ndim = 3 : dm.shape = (nkpts, nao, nao)
    ground_state = (isinstance(dm, np.ndarray) and dm.ndim == 3
                    and kpts_band is None)

    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        if ks.small_rho_cutoff > 1e-20 and ground_state:
            ks.grids = rks.prune_small_rho_grids_(ks, cell, dm, ks.grids, kpts)
        t0 = logger.timer(ks, 'setting up grids', *t0)

    if hermi == 2:  # because rho = 0
        n, exc, vxc = 0, 0, 0
    else:
        n, exc, vxc = ks._numint.nr_rks(cell, ks.grids, ks.xc, dm, 0, kpts,
                                        kpts_band)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    weight = 1. / len(kpts)
    hyb = ks._numint.hybrid_coeff(ks.xc, spin=cell.spin)
    if abs(hyb) < 1e-10:
        vj = ks.get_j(cell, dm, hermi, kpts, kpts_band)
        vxc += vj
    else:
        if getattr(ks.with_df, '_j_only', False):  # for GDF and MDF
            ks.with_df._j_only = False
        vj, vk = ks.get_jk(cell, dm, hermi, kpts, kpts_band)
        vxc += vj - vk * (hyb * .5)

        if ground_state:
            exc -= np.einsum('Kij,Kji', dm, vk).real * .5 * hyb * .5 * weight

    if ground_state:
        ecoul = np.einsum('Kij,Kji', dm, vj).real * .5 * weight
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=None, vk=None)
    return vxc
Пример #41
0
def kernel(mf,
           conv_tol=1e-10,
           conv_tol_grad=None,
           dump_chk=False,
           dm0e=None,
           dm0n=[],
           callback=None,
           conv_check=True,
           **kwargs):
    cput0 = (logger.process_clock(), logger.perf_counter())
    if conv_tol_grad is None:
        conv_tol_grad = numpy.sqrt(conv_tol)
        logger.info(mf, 'Set gradient conv threshold to %g', conv_tol_grad)
    mol = mf.mol
    if dm0e is None:
        mf.dm_elec = mf.get_init_guess_elec(mol, mf.init_guess)
    else:
        mf.dm_elec = dm0e
    if len(dm0n) < mol.nuc_num:
        mf.dm_nuc = mf.get_init_guess_nuc(mol, mf.init_guess)
        # if mf.init_guess is not 'chkfile', then it only affects the electronic part
    else:
        mf.dm_nuc = dm0n

    h1e = mf.mf_elec.get_hcore(mol.elec)
    vhf_e = mf.mf_elec.get_veff(mol.elec, mf.dm_elec)
    h1n = []
    veff_n = []
    for i in range(mol.nuc_num):
        h1n.append(mf.mf_nuc[i].get_hcore(mol.nuc[i]))
        veff_n.append(mf.mf_nuc[i].get_veff(mol.nuc[i], mf.dm_nuc[i]))
    e_tot = mf.energy_tot(mf.dm_elec, mf.dm_nuc, h1e, vhf_e, h1n, veff_n)
    logger.info(mf, 'init E= %.15g', e_tot)

    scf_conv = False
    mo_energy_e = mo_coeff_e = mo_occ_e = None
    mo_energy_n = [None] * mol.nuc_num
    mo_coeff_n = [None] * mol.nuc_num
    mo_occ_n = [None] * mol.nuc_num
    fock_n = [None] * mol.nuc_num

    s1e = mf.mf_elec.get_ovlp(mol.elec)
    cond = lib.cond(s1e)
    logger.debug(mf, 'cond(S) = %s', cond)
    if numpy.max(cond) * 1e-17 > conv_tol:
        logger.warn(
            mf,
            'Singularity detected in overlap matrix (condition number = %4.3g). '
            'SCF may be inaccurate and hard to converge.', numpy.max(cond))
    s1n = []
    for i in range(mol.nuc_num):
        s1n.append(mf.mf_nuc[i].get_ovlp(mol.nuc[i]))

    # Skip SCF iterations. Compute only the total energy of the initial density
    if mf.max_cycle <= 0:
        fock_e = mf.mf_elec.get_fock(h1e, s1e, vhf_e,
                                     mf.dm_elec)  # = h1e + vhf, no DIIS
        mo_energy_e, mo_coeff_e = mf.mf_elec.eig(fock_e, s1e)
        mo_occ_e = mf.mf_elec.get_occ(mo_energy_e, mo_coeff_e)
        mf.mf_elec.mo_energy = mo_energy_e
        mf.mf_elec.mo_coeff = mo_coeff_e
        mf.mf_elec.mo_occ = mo_occ_e
        for i in range(mol.nuc_num):
            fock_n[i] = mf.mf_nuc[i].get_fock(h1n[i], s1n[i], veff_n[i],
                                              mf.dm_nuc[i])
            mo_energy_n[i], mo_coeff_n[i] = mf.mf_nuc[i].eig(fock_n[i], s1n[i])
            mo_occ_n[i] = mf.mf_nuc[i].get_occ(mo_energy_n[i], mo_coeff_e[i])
            mf.mf_nuc[i].mo_energy = mo_energy_n[i]
            mf.mf_nuc[i].mo_coeff = mo_coeff_n[i]
            mf.mf_nuc[i].mo_occ = mo_occ_n[i]
        if mf.dm_elec.ndim > 2:
            mf.dm_elec = mf.dm_elec[0] + mf.dm_elec[1]
        return scf_conv, e_tot, mo_energy_e, mo_coeff_e, mo_occ_e, \
               mo_energy_n, mo_coeff_n, mo_occ_n

    if isinstance(mf.mf_elec.diis, lib.diis.DIIS):
        mf_diis = mf.mf_elec.diis
    elif mf.mf_elec.diis:
        assert issubclass(mf.mf_elec.DIIS, lib.diis.DIIS)
        mf_diis = mf.mf_elec.DIIS(mf.mf_elec, mf.mf_elec.diis_file)
        mf_diis.space = mf.mf_elec.diis_space
        mf_diis.rollback = mf.mf_elec.diis_space_rollback
    else:
        mf_diis = None
    # Nuclei need DIIS when there is epc
    mf_nuc_diis = [None] * mol.nuc_num
    if hasattr(mf, 'epc') and mf.epc is not None:
        for i in range(mol.nuc_num):
            mf_nuc = mf.mf_nuc[i]
            if isinstance(mf_nuc.diis, lib.diis.DIIS):
                mf_nuc_diis[i] = mf_nuc.diis
            elif mf_nuc.diis:
                assert issubclass(mf_nuc.DIIS, lib.diis.DIIS)
                mf_nuc_diis[i] = mf_nuc.DIIS(mf_nuc, mf_nuc.diis_file)
                mf_nuc_diis[i].space = mf_nuc.diis_space
                mf_nuc_diis[i].rollback = mf_nuc.diis_space_rollback
            else:
                mf_nuc_diis[i] = None

    if dump_chk and mf.chkfile:
        # Explicit overwrite the mol object in chkfile
        # Note in pbc.scf, mf.mol == mf.cell, cell is saved under key "mol"
        chkfile.save_mol(mol, mf.chkfile)

    # A preprocessing hook before the SCF iteration
    mf.pre_kernel(locals())

    if isinstance(mf, neo.CDFT):
        int1e_r = []
        for i in range(mol.nuc_num):
            int1e_r.append(mf.mf_nuc[i].mol.intor_symmetric('int1e_r', comp=3))

    cput1 = logger.timer(mf, 'initialize scf', *cput0)
    for cycle in range(mf.max_cycle):
        dm_elec_last = numpy.copy(
            mf.dm_elec)  # why didn't pyscf.scf.hf use copy?
        dm_nuc_last = numpy.copy(mf.dm_nuc)
        last_e = e_tot

        # set up the electronic Hamiltonian and diagonalize it
        fock_e = mf.mf_elec.get_fock(h1e, s1e, vhf_e, mf.dm_elec, cycle,
                                     mf_diis)
        mo_energy_e, mo_coeff_e = mf.mf_elec.eig(fock_e, s1e)
        mo_occ_e = mf.mf_elec.get_occ(mo_energy_e, mo_coeff_e)
        mf.dm_elec = mf.mf_elec.make_rdm1(mo_coeff_e, mo_occ_e)
        # attach mo_coeff and mo_occ to dm to improve DFT get_veff efficiency
        mf.dm_elec = lib.tag_array(mf.dm_elec,
                                   mo_coeff=mo_coeff_e,
                                   mo_occ=mo_occ_e)

        # set up the nuclear Hamiltonian and diagonalize it
        for i in range(mol.nuc_num):
            # update nuclear core Hamiltonian after the electron density is updated
            h1n[i] = mf.mf_nuc[i].get_hcore(mf.mf_nuc[i].mol)
            # optimize f in cNEO
            skip = False
            if isinstance(mf, neo.CDFT):
                ia = mf.mf_nuc[i].mol.atom_index
                fx = numpy.einsum('xij,x->ij', int1e_r[i], mf.f[ia])
                opt = scipy.optimize.root(mf.first_order_de,
                                          mf.f[ia],
                                          args=(mf.mf_nuc[i], h1n[i] - fx,
                                                veff_n[i], s1n[i], int1e_r[i]),
                                          method='hybr')
                logger.debug(
                    mf, 'f of %s(%i) atom: %s' %
                    (mf.mf_nuc[i].mol.atom_symbol(ia), ia, mf.f[ia]))
                logger.debug(mf, '1st de of L: %s', opt.fun)
                if mf_nuc_diis[i] is None:
                    # skip the extra diagonalization if epc is not present and DIIS is disabled
                    skip = True
            if not skip:
                fock_n[i] = mf.mf_nuc[i].get_fock(h1n[i], s1n[i], veff_n[i],
                                                  mf.dm_nuc[i], cycle,
                                                  mf_nuc_diis[i])
                mo_energy_n[i], mo_coeff_n[i] = mf.mf_nuc[i].eig(
                    fock_n[i], s1n[i])
                mf.mf_nuc[i].mo_energy, mf.mf_nuc[i].mo_coeff = mo_energy_n[
                    i], mo_coeff_n[i]
                mo_occ_n[i] = mf.mf_nuc[i].get_occ(mo_energy_n[i],
                                                   mo_coeff_n[i])
                mf.mf_nuc[i].mo_occ = mo_occ_n[i]
                mf.dm_nuc[i] = mf.mf_nuc[i].make_rdm1(mo_coeff_n[i],
                                                      mo_occ_n[i])
            # update nuclear veff and possible ep correlation part after the diagonalization
            veff_n[i] = mf.mf_nuc[i].get_veff(mf.mf_nuc[i].mol, mf.dm_nuc[i])
        norm_ddm_n = numpy.linalg.norm(
            numpy.concatenate(mf.dm_nuc, axis=None).ravel() -
            numpy.concatenate(dm_nuc_last, axis=None).ravel())

        # update electronic core Hamiltonian after the nuclear density is updated
        h1e = mf.mf_elec.get_hcore(mol.elec)
        # also update the veff, along with the possible ep correlation part
        vhf_e = mf.mf_elec.get_veff(mol.elec, mf.dm_elec, dm_elec_last, vhf_e)

        # Here Fock matrix is h1e + vhf, without DIIS.  Calling get_fock
        # instead of the statement "fock = h1e + vhf" because Fock matrix may
        # be modified in some methods.
        fock_e = mf.mf_elec.get_fock(h1e, s1e, vhf_e,
                                     mf.dm_elec)  # = h1e + vhf, no DIIS
        norm_gorb_e = numpy.linalg.norm(
            mf.mf_elec.get_grad(mo_coeff_e, mo_occ_e, fock_e))
        if not TIGHT_GRAD_CONV_TOL:
            norm_gorb_e = norm_gorb_e / numpy.sqrt(norm_gorb_e.size)
        norm_ddm_e = numpy.linalg.norm(mf.dm_elec - dm_elec_last)

        e_tot = mf.energy_tot(mf.dm_elec, mf.dm_nuc, h1e, vhf_e, h1n, veff_n)
        logger.info(
            mf,
            'cycle= %d E= %.15g  delta_E= %4.3g  |g_e|= %4.3g  |ddm_e|= %4.3g  |ddm_n|= %4.3g',
            cycle + 1, e_tot, e_tot - last_e, norm_gorb_e, norm_ddm_e,
            norm_ddm_n)

        if abs(e_tot - last_e) < conv_tol and norm_gorb_e < conv_tol_grad:
            scf_conv = True

        if dump_chk:
            mf.dump_chk(locals())

        if callable(callback):
            callback(locals())

        cput1 = logger.timer(mf, 'cycle= %d' % (cycle + 1), *cput1)

        if scf_conv:
            break

    if scf_conv and conv_check:
        # An extra diagonalization, to remove level shift
        #fock = mf.get_fock(h1e, s1e, vhf, dm)  # = h1e + vhf
        mo_energy_e, mo_coeff_e = mf.mf_elec.eig(fock_e, s1e)
        mo_occ_e = mf.mf_elec.get_occ(mo_energy_e, mo_coeff_e)
        mf.dm_elec, dm_elec_last = mf.mf_elec.make_rdm1(mo_coeff_e,
                                                        mo_occ_e), mf.dm_elec
        mf.dm_elec = lib.tag_array(mf.dm_elec,
                                   mo_coeff=mo_coeff_e,
                                   mo_occ=mo_occ_e)

        for i in range(mol.nuc_num):
            h1n[i] = mf.mf_nuc[i].get_hcore(mf.mf_nuc[i].mol)
            veff_n[i] = mf.mf_nuc[i].get_veff(mf.mf_nuc[i].mol, mf.dm_nuc[i])
            fock_n[i] = mf.mf_nuc[i].get_fock(h1n[i], s1n[i], veff_n[i],
                                              mf.dm_nuc[i])
            mo_energy_n[i], mo_coeff_n[i] = mf.mf_nuc[i].eig(fock_n[i], s1n[i])
            mf.mf_nuc[i].mo_energy, mf.mf_nuc[i].mo_coeff = mo_energy_n[
                i], mo_coeff_n[i]
            mo_occ_n[i] = mf.mf_nuc[i].get_occ(mo_energy_n[i], mo_coeff_n[i])
            mf.mf_nuc[i].mo_occ = mo_occ_n[i]
            mf.dm_nuc[i], dm_nuc_last[i] = mf.mf_nuc[i].make_rdm1(
                mo_coeff_n[i], mo_occ_n[i]), mf.dm_nuc[i]
        norm_ddm_n = numpy.linalg.norm(
            numpy.concatenate(mf.dm_nuc, axis=None).ravel() -
            numpy.concatenate(dm_nuc_last, axis=None).ravel())

        h1e = mf.mf_elec.get_hcore(mol.elec)
        vhf_e = mf.mf_elec.get_veff(mol.elec, mf.dm_elec, dm_elec_last, vhf_e)
        fock_e = mf.mf_elec.get_fock(h1e, s1e, vhf_e, mf.dm_elec)
        norm_gorb_e = numpy.linalg.norm(
            mf.mf_elec.get_grad(mo_coeff_e, mo_occ_e, fock_e))
        if not TIGHT_GRAD_CONV_TOL:
            norm_gorb_e = norm_gorb_e / numpy.sqrt(norm_gorb_e.size)
        norm_ddm_e = numpy.linalg.norm(mf.dm_elec - dm_elec_last)

        e_tot, last_e = mf.energy_tot(mf.dm_elec, mf.dm_nuc, h1e, vhf_e, h1n,
                                      veff_n), e_tot
        conv_tol = conv_tol * 10
        conv_tol_grad = conv_tol_grad * 3
        if abs(e_tot - last_e) < conv_tol or norm_gorb_e < conv_tol_grad:
            scf_conv = True
        logger.info(
            mf,
            'Extra cycle  E= %.15g  delta_E= %4.3g  |g_e|= %4.3g  |ddm_e|= %4.3g  |ddm_n|= %4.3g',
            e_tot, e_tot - last_e, norm_gorb_e, norm_ddm_e, norm_ddm_n)
        if dump_chk:
            mf.dump_chk(locals())

    logger.timer(mf, 'scf_cycle', *cput0)
    # A post-processing hook before return
    mf.post_kernel(locals())

    if mf.dm_elec.ndim > 2:
        mf.dm_elec = mf.dm_elec[0] + mf.dm_elec[1]
    return scf_conv, e_tot, mo_energy_e, mo_coeff_e, mo_occ_e, \
           mo_energy_n, mo_coeff_n, mo_occ_n
Пример #42
0
def get_veff(ks,
             cell=None,
             dm=None,
             dm_last=0,
             vhf_last=0,
             hermi=1,
             kpts=None,
             kpts_band=None):
    '''Coulomb + XC functional

    .. note::
        This is a replica of pyscf.dft.rks.get_veff with kpts added.
        This function will change the ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.  The ._exc and ._ecoul attributes
            will be updated after return.  Attributes ._dm_last, ._vj_last and
            ._vk_last might be changed if direct SCF method is applied.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Returns:
        Veff : (nkpts, nao, nao) or (*, nkpts, nao, nao) ndarray
        Veff = J + Vxc.
    '''
    needs_ao_update = False

    if cell is None:
        cell = ks.cell
    elif not cell == ks.cell:
        ks.cell = cell
        needs_ao_update = True

    if kpts is None:
        kpts = ks.kpts
    elif not np.array_equal(kpts, ks.kpts):
        ks.kpts = np.array(kpts)
        needs_ao_update = True

    if dm is None: dm = ks.make_rdm1()
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        small_rho_cutoff = ks.small_rho_cutoff
        t0 = logger.timer(ks, 'setting up grids', *t0)
    else:
        small_rho_cutoff = 0

    ao_derivatives_required = {
        "LDA": 0,
        "GGA": 1,
        "MGGA": 2,
    }[ks._numint._xc_type(ks.xc)]

    # If needs an update
    if ks._ao is None or needs_ao_update:
        ks._update_ao(ao_derivatives_required)

    # If number of derivatives is not sufficiently large: update as well
    shape = ks._ao[0].shape
    # Retrieve primary dimension
    if len(shape) == 2:
        prim = 1
    else:
        prim = shape[0]

    n = (ao_derivatives_required + 1) * (ao_derivatives_required + 2) * (
        ao_derivatives_required + 3) // 6
    if n > prim:
        ks._update_ao(ao_derivatives_required)

    if hermi == 2:  # because rho = 0
        n, ks._exc, vx = 0, 0, 0
    else:
        n, ks._exc, vx = ks._numint.nr_rks(cell,
                                           ks.grids,
                                           ks.xc,
                                           dm,
                                           1,
                                           kpts,
                                           kpts_band,
                                           precomputed_ao=ks._ao)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    # ndim = 3 : dm.shape = (nkpts, nao, nao)
    ground_state = (isinstance(dm, np.ndarray) and dm.ndim == 3
                    and kpts_band is None)
    nkpts = len(kpts)

    hyb = ks._numint.hybrid_coeff(ks.xc, spin=cell.spin)
    if abs(hyb) < 1e-10:
        vhf = vj = ks.get_j(cell, dm, hermi, kpts, kpts_band)
    else:
        vj, vk = ks.get_jk(cell, dm, hermi, kpts, kpts_band)
        vhf = vj - vk * (hyb * .5)

        if ground_state:
            ks._exc -= (1. / nkpts) * np.einsum('Kij,Kji', dm,
                                                vk).real * .5 * hyb * .5

    if ground_state:
        ks._ecoul = (1. / nkpts) * np.einsum('Kij,Kji', dm, vj).real * .5

    if (small_rho_cutoff > 1e-20 and ground_state
            and abs(n - cell.nelectron) < 0.01 * n):
        # Filter grids the first time setup grids
        _ao = ks._ao if len(ks._ao[0].shape) == 2 else list(i[0]
                                                            for i in ks._ao)
        idx = ks._numint.large_rho_indices(cell,
                                           dm,
                                           ks.grids,
                                           small_rho_cutoff,
                                           kpts,
                                           precomputed_ao=_ao)
        logger.debug(ks, 'Drop grids %d',
                     ks.grids.weights.size - np.count_nonzero(idx))
        ks.grids.coords = np.asarray(ks.grids.coords[idx], order='C')
        ks.grids.weights = np.asarray(ks.grids.weights[idx], order='C')
        ks.grids.non0tab = ks.grids.make_mask(cell, ks.grids.coords)
    return vhf + vx
Пример #43
0
def kernel(mc, ot, root=-1):
    ''' Calculate MC-PDFT total energy

        Args:
            mc : an instance of CASSCF or CASCI class
                Note: this function does not currently run the CASSCF or CASCI calculation itself
                prior to calculating the MC-PDFT energy. Call mc.kernel () before passing to this function!
            ot : an instance of on-top density functional class - see otfnal.py

        Kwargs:
            root : int
                If mc describes a state-averaged calculation, select the root (0-indexed)
                Negative number requests state-averaged MC-PDFT results (i.e., using state-averaged density matrices)

        Returns:
            Total MC-PDFT energy including nuclear repulsion energy.
    '''
    t0 = (time.clock(), time.time())
    amo = mc.mo_coeff[:, mc.ncore:mc.ncore + mc.ncas]
    # make_rdm12s returns (a, b), (aa, ab, bb)

    mc_1root = mc
    if isinstance(mc.ci, list) and root >= 0:
        mc_1root = mcscf.CASCI(mc._scf, mc.ncas, mc.nelecas)
        mc_1root.fcisolver = fci.solver(mc._scf.mol, singlet=False, symm=False)
        mc_1root.mo_coeff = mc.mo_coeff
        mc_1root.ci = mc.ci[root]
        mc_1root.e_tot = mc.e_tot
    dm1s = np.asarray(mc_1root.make_rdm1s())
    adm1s = np.stack(mc_1root.fcisolver.make_rdm1s(mc_1root.ci, mc.ncas,
                                                   mc.nelecas),
                     axis=0)
    adm2 = get_2CDM_from_2RDM(
        mc_1root.fcisolver.make_rdm12(mc_1root.ci, mc.ncas, mc.nelecas)[1],
        adm1s)
    if ot.verbose >= logger.DEBUG:
        adm2s = get_2CDMs_from_2RDMs(
            mc_1root.fcisolver.make_rdm12s(mc_1root.ci, mc.ncas,
                                           mc.nelecas)[1], adm1s)
        adm2s_ss = adm2s[0] + adm2s[2]
        adm2s_os = adm2s[1]
    spin = abs(mc.nelecas[0] - mc.nelecas[1])
    t0 = logger.timer(ot, 'rdms', *t0)

    omega, alpha, hyb = ot._numint.rsh_and_hybrid_coeff(ot.otxc, spin=spin)
    Vnn = mc._scf.energy_nuc()
    h = mc._scf.get_hcore()
    dm1 = dm1s[0] + dm1s[1]
    if ot.verbose >= logger.DEBUG or abs(hyb) > 1e-10:
        vj, vk = mc._scf.get_jk(dm=dm1s)
        vj = vj[0] + vj[1]
    else:
        vj = mc._scf.get_j(dm=dm1)
    Te_Vne = np.tensordot(h, dm1)
    # (vj_a + vj_b) * (dm_a + dm_b)
    E_j = np.tensordot(vj, dm1) / 2
    # (vk_a * dm_a) + (vk_b * dm_b) Mind the difference!
    if ot.verbose >= logger.DEBUG or abs(hyb) > 1e-10:
        E_x = -(np.tensordot(vk[0], dm1s[0]) +
                np.tensordot(vk[1], dm1s[1])) / 2
    else:
        E_x = 0
    logger.debug(ot, 'CAS energy decomposition:')
    logger.debug(ot, 'Vnn = %s', Vnn)
    logger.debug(ot, 'Te + Vne = %s', Te_Vne)
    logger.debug(ot, 'E_j = %s', E_j)
    logger.debug(ot, 'E_x = %s', E_x)
    if ot.verbose >= logger.DEBUG:
        # g_pqrs * l_pqrs / 2
        #if ot.verbose >= logger.DEBUG:
        aeri = ao2mo.restore(1, mc.get_h2eff(mc.mo_coeff), mc.ncas)
        E_c = np.tensordot(aeri, adm2, axes=4) / 2
        E_c_ss = np.tensordot(aeri, adm2s_ss, axes=4) / 2
        E_c_os = np.tensordot(aeri, adm2s_os, axes=4)  # ab + ba -> factor of 2
        logger.info(ot, 'E_c = %s', E_c)
        logger.info(ot, 'E_c (SS) = %s', E_c_ss)
        logger.info(ot, 'E_c (OS) = %s', E_c_os)
        e_err = E_c_ss + E_c_os - E_c
        assert (abs(e_err) < 1e-8), e_err
        if isinstance(mc_1root.e_tot, float):
            e_err = mc_1root.e_tot - (Vnn + Te_Vne + E_j + E_x + E_c)
            assert (abs(e_err) < 1e-8), e_err
    if abs(hyb) > 1e-10:
        logger.debug(ot, 'Adding %s * %s CAS exchange to E_ot', hyb, E_x)
    t0 = logger.timer(ot, 'Vnn, Te, Vne, E_j, E_x', *t0)

    E_ot = get_E_ot(ot, dm1s, adm2, amo)
    t0 = logger.timer(ot, 'E_ot', *t0)
    e_tot = Vnn + Te_Vne + E_j + (hyb * E_x) + E_ot
    logger.info(ot, 'MC-PDFT E = %s, Eot(%s) = %s', e_tot, ot.otxc, E_ot)

    return e_tot, E_ot
Пример #44
0
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional

    .. note::
        This function will modify the input ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Kwargs:
        dm_last : ndarray or a list of ndarrays or 0
            The density matrix baseline.  If not 0, this function computes the
            increment of HF potential w.r.t. the reference HF potential matrix.
        vhf_last : ndarray or a list of ndarrays or 0
            The reference Vxc potential matrix.
        hermi : int
            Whether J, K matrix is hermitian

            | 0 : no hermitian or symmetric
            | 1 : hermitian
            | 2 : anti-hermitian

    Returns:
        matrix Veff = J + Vxc.  Veff can be a list matrices, if the input
        dm is a list of density matrices.
    '''
    if mol is None: mol = ks.mol
    if dm is None: dm = ks.make_rdm1()
    t0 = (logger.process_clock(), logger.perf_counter())

    ground_state = (isinstance(dm, numpy.ndarray) and dm.ndim == 2)

    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        if ks.small_rho_cutoff > 1e-20 and ground_state:
            # Filter grids the first time setup grids
            ks.grids = prune_small_rho_grids_(ks, mol, dm, ks.grids)
        t0 = logger.timer(ks, 'setting up grids', *t0)
    if ks.nlc != '':
        if ks.nlcgrids.coords is None:
            ks.nlcgrids.build(with_non0tab=True)
            if ks.small_rho_cutoff > 1e-20 and ground_state:
                # Filter grids the first time setup grids
                ks.nlcgrids = prune_small_rho_grids_(ks, mol, dm, ks.nlcgrids)
            t0 = logger.timer(ks, 'setting up nlc grids', *t0)

    ni = ks._numint
    if hermi == 2:  # because rho = 0
        n, exc, vxc = 0, 0, 0
    else:
        max_memory = ks.max_memory - lib.current_memory()[0]
        n, exc, vxc = ni.nr_rks(mol,
                                ks.grids,
                                ks.xc,
                                dm,
                                max_memory=max_memory)
        if ks.nlc:
            assert 'VV10' in ks.nlc.upper()
            _, enlc, vnlc = ni.nr_rks(mol,
                                      ks.nlcgrids,
                                      ks.xc + '__' + ks.nlc,
                                      dm,
                                      max_memory=max_memory)
            exc += enlc
            vxc += vnlc
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    #enabling range-separated hybrids
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(ks.xc, spin=mol.spin)

    if abs(hyb) < 1e-10 and abs(alpha) < 1e-10:
        vk = None
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vj', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj = ks.get_j(mol, ddm, hermi)
            vj += vhf_last.vj
        else:
            vj = ks.get_j(mol, dm, hermi)
        vxc += vj
    else:
        if (ks._eri is None and ks.direct_scf
                and getattr(vhf_last, 'vk', None) is not None):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:  # For range separated Coulomb operator
                vklr = ks.get_k(mol, ddm, hermi, omega=omega)
                vklr *= (alpha - hyb)
                vk += vklr
            vj += vhf_last.vj
            vk += vhf_last.vk
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
            vk *= hyb
            if abs(omega) > 1e-10:
                vklr = ks.get_k(mol, dm, hermi, omega=omega)
                vklr *= (alpha - hyb)
                vk += vklr
        vxc += vj - vk * .5

        if ground_state:
            exc -= numpy.einsum('ij,ji', dm, vk).real * .5 * .5

    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm, vj).real * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=vj, vk=vk)
    return vxc
Пример #45
0
def DMRG_COMPRESS_NEVPT(mc, maxM=500, root=0, nevptsolver=None, tol=1e-7):
    if (isinstance(mc, str)):
        mol = chkfile.load_mol(mc)

        fh5 = h5py.File(mc, 'r')
        ncas = fh5['mc/ncas'].value
        ncore = fh5['mc/ncore'].value
        nvirt = fh5['mc/nvirt'].value
        nelecas = fh5['mc/nelecas'].value
        nroots = fh5['mc/nroots'].value
        wfnsym = fh5['mc/wfnsym'].value
        fh5.close()
        mc_chk = mc
    else :
        mol = mc.mol
        ncas = mc.ncas
        ncore = mc.ncore
        nvirt = mc.mo_coeff.shape[1] - mc.ncas-mc.ncore
        nelecas = mc.nelecas
        nroots = mc.fcisolver.nroots
        wfnsym = mc.fcisolver.wfnsym
        mc_chk = 'nevpt_perturb_integral'
        write_chk(mc, root, mc_chk)

    if nevptsolver is None:
        nevptsolver = default_nevpt_schedule(mol,maxM, tol)
        nevptsolver.wfnsym = wfnsym
        nevptsolver.block_extra_keyword = mc.fcisolver.block_extra_keyword
    nevptsolver.nroots = nroots
    from pyscf.dmrgscf import settings
    nevptsolver.executable = settings.BLOCKEXE_COMPRESS_NEVPT
    scratch = nevptsolver.scratchDirectory
    nevptsolver.scratchDirectory = ''


    dmrgci.writeDMRGConfFile(nevptsolver, nelecas, False, with_2pdm=False,
                             extraline=['fullrestart','nevpt_state_num %d'%root])
    nevptsolver.scratchDirectory = scratch

    if nevptsolver.verbose >= logger.DEBUG1:
        inFile = os.path.join(nevptsolver.runtimeDir, nevptsolver.configFile)
        logger.debug1(nevptsolver, 'Block Input conf')
        logger.debug1(nevptsolver, open(inFile, 'r').read())

    t0 = (time.clock(), time.time())

    cmd = ' '.join((nevptsolver.mpiprefix,
                    '%s/nevpt_mpi.py' % os.path.dirname(os.path.realpath(__file__)),
                    mc_chk,
                    nevptsolver.executable,
                    os.path.join(nevptsolver.runtimeDir, nevptsolver.configFile),
                    nevptsolver.outputFile,
                    nevptsolver.scratchDirectory))
    logger.debug(nevptsolver, 'DMRG_COMPRESS_NEVPT cmd %s', cmd)

    try:
        output = subprocess.check_call(cmd, shell=True)
    except subprocess.CalledProcessError as err:
        logger.error(nevptsolver, cmd)
        raise err

    if nevptsolver.verbose >= logger.DEBUG1:
        logger.debug1(nevptsolver, open(os.path.join(nevptsolver.scratchDirectory, '0/dmrg.out')).read())

    fh5 = h5py.File('Perturbation_%d'%root,'r')
    Vi_e  =  fh5['Vi/energy'].value
    Vr_e  =  fh5['Vr/energy'].value
    fh5.close()
    logger.note(nevptsolver,'Nevpt Energy:')
    logger.note(nevptsolver,'Sr Subspace:  E = %.14f'%( Vr_e))
    logger.note(nevptsolver,'Si Subspace:  E = %.14f'%( Vi_e))

    logger.timer(nevptsolver,'MPS NEVPT calculation time', *t0)
Пример #46
0
    def build(self, omega=None, direct_scf_tol=None):
        cpu0 = (time.clock(), time.time())
        cell = self.cell
        kpts = self.kpts

        k_scaled = cell.get_scaled_kpts(kpts).sum(axis=0)
        k_mod_to_half = k_scaled * 2 - (k_scaled * 2).round(0)
        if abs(k_mod_to_half).sum() > 1e-5:
            raise NotImplementedError('k-points must be symmetryic')

        if omega is not None:
            self.omega = omega

        if self.omega is None:
            # Search a proper range-separation parameter omega that can balance the
            # computational cost between the real space integrals and moment space
            # integrals
            self.omega, self.mesh, self.ke_cutoff = _guess_omega(
                cell, kpts, self.mesh)
        else:
            self.ke_cutoff = aft.estimate_ke_cutoff_for_omega(cell, self.omega)
            self.mesh = pbctools.cutoff_to_mesh(cell.lattice_vectors(),
                                                self.ke_cutoff)

        logger.info(self, 'omega = %.15g  ke_cutoff = %s  mesh = %s',
                    self.omega, self.ke_cutoff, self.mesh)

        if direct_scf_tol is None:
            direct_scf_tol = cell.precision**1.5
            logger.debug(self, 'Set direct_scf_tol %g', direct_scf_tol)

        self.cell_rs = cell_rs = _re_contract_cell(cell, self.ke_cutoff)
        self.bvk_kmesh = kmesh = k2gamma.kpts_to_kmesh(cell_rs, kpts)
        bvkcell, phase = k2gamma.get_phase(cell_rs, kpts, kmesh)
        self.bvkmesh_Ls = Ks = k2gamma.translation_vectors_for_kmesh(
            cell_rs, kmesh)
        self.bvkcell = bvkcell
        self.phase = phase

        # Given ke_cutoff, eta corresponds to the most steep Gaussian basis
        # of which the Coulomb integrals can be accurately computed in moment
        # space.
        eta = aft.estimate_eta_for_ke_cutoff(cell,
                                             self.ke_cutoff,
                                             precision=cell.precision)
        # * Assuming the most steep function in smooth basis has exponent eta,
        # with attenuation parameter omega, rcut_sr is the distance of which
        # the value of attenuated Coulomb integrals of four shells |eta> is
        # smaller than the required precision.
        # * The attenuated coulomb integrals between four s-type Gaussians
        # (2*a/pi)^{3/4}exp(-a*r^2) is
        #   (erfc(omega*a^0.5/(omega^2+a)^0.5*R) - erfc(a^0.5*R)) / R
        # if two Gaussians on one center and the other two on another center
        # and the distance between the two centers are R.
        # * The attenuated coulomb integrals between two spherical charge
        # distributions is
        #   ~(pi/eta)^3/2 (erfc(tau*(eta/2)^0.5*R) - erfc((eta/2)^0.5*R)) / R
        #       tau = omega/sqrt(omega^2 + eta/2)
        # if the spherical charge distribution is the product of above s-type
        # Gaussian with exponent eta and a very smooth function.
        # When R is large, the attenuated Coulomb integral is
        #   ~= (pi/eta)^3/2 erfc(tau*(eta/2)^0.5*R) / R
        #   ~= pi/(tau*eta^2*R^2) exp(-tau^2*eta*R^2/2)
        tau = self.omega / (self.omega**2 + eta / 2)**.5
        rcut_sr = 10  # initial guess
        rcut_sr = (-np.log(direct_scf_tol * tau * (eta * rcut_sr)**2 / np.pi) /
                   (tau**2 * eta / 2))**.5
        logger.debug(self, 'eta = %g  rcut_sr = %g', eta, rcut_sr)

        # Ls is the translation vectors to mimic periodicity of a cell
        Ls = bvkcell.get_lattice_Ls(rcut=cell.rcut + rcut_sr)
        self.supmol_Ls = Ls = Ls[np.linalg.norm(Ls, axis=1).argsort()]

        supmol = _make_extended_mole(cell_rs, Ls, Ks, self.omega,
                                     direct_scf_tol)
        self.supmol = supmol

        nkpts = len(self.bvkmesh_Ls)
        nbas = cell_rs.nbas
        n_steep, n_local, n_diffused = cell_rs._nbas_each_set
        n_compact = n_steep + n_local
        bas_mask = supmol._bas_mask

        self.bvk_bas_mask = bvk_bas_mask = bas_mask.any(axis=2)
        # Some basis in bvk-cell are not presented in the supmol. They can be
        # skipped when computing SR integrals
        self.bvkcell._bas = bvkcell._bas[bvk_bas_mask.ravel()]

        # Record the mapping between the dense bvkcell basis and the
        # original sparse bvkcell basis
        bvk_cell_idx = np.repeat(np.arange(nkpts)[:, None], nbas, axis=1)
        self.bvk_cell_id = bvk_cell_idx[bvk_bas_mask].astype(np.int32)
        cell0_shl_idx = np.repeat(np.arange(nbas)[None, :], nkpts, axis=0)
        self.cell0_shl_id = cell0_shl_idx[bvk_bas_mask].astype(np.int32)

        logger.timer_debug1(self, 'initializing supmol', *cpu0)
        logger.info(self, 'sup-mol nbas = %d cGTO = %d pGTO = %d', supmol.nbas,
                    supmol.nao, supmol.npgto_nr())

        supmol.omega = -self.omega  # Set short range coulomb
        with supmol.with_integral_screen(direct_scf_tol**2):
            vhfopt = _vhf.VHFOpt(supmol,
                                 'int2e_sph',
                                 qcondname=libpbc.PBCVHFsetnr_direct_scf)
        vhfopt.direct_scf_tol = direct_scf_tol
        self.vhfopt = vhfopt
        logger.timer(self, 'initializing vhfopt', *cpu0)

        q_cond = vhfopt.get_q_cond((supmol.nbas, supmol.nbas))
        idx = supmol._images_loc
        bvk_q_cond = lib.condense('NP_absmax', q_cond, idx, idx)
        ovlp_mask = bvk_q_cond > direct_scf_tol
        # Remove diffused-diffused block
        if n_diffused > 0:
            diffused_mask = np.zeros_like(bvk_bas_mask)
            diffused_mask[:, n_compact:] = True
            diffused_mask = diffused_mask[bvk_bas_mask]
            ovlp_mask[diffused_mask[:, None] & diffused_mask] = False
        self.ovlp_mask = ovlp_mask.astype(np.int8)

        # mute rcut_threshold, divide basis into two sets only
        cell_lr_aft = _re_contract_cell(cell, self.ke_cutoff, -1, verbose=0)
        self.lr_aft = lr_aft = _LongRangeAFT(cell_lr_aft, kpts, self.omega,
                                             self.bvk_kmesh)
        lr_aft.ke_cutoff = self.ke_cutoff
        lr_aft.mesh = self.mesh
        lr_aft.eta = eta
        return self
Пример #47
0
def get_veff(ks,
             cell=None,
             dm=None,
             dm_last=0,
             vhf_last=0,
             hermi=1,
             kpt=None,
             kpts_band=None):
    '''Coulomb + XC functional for UKS.  See pyscf/pbc/dft/uks.py
    :func:`get_veff` fore more details.
    '''
    if cell is None: cell = ks.cell
    if dm is None: dm = ks.make_rdm1()
    if kpt is None: kpt = ks.kpt
    t0 = (time.clock(), time.time())

    omega, alpha, hyb = ks._numint.rsh_and_hybrid_coeff(ks.xc, spin=cell.spin)
    if abs(omega) > 1e-10:
        raise NotImplementedError
    hybrid = abs(hyb) > 1e-10

    if not hybrid and isinstance(ks.with_df, multigrid.MultiGridFFTDF):
        n, exc, vxc = multigrid.nr_uks(ks.with_df,
                                       ks.xc,
                                       dm,
                                       hermi,
                                       kpt.reshape(1, 3),
                                       kpts_band,
                                       with_j=True,
                                       return_j=False)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)
        return vxc

    # ndim = 3 : dm.shape = ([alpha,beta], nao, nao)
    ground_state = (dm.ndim == 3 and dm.shape[0] == 2 and kpts_band is None)

    if ks.grids.non0tab is None:
        ks.grids.build(with_non0tab=True)
        if (isinstance(ks.grids, gen_grid.BeckeGrids)
                and ks.small_rho_cutoff > 1e-20 and ground_state):
            ks.grids = rks.prune_small_rho_grids_(ks, cell, dm, ks.grids, kpt)
        t0 = logger.timer(ks, 'setting up grids', *t0)

    if not isinstance(dm, numpy.ndarray):
        dm = numpy.asarray(dm)
    if dm.ndim == 2:  # RHF DM
        dm = numpy.asarray((dm * .5, dm * .5))

    if hermi == 2:  # because rho = 0
        n, exc, vxc = (0, 0), 0, 0
    else:
        n, exc, vxc = ks._numint.nr_uks(cell, ks.grids, ks.xc, dm, 0, kpt,
                                        kpts_band)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    if not hybrid:
        vj = ks.get_j(cell, dm[0] + dm[1], hermi, kpt, kpts_band)
        vxc += vj
    else:
        if getattr(ks.with_df, '_j_only', False):  # for GDF and MDF
            ks.with_df._j_only = False
        vj, vk = ks.get_jk(cell, dm, hermi, kpt, kpts_band)
        vj = vj[0] + vj[1]
        vxc += vj - vk * hyb

        if ground_state:
            exc -= (numpy.einsum('ij,ji', dm[0], vk[0]) +
                    numpy.einsum('ij,ji', dm[1], vk[1])).real * hyb * .5

    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm[0] + dm[1], vj).real * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=None, vk=None)
    return vxc
Пример #48
0
    def build(self):

        t0 = (time.clock(), time.time())
        lib.logger.TIMER_LEVEL = 3

        self.mol = lib.chkfile.load_mol(self.chkfile)
        self.nelectron = self.mol.nelectron
        self.charge = self.mol.charge
        self.spin = self.mol.spin
        self.natm = self.mol.natm
        self.coords = numpy.asarray([(numpy.asarray(atom[1])).tolist()
                                     for atom in self.mol._atom])
        self.charges = self.mol.atom_charges()
        if (self.cas):
            self.mo_coeff = lib.chkfile.load(self.chkfile, 'mcscf/mo_coeff')
        else:
            self.mo_coeff = lib.chkfile.load(self.chkfile, 'scf/mo_coeff')
        self.mo_occ = lib.chkfile.load(self.chkfile, 'scf/mo_occ')
        nprims, nmo = self.mo_coeff.shape
        self.nprims = nprims
        self.nmo = nmo
        if self.charges[self.inuc] == 1:
            self.rad = grid.BRAGG[self.charges[self.inuc]]
        else:
            self.rad = grid.BRAGG[self.charges[self.inuc]] * 0.5

        if (self.corr):
            self.rdm1 = lib.chkfile.load(self.chkfile, 'rdm/rdm1')
            natocc, natorb = numpy.linalg.eigh(self.rdm1)
            natorb = numpy.dot(self.mo_coeff, natorb)
            self.mo_coeff = natorb
            self.mo_occ = natocc
        nocc = self.mo_occ[abs(self.mo_occ) > self.occdrop]
        nocc = len(nocc)
        self.nocc = nocc

        idx = 'atom' + str(self.inuc)
        with h5py.File(self.surfile) as f:
            self.xnuc = f[idx + '/xnuc'].value
            self.xyzrho = f[idx + '/xyzrho'].value
            self.npang = f[idx + '/npang'].value
            self.ntrial = f[idx + '/ntrial'].value
            self.rmin = f[idx + '/rmin'].value
            self.rmax = f[idx + '/rmax'].value
            self.rsurf = f[idx + '/rsurf'].value
            self.nlimsurf = f[idx + '/nlimsurf'].value
            self.agrids = f[idx + '/coords'].value

        self.brad = self.rmin * self.betafac

        if self.verbose >= logger.WARN:
            self.check_sanity()
        if self.verbose > logger.NOTE:
            self.dump_input()

        if (self.iqudr == 'legendre'):
            self.iqudr = 1
        if (self.biqudr == 'legendre'):
            self.biqudr = 1

        if (self.mapr == 'becke'):
            self.mapr = 1
        elif (self.mapr == 'exp'):
            self.mapr = 2
        elif (self.mapr == 'none'):
            self.mapr = 0
        if (self.bmapr == 'becke'):
            self.bmapr = 1
        elif (self.bmapr == 'exp'):
            self.bmapr = 2
        elif (self.bmapr == 'none'):
            self.bmapr = 0

        if (self.full):
            self.nocc = self.nmo
            nocc = self.nmo
        else:
            nocc = self.mo_occ[self.mo_occ > self.occdrop]
            nocc = len(nocc)
            self.nocc = nocc

        self.aom = numpy.zeros((nocc, nocc))

        with lib.with_omp_threads(self.nthreads):
            aomb = int_beta(self)
            aoma = out_beta(self)

        idx = 0
        for i in range(nocc):
            for j in range(i + 1):
                self.aom[i, j] = aoma[idx] + aomb[idx]
                self.aom[j, i] = self.aom[i, j]
                idx += 1
        if (self.nmo <= 30):
            dump_tri(self.stdout, self.aom, ncol=NCOL, digits=DIGITS, start=0)

        logger.info(self, 'Write info to HDF5 file')
        atom_dic = {'aom': self.aom}
        lib.chkfile.save(self.surfile, 'ovlp' + str(self.inuc), atom_dic)
        logger.info(self, '')

        logger.info(self, 'AOM of atom %d done', self.inuc)
        logger.timer(self, 'AOM build', *t0)

        return self
Пример #49
0
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional for UKS.  See pyscf/dft/rks.py
    :func:`get_veff` fore more details.
    '''
    if mol is None: mol = self.mol
    if dm is None: dm = ks.make_rdm1()
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        small_rho_cutoff = ks.small_rho_cutoff
        t0 = logger.timer(ks, 'setting up grids', *t0)
    else:
        # Filter grids only for the first time setting up grids
        small_rho_cutoff = 0

    if not isinstance(dm, numpy.ndarray):
        dm = numpy.asarray(dm)
    if dm.ndim == 2:  # RHF DM
        dm = numpy.asarray((dm * .5, dm * .5))

    if hermi == 2:  # because rho = 0
        n, ks._exc, vx = (0, 0), 0, 0
    else:
        n, ks._exc, vx = ks._numint.nr_uks(mol, ks.grids, ks.xc, dm)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    ground_state = (dm.ndim == 3 and dm.shape[0] == 2)

    hyb = ks._numint.hybrid_coeff(ks.xc, spin=mol.spin)
    if abs(hyb) < 1e-10:
        if (ks._eri is not None or not ks.direct_scf
                or not hasattr(ks, '_dm_last')
                or not isinstance(vhf_last, numpy.ndarray)):
            vj = ks.get_j(mol, dm, hermi)
        else:
            ddm = dm - numpy.asarray(ks._dm_last)
            vj = ks.get_j(mol, ddm, hermi)
            vj += ks._vj_last
            ks._dm_last = dm
            ks._vj_last = vj
        vhf = vj[0] + vj[1]
        vhf = numpy.asarray((vhf, vhf))
    else:
        if (ks._eri is not None or not ks.direct_scf
                or not hasattr(ks, '_dm_last')
                or not isinstance(vhf_last, numpy.ndarray)):
            vj, vk = ks.get_jk(mol, dm, hermi)
        else:
            ddm = dm - numpy.asarray(ks._dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vj += ks._vj_last
            vk += ks._vk_last
            ks._dm_last = dm
            ks._vj_last, ks._vk_last = vj, vk
        vhf = uhf._makevhf(vj, vk * hyb)

        if ground_state:
            ks._exc -= (numpy.einsum('ij,ji', dm[0], vk[0]) +
                        numpy.einsum('ij,ji', dm[1], vk[1])) * .5 * hyb
    if ground_state:
        ks._ecoul = numpy.einsum('ij,ji', dm[0] + dm[1], vj[0] + vj[1]) * .5

    nelec = mol.nelec
    if (small_rho_cutoff > 1e-20 and ground_state
            and abs(n[0] - nelec[0]) < 0.01 * n[0]
            and abs(n[1] - nelec[1]) < 0.01 * n[1]):
        idx = ks._numint.large_rho_indices(mol, dm[0] + dm[1], ks.grids,
                                           small_rho_cutoff)
        logger.debug(ks, 'Drop grids %d',
                     ks.grids.weights.size - numpy.count_nonzero(idx))
        ks.grids.coords = numpy.asarray(ks.grids.coords[idx], order='C')
        ks.grids.weights = numpy.asarray(ks.grids.weights[idx], order='C')
        ks.grids.non0tab = ks.grids.make_mask(mol, ks.grids.coords)
    return vhf + vx
Пример #50
0
def get_jk(dfobj, dm, hermi=1, with_j=True, with_k=True, direct_scf_tol=1e-13):
    assert (with_j or with_k)
    if (not with_k and not dfobj.mol.incore_anyway and
            # 3-center integral tensor is not initialized
            dfobj._cderi is None):
        return get_j(dfobj, dm, hermi, direct_scf_tol), None

    t0 = t1 = (time.clock(), time.time())
    log = logger.Logger(dfobj.stdout, dfobj.verbose)
    fmmm = _ao2mo.libao2mo.AO2MOmmm_bra_nr_s2
    fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv
    ftrans = _ao2mo.libao2mo.AO2MOtranse2_nr_s2
    null = lib.c_null_ptr()

    dms = numpy.asarray(dm)
    dm_shape = dms.shape
    nao = dm_shape[-1]
    dms = dms.reshape(-1, nao, nao)
    nset = dms.shape[0]
    vj = 0
    vk = numpy.zeros_like(dms)

    if with_j:
        idx = numpy.arange(nao)
        dmtril = lib.pack_tril(dms + dms.conj().transpose(0, 2, 1))
        dmtril[:, idx * (idx + 1) // 2 + idx] *= .5

    if not with_k:
        for eri1 in dfobj.loop():
            rho = numpy.einsum('ix,px->ip', dmtril, eri1)
            vj += numpy.einsum('ip,px->ix', rho, eri1)

    elif getattr(dm, 'mo_coeff', None) is not None:
        #TODO: test whether dm.mo_coeff matching dm
        mo_coeff = numpy.asarray(dm.mo_coeff, order='F')
        mo_occ = numpy.asarray(dm.mo_occ)
        nmo = mo_occ.shape[-1]
        mo_coeff = mo_coeff.reshape(-1, nao, nmo)
        mo_occ = mo_occ.reshape(-1, nmo)
        if mo_occ.shape[0] * 2 == nset:  # handle ROHF DM
            mo_coeff = numpy.vstack((mo_coeff, mo_coeff))
            mo_occa = numpy.array(mo_occ > 0, dtype=numpy.double)
            mo_occb = numpy.array(mo_occ == 2, dtype=numpy.double)
            assert (mo_occa.sum() + mo_occb.sum() == mo_occ.sum())
            mo_occ = numpy.vstack((mo_occa, mo_occb))

        orbo = []
        for k in range(nset):
            c = numpy.einsum('pi,i->pi', mo_coeff[k][:, mo_occ[k] > 0],
                             numpy.sqrt(mo_occ[k][mo_occ[k] > 0]))
            orbo.append(numpy.asarray(c, order='F'))

        max_memory = dfobj.max_memory - lib.current_memory()[0]
        blksize = max(4,
                      int(min(dfobj.blockdim, max_memory * .3e6 / 8 / nao**2)))
        buf = numpy.empty((blksize * nao, nao))
        for eri1 in dfobj.loop(blksize):
            naux, nao_pair = eri1.shape
            assert (nao_pair == nao * (nao + 1) // 2)
            if with_j:
                rho = numpy.einsum('ix,px->ip', dmtril, eri1)
                vj += numpy.einsum('ip,px->ix', rho, eri1)

            for k in range(nset):
                nocc = orbo[k].shape[1]
                if nocc > 0:
                    buf1 = buf[:naux * nocc]
                    fdrv(ftrans, fmmm, buf1.ctypes.data_as(ctypes.c_void_p),
                         eri1.ctypes.data_as(ctypes.c_void_p),
                         orbo[k].ctypes.data_as(ctypes.c_void_p),
                         ctypes.c_int(naux), ctypes.c_int(nao),
                         (ctypes.c_int * 4)(0, nocc, 0, nao), null,
                         ctypes.c_int(0))
                    vk[k] += lib.dot(buf1.T, buf1)
            t1 = log.timer_debug1('jk', *t1)
    else:
        #:vk = numpy.einsum('pij,jk->pki', cderi, dm)
        #:vk = numpy.einsum('pki,pkj->ij', cderi, vk)
        rargs = (ctypes.c_int(nao), (ctypes.c_int * 4)(0, nao, 0, nao), null,
                 ctypes.c_int(0))
        dms = [numpy.asarray(x, order='F') for x in dms]
        max_memory = dfobj.max_memory - lib.current_memory()[0]
        blksize = max(
            4, int(min(dfobj.blockdim, max_memory * .22e6 / 8 / nao**2)))
        buf = numpy.empty((2, blksize, nao, nao))
        for eri1 in dfobj.loop(blksize):
            naux, nao_pair = eri1.shape
            if with_j:
                rho = numpy.einsum('ix,px->ip', dmtril, eri1)
                vj += numpy.einsum('ip,px->ix', rho, eri1)

            for k in range(nset):
                buf1 = buf[0, :naux]
                fdrv(ftrans, fmmm, buf1.ctypes.data_as(ctypes.c_void_p),
                     eri1.ctypes.data_as(ctypes.c_void_p),
                     dms[k].ctypes.data_as(ctypes.c_void_p),
                     ctypes.c_int(naux), *rargs)

                buf2 = lib.unpack_tril(eri1, out=buf[1])
                vk[k] += lib.dot(
                    buf1.reshape(-1, nao).T, buf2.reshape(-1, nao))
            t1 = log.timer_debug1('jk', *t1)

    if with_j: vj = lib.unpack_tril(vj, 1).reshape(dm_shape)
    if with_k: vk = vk.reshape(dm_shape)
    logger.timer(dfobj, 'df vj and vk', *t0)
    return vj, vk
Пример #51
0
def get_jk(dfobj, dm, hermi=1, vhfopt=None, with_j=True, with_k=True):
    t0 = t1 = (time.clock(), time.time())
    log = logger.Logger(dfobj.stdout, dfobj.verbose)
    assert (with_j or with_k)

    fmmm = _ao2mo.libao2mo.AO2MOmmm_bra_nr_s2
    fdrv = _ao2mo.libao2mo.AO2MOnr_e2_drv
    ftrans = _ao2mo.libao2mo.AO2MOtranse2_nr_s2
    null = lib.c_null_ptr()

    dms = numpy.asarray(dm)
    dm_shape = dms.shape
    nao = dm_shape[-1]
    dms = dms.reshape(-1, nao, nao)
    nset = dms.shape[0]
    vj = [0] * nset
    vk = [0] * nset

    if not with_k:
        dmtril = []
        idx = numpy.arange(nao)
        for k in range(nset):
            dm = lib.pack_tril(dms[k] + dms[k].T)
            dm[idx * (idx + 1) // 2 + idx] *= .5
            dmtril.append(dm)
        for eri1 in dfobj.loop():
            naux, nao_pair = eri1.shape
            for k in range(nset):
                rho = numpy.einsum('px,x->p', eri1, dmtril[k])
                vj[k] += numpy.einsum('p,px->x', rho, eri1)

    elif hasattr(dm, 'mo_coeff'):
        #TODO: test whether dm.mo_coeff matching dm
        mo_coeff = numpy.asarray(dm.mo_coeff, order='F')
        mo_occ = numpy.asarray(dm.mo_occ)
        nmo = mo_occ.shape[-1]
        mo_coeff = mo_coeff.reshape(-1, nao, nmo)
        mo_occ = mo_occ.reshape(-1, nmo)
        if mo_occ.shape[0] * 2 == nset:  # handle ROHF DM
            mo_coeff = numpy.vstack((mo_coeff, mo_coeff))
            mo_occa = numpy.array(mo_occ > 0, dtype=numpy.double)
            mo_occb = numpy.array(mo_occ == 2, dtype=numpy.double)
            assert (mo_occa.sum() + mo_occb.sum() == mo_occ.sum())
            mo_occ = numpy.vstack((mo_occa, mo_occb))

        dmtril = []
        orbo = []
        for k in range(nset):
            if with_j:
                dmtril.append(lib.pack_tril(dms[k] + dms[k].T))
                i = numpy.arange(nao)
                dmtril[k][i * (i + 1) // 2 + i] *= .5

            c = numpy.einsum('pi,i->pi', mo_coeff[k][:, mo_occ[k] > 0],
                             numpy.sqrt(mo_occ[k][mo_occ[k] > 0]))
            orbo.append(numpy.asarray(c, order='F'))

        buf = numpy.empty((dfobj.blockdim * nao, nao))
        for eri1 in dfobj.loop():
            naux, nao_pair = eri1.shape
            assert (nao_pair == nao * (nao + 1) // 2)
            for k in range(nset):
                if with_j:
                    rho = numpy.einsum('px,x->p', eri1, dmtril[k])
                    vj[k] += numpy.einsum('p,px->x', rho, eri1)

                nocc = orbo[k].shape[1]
                if nocc > 0:
                    buf1 = buf[:naux * nocc]
                    fdrv(ftrans, fmmm, buf1.ctypes.data_as(ctypes.c_void_p),
                         eri1.ctypes.data_as(ctypes.c_void_p),
                         orbo[k].ctypes.data_as(ctypes.c_void_p),
                         ctypes.c_int(naux), ctypes.c_int(nao),
                         (ctypes.c_int * 4)(0, nocc, 0, nao), null,
                         ctypes.c_int(0))
                    vk[k] += lib.dot(buf1.T, buf1)
            t1 = log.timer_debug1('jk', *t1)
    else:
        #:vk = numpy.einsum('pij,jk->pki', cderi, dm)
        #:vk = numpy.einsum('pki,pkj->ij', cderi, vk)
        rargs = (ctypes.c_int(nao), (ctypes.c_int * 4)(0, nao, 0, nao), null,
                 ctypes.c_int(0))
        dms = [numpy.asarray(x, order='F') for x in dms]
        buf = numpy.empty((2, dfobj.blockdim, nao, nao))
        for eri1 in dfobj.loop():
            naux, nao_pair = eri1.shape
            for k in range(nset):
                buf1 = buf[0, :naux]
                fdrv(ftrans, fmmm, buf1.ctypes.data_as(ctypes.c_void_p),
                     eri1.ctypes.data_as(ctypes.c_void_p),
                     dms[k].ctypes.data_as(ctypes.c_void_p),
                     ctypes.c_int(naux), *rargs)
                if with_j:
                    rho = numpy.einsum('kii->k', buf1)
                    vj[k] += numpy.einsum('p,px->x', rho, eri1)

                buf2 = lib.unpack_tril(eri1, out=buf[1])
                vk[k] += lib.dot(
                    buf1.reshape(-1, nao).T, buf2.reshape(-1, nao))
            t1 = log.timer_debug1('jk', *t1)

    if with_j: vj = lib.unpack_tril(vj, 1).reshape(dm_shape)
    if with_k: vk = numpy.asarray(vk).reshape(dm_shape)
    logger.timer(dfobj, 'vj and vk', *t0)
    return vj, vk
Пример #52
0
def get_j(dfobj, dm, hermi=1, direct_scf_tol=1e-13):
    from pyscf.scf import _vhf
    from pyscf.scf import jk
    from pyscf.df import addons
    t0 = t1 = (time.clock(), time.time())

    mol = dfobj.mol
    if dfobj._vjopt is None:
        dfobj.auxmol = auxmol = addons.make_auxmol(mol, dfobj.auxbasis)
        opt = _vhf.VHFOpt(mol, 'int3c2e', 'CVHFnr3c2e_schwarz_cond')
        opt.direct_scf_tol = direct_scf_tol

        # q_cond part 1: the regular int2e (ij|ij) for mol's basis
        opt.init_cvhf_direct(mol, 'int2e', 'CVHFsetnr_direct_scf')
        mol_q_cond = lib.frompointer(opt._this.contents.q_cond, mol.nbas**2)

        # Update q_cond to include the 2e-integrals (auxmol|auxmol)
        j2c = auxmol.intor('int2c2e', hermi=1)
        j2c_diag = numpy.sqrt(abs(j2c.diagonal()))
        aux_loc = auxmol.ao_loc
        aux_q_cond = [
            j2c_diag[i0:i1].max() for i0, i1 in zip(aux_loc[:-1], aux_loc[1:])
        ]
        q_cond = numpy.hstack((mol_q_cond, aux_q_cond))
        fsetqcond = _vhf.libcvhf.CVHFset_q_cond
        fsetqcond(opt._this, q_cond.ctypes.data_as(ctypes.c_void_p),
                  ctypes.c_int(q_cond.size))

        try:
            opt.j2c = j2c = scipy.linalg.cho_factor(j2c, lower=True)
            opt.j2c_type = 'cd'
        except scipy.linalg.LinAlgError:
            opt.j2c = j2c
            opt.j2c_type = 'regular'

        # jk.get_jk function supports 4-index integrals. Use bas_placeholder
        # (l=0, nctr=1, 1 function) to hold the last index.
        bas_placeholder = numpy.array([0, 0, 1, 1, 0, 0, 0, 0],
                                      dtype=numpy.int32)
        fakemol = mol + auxmol
        fakemol._bas = numpy.vstack((fakemol._bas, bas_placeholder))
        opt.fakemol = fakemol
        dfobj._vjopt = opt
        t1 = logger.timer_debug1(dfobj, 'df-vj init_direct_scf', *t1)

    opt = dfobj._vjopt
    fakemol = opt.fakemol
    dm = numpy.asarray(dm, order='C')
    dm_shape = dm.shape
    nao = dm_shape[-1]
    dm = dm.reshape(-1, nao, nao)
    n_dm = dm.shape[0]

    # First compute the density in auxiliary basis
    # j3c = fauxe2(mol, auxmol)
    # jaux = numpy.einsum('ijk,ji->k', j3c, dm)
    # rho = numpy.linalg.solve(auxmol.intor('int2c2e'), jaux)
    nbas = mol.nbas
    nbas1 = mol.nbas + dfobj.auxmol.nbas
    shls_slice = (0, nbas, 0, nbas, nbas, nbas1, nbas1, nbas1 + 1)
    with lib.temporary_env(opt,
                           prescreen='CVHFnr3c2e_vj_pass1_prescreen',
                           _dmcondname='CVHFsetnr_direct_scf_dm'):
        jaux = jk.get_jk(fakemol,
                         dm, ['ijkl,ji->kl'] * n_dm,
                         'int3c2e',
                         aosym='s2ij',
                         hermi=0,
                         shls_slice=shls_slice,
                         vhfopt=opt)
    # remove the index corresponding to bas_placeholder
    jaux = numpy.array(jaux)[:, :, 0]
    t1 = logger.timer_debug1(dfobj, 'df-vj pass 1', *t1)

    if opt.j2c_type == 'cd':
        rho = scipy.linalg.cho_solve(opt.j2c, jaux.T)
    else:
        rho = scipy.linalg.solve(opt.j2c, jaux.T)
    # transform rho to shape (:,1,naux), to adapt to 3c2e integrals (ij|k)
    rho = rho.T[:, numpy.newaxis, :]
    t1 = logger.timer_debug1(dfobj, 'df-vj solve ', *t1)

    # Next compute the Coulomb matrix
    # j3c = fauxe2(mol, auxmol)
    # vj = numpy.einsum('ijk,k->ij', j3c, rho)
    with lib.temporary_env(opt,
                           prescreen='CVHFnr3c2e_vj_pass2_prescreen',
                           _dmcondname=None):
        # CVHFnr3c2e_vj_pass2_prescreen requires custom dm_cond
        aux_loc = dfobj.auxmol.ao_loc
        dm_cond = [
            abs(rho[:, :, i0:i1]).max()
            for i0, i1 in zip(aux_loc[:-1], aux_loc[1:])
        ]
        dm_cond = numpy.array(dm_cond)
        fsetcond = _vhf.libcvhf.CVHFset_dm_cond
        fsetcond(opt._this, dm_cond.ctypes.data_as(ctypes.c_void_p),
                 ctypes.c_int(dm_cond.size))

        vj = jk.get_jk(fakemol,
                       rho, ['ijkl,lk->ij'] * n_dm,
                       'int3c2e',
                       aosym='s2ij',
                       hermi=1,
                       shls_slice=shls_slice,
                       vhfopt=opt)

    t1 = logger.timer_debug1(dfobj, 'df-vj pass 2', *t1)
    logger.timer(dfobj, 'df-vj', *t0)
    return numpy.asarray(vj).reshape(dm_shape)
Пример #53
0
def get_veff(ks,
             cell=None,
             dm=None,
             dm_last=0,
             vhf_last=0,
             hermi=1,
             kpt=None,
             kpts_band=None):
    '''Coulomb + XC functional

    .. note::
        This function will change the ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Returns:
        matrix Veff = J + Vxc.  Veff can be a list matrices, if the input
        dm is a list of density matrices.
    '''
    if cell is None: cell = ks.cell
    if dm is None: dm = ks.make_rdm1()
    if kpt is None: kpt = ks.kpt
    t0 = (time.clock(), time.time())

    omega, alpha, hyb = ks._numint.rsh_and_hybrid_coeff(ks.xc, spin=cell.spin)
    if abs(omega) > 1e-10:
        raise NotImplementedError
    hybrid = abs(hyb) > 1e-10

    if not hybrid and isinstance(ks.with_df, multigrid.MultiGridFFTDF):
        n, exc, vxc = multigrid.nr_rks(ks.with_df,
                                       ks.xc,
                                       dm,
                                       hermi,
                                       kpt.reshape(1, 3),
                                       kpts_band,
                                       with_j=True,
                                       return_j=False)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)
        return vxc

    ground_state = (isinstance(dm, numpy.ndarray) and dm.ndim == 2
                    and kpts_band is None)

    # Use grids.non0tab to detect whether grids are initialized.  For
    # UniformGrids, grids.coords as a property cannot indicate whehter grids are
    # initialized.
    if ks.grids.non0tab is None:
        ks.grids.build(with_non0tab=True)
        if (isinstance(ks.grids, gen_grid.BeckeGrids)
                and ks.small_rho_cutoff > 1e-20 and ground_state):
            ks.grids = prune_small_rho_grids_(ks, cell, dm, ks.grids, kpt)
        t0 = logger.timer(ks, 'setting up grids', *t0)

    if hermi == 2:  # because rho = 0
        n, exc, vxc = 0, 0, 0
    else:
        n, exc, vxc = ks._numint.nr_rks(cell, ks.grids, ks.xc, dm, 0, kpt,
                                        kpts_band)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    if not hybrid:
        vj = ks.get_j(cell, dm, hermi, kpt, kpts_band)
        vxc += vj
    else:
        if getattr(ks.with_df, '_j_only', False):  # for GDF and MDF
            ks.with_df._j_only = False
        vj, vk = ks.get_jk(cell, dm, hermi, kpt, kpts_band)
        vxc += vj - vk * (hyb * .5)

        if ground_state:
            exc -= numpy.einsum('ij,ji', dm, vk).real * .5 * hyb * .5

    if ground_state:
        ecoul = numpy.einsum('ij,ji', dm, vj).real * .5
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=None, vk=None)
    return vxc
Пример #54
0
def solve_mo1(sscobj,
              mo_energy=None,
              mo_coeff=None,
              mo_occ=None,
              h1=None,
              s1=None,
              with_cphf=None):
    cput1 = (time.clock(), time.time())
    log = logger.Logger(sscobj.stdout, sscobj.verbose)
    if mo_energy is None: mo_energy = sscobj._scf.mo_energy
    if mo_coeff is None: mo_coeff = sscobj._scf.mo_coeff
    if mo_occ is None: mo_occ = sscobj._scf.mo_occ
    if with_cphf is None: with_cphf = sscobj.cphf

    mol = sscobj.mol
    if sscobj.mb.upper().startswith('ST'):  # Sternheim approximation
        nmo = mo_occ.size
        mo_energy = mo_energy[nmo // 2:]
        mo_coeff = mo_coeff[:, nmo // 2:]
        mo_occ = mo_occ[nmo // 2:]

    if h1 is None:
        atmlst = sorted(set([j for i, j in sscobj.nuc_pair]))
        h1 = numpy.asarray(make_h1(mol, mo_coeff, mo_occ, atmlst))

    if with_cphf:
        if callable(with_cphf):
            vind = with_cphf
        else:
            vind = gen_vind(sscobj._scf, mo_coeff, mo_occ)
        mo1, mo_e1 = cphf.solve(vind,
                                mo_energy,
                                mo_occ,
                                h1,
                                None,
                                sscobj.max_cycle_cphf,
                                sscobj.conv_tol,
                                verbose=log)
    else:
        e_ai = lib.direct_sum('i-a->ai', mo_energy[mo_occ > 0],
                              mo_energy[mo_occ == 0])
        mo1 = h1 / e_ai
        mo_e1 = None


# Calculate RMB with approximation
# |MO1> = Z_RMB |i> + |p> bar{C}_{pi}^1 ~= |p> C_{pi}^1
# bar{C}_{pi}^1 ~= C_{pi}^1 - <p|Z_RMB|i>
    if sscobj.mb.upper() == 'RMB':
        orbo = mo_coeff[:, mo_occ > 0]
        orbv = mo_coeff[:, mo_occ == 0]
        n4c = mo_coeff.shape[0]
        n2c = n4c // 2
        c = lib.param.LIGHT_SPEED
        orbvS_T = orbv[n2c:].conj().T
        for ia in atmlst:
            mol.set_rinv_origin(mol.atom_coord(ia))
            a01int = mol.intor('int1e_sa01sp_spinor', 3)
            for k in range(3):
                s1 = orbvS_T.dot(a01int[k].conj().T).dot(orbo[n2c:])
                mo1[ia * 3 + k] -= s1 * (.25 / c**2)

    logger.timer(sscobj, 'solving mo1 eqn', *cput1)
    return mo1, mo_e1
Пример #55
0
def get_veff(ks,
             cell=None,
             dm=None,
             dm_last=0,
             vhf_last=0,
             hermi=1,
             kpt=None,
             kpt_band=None):
    '''Coulomb + XC functional

    .. note::
        This function will change the ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.  The ._exc and ._ecoul attributes
            will be updated after return.  Attributes ._dm_last, ._vj_last and
            ._vk_last might be changed if direct SCF method is applied.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Returns:
        matrix Veff = J + Vxc.  Veff can be a list matrices, if the input
        dm is a list of density matrices.
    '''
    if cell is None: cell = ks.cell
    if dm is None: dm = ks.make_rdm1()
    if kpt is None: kpt = ks.kpt
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.build()
        small_rho_cutoff = ks.small_rho_cutoff
        t0 = logger.timer(ks, 'setting up grids', *t0)
    else:
        small_rho_cutoff = 0

    dm = numpy.asarray(dm)
    nao = dm.shape[-1]
    ground_state = (dm.ndim == 2)

    if hermi == 2:  # because rho = 0
        n, ks._exc, vx = 0, 0, 0
    else:
        n, ks._exc, vx = ks._numint.nr_rks(cell, ks.grids, ks.xc, dm, 1, kpt,
                                           kpt_band)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    hyb = ks._numint.hybrid_coeff(ks.xc, spin=(cell.spin > 0) + 1)
    if abs(hyb) < 1e-10:
        vhf = vj = ks.get_j(cell, dm, hermi, kpt, kpt_band)
    else:
        vj, vk = ks.get_jk(cell, dm, hermi, kpt, kpt_band)
        vhf = vj - vk * (hyb * .5)

        if ground_state:
            ks._exc -= numpy.einsum('ij,ji', dm, vk).real * .5 * hyb * .5

    if ground_state:
        ks._ecoul = numpy.einsum('ij,ji', dm, vj).real * .5

    if (small_rho_cutoff > 1e-20 and ground_state
            and abs(n - cell.nelectron) < 0.01 * n):
        # Filter grids the first time setup grids
        idx = ks._numint.large_rho_indices(cell, dm, ks.grids,
                                           small_rho_cutoff, kpt)
        logger.debug(ks, 'Drop grids %d',
                     ks.grids.weights.size - numpy.count_nonzero(idx))
        ks.grids.coords = numpy.asarray(ks.grids.coords[idx], order='C')
        ks.grids.weights = numpy.asarray(ks.grids.weights[idx], order='C')
        ks._numint.non0tab = None
    return vhf + vx
Пример #56
0
def get_veff(ks, cell=None, dm=None, dm_last=0, vhf_last=0, hermi=1,
             kpts=None, kpts_band=None):
    '''Coulomb + XC functional

    .. note::
        This is a replica of pyscf.dft.rks.get_veff with kpts added.
        This function will change the ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Returns:
        Veff : (nkpts, nao, nao) or (*, nkpts, nao, nao) ndarray
        Veff = J + Vxc.
    '''
    if cell is None: cell = ks.cell
    if dm is None: dm = ks.make_rdm1()
    if kpts is None: kpts = ks.kpts
    t0 = (logger.process_clock(), logger.perf_counter())

    omega, alpha, hyb = ks._numint.rsh_and_hybrid_coeff(ks.xc, spin=cell.spin)
    hybrid = abs(hyb) > 1e-10 or abs(alpha) > 1e-10

    if not hybrid and isinstance(ks.with_df, multigrid.MultiGridFFTDF):
        n, exc, vxc = multigrid.nr_rks(ks.with_df, ks.xc, dm, hermi,
                                       kpts, kpts_band,
                                       with_j=True, return_j=False)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)
        return vxc

    # ndim = 3 : dm.shape = (nkpts, nao, nao)
    ground_state = (isinstance(dm, np.ndarray) and dm.ndim == 3 and
                    kpts_band is None)

# For UniformGrids, grids.coords does not indicate whehter grids are initialized
    if ks.grids.non0tab is None:
        ks.grids.build(with_non0tab=True)
        if (isinstance(ks.grids, gen_grid.BeckeGrids) and
            ks.small_rho_cutoff > 1e-20 and ground_state):
            ks.grids = rks.prune_small_rho_grids_(ks, cell, dm, ks.grids, kpts)
        t0 = logger.timer(ks, 'setting up grids', *t0)

    if hermi == 2:  # because rho = 0
        n, exc, vxc = 0, 0, 0
    else:
        n, exc, vxc = ks._numint.nr_rks(cell, ks.grids, ks.xc, dm, hermi,
                                        kpts, kpts_band)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    weight = 1./len(kpts)
    if not hybrid:
        vj = ks.get_j(cell, dm, hermi, kpts, kpts_band)
        vxc += vj
    else:
        if getattr(ks.with_df, '_j_only', False):  # for GDF and MDF
            ks.with_df._j_only = False
        vj, vk = ks.get_jk(cell, dm, hermi, kpts, kpts_band)
        vk *= hyb
        if abs(omega) > 1e-10:
            vklr = ks.get_k(cell, dm, hermi, kpts, kpts_band, omega=omega)
            vklr *= (alpha - hyb)
            vk += vklr
        vxc += vj - vk * .5

        if ground_state:
            exc -= np.einsum('Kij,Kji', dm, vk).real * .5 * .5 * weight

    if ground_state:
        ecoul = np.einsum('Kij,Kji', dm, vj).real * .5 * weight
    else:
        ecoul = None

    vxc = lib.tag_array(vxc, ecoul=ecoul, exc=exc, vj=None, vk=None)
    return vxc
Пример #57
0
    def build(self):

        t0 = (time.clock(), time.time())
        lib.logger.TIMER_LEVEL = 3

        cell = libpbc.chkfile.load_cell(self.chkfile)
        cell.ecp = None
        self.cell = cell
        self.a = self.cell.lattice_vectors()
        self.b = self.cell.reciprocal_vectors()
        self.vol = self.cell.vol
        self.nelectron = self.cell.nelectron 
        self.charge = self.cell.charge    
        self.spin = self.cell.spin      
        self.natm = self.cell.natm		
        self.kpts = lib.chkfile.load(self.chkfile, 'kcell/kpts')
        self.nkpts = len(self.kpts)
        self.ls = cell.get_lattice_Ls(dimension=3)
        self.ls = self.ls[numpy.argsort(lib.norm(self.ls, axis=1))]
        self.atm = numpy.asarray(cell._atm, dtype=numpy.int32, order='C')
        self.bas = numpy.asarray(cell._bas, dtype=numpy.int32, order='C')
        self.env = numpy.asarray(cell._env, dtype=numpy.double, order='C')
        self.nbas = self.bas.shape[0]
        self.ao_loc = cell.ao_loc_nr()
        self.shls_slice = (0, self.nbas)
        sh0, sh1 = self.shls_slice
        self.nao = self.ao_loc[sh1] - self.ao_loc[sh0]
        self.non0tab = numpy.empty((1,self.nbas), dtype=numpy.int8)
        # non0tab stores the number of images to be summed in real space.
        # Initializing it to 255 means all images are summed
        self.non0tab[:] = 0xff
        self.coords = numpy.asarray([(numpy.asarray(atom[1])).tolist() for atom in cell._atom])
        self.charges = cell.atom_charges()
        self.mo_coeff = lib.chkfile.load(self.chkfile, 'scf/mo_coeff')
        self.mo_occ = lib.chkfile.load(self.chkfile, 'scf/mo_occ')
        nprims, nmo = self.mo_coeff[0].shape 
        self.nprims = nprims
        self.nmo = nmo
        self.cart = cell.cart
        if (not self.leb):
            self.npang = self.npphi*self.nptheta

        self.rcut = _estimate_rcut(self)
        kpts = numpy.reshape(self.kpts, (-1,3))
        kpts_lst = numpy.reshape(kpts, (-1,3))
        self.explk = numpy.exp(1j * numpy.asarray(numpy.dot(self.ls, kpts_lst.T), order='C'))

        if (self.ntrial%2 == 0): self.ntrial += 1
        geofac = numpy.power(((self.rmaxsurf-0.1)/self.rprimer),(1.0/(self.ntrial-1.0)))
        self.rpru = numpy.zeros((self.ntrial))
        for i in range(self.ntrial): 
            self.rpru[i] = self.rprimer*numpy.power(geofac,(i+1)-1)
        self.rsurf = numpy.zeros((self.npang,self.ntrial), order='C')
        self.nlimsurf = numpy.zeros((self.npang), dtype=numpy.int32)

        if self.verbose >= logger.WARN:
            self.check_sanity()
        if self.verbose > logger.NOTE:
            self.dump_input()

        if (self.iqudt == 'legendre'):
            self.iqudt = 1
        
        if (self.leb):
            self.grids = grid.lebgrid(self.npang)
        else:
            self.grids = grid.anggrid(self.iqudt,self.nptheta,self.npphi)
         
        self.xyzrho = numpy.zeros((self.natm,3))
        t = time.time()
        logger.info(self,'Time finding nucleus %.3f (sec)' % (time.time()-t))

        if (self.backend == 'rkck'):
            backend = 1
        elif (self.backend == 'rkdp'):
            backend = 2
        else:
            raise NotImplementedError('Only rkck or rkdp ODE solver yet available') 
         
        ct_ = numpy.asarray(self.grids[:,0], order='C')
        st_ = numpy.asarray(self.grids[:,1], order='C')
        cp_ = numpy.asarray(self.grids[:,2], order='C')
        sp_ = numpy.asarray(self.grids[:,3], order='C')

        mo_coeff = numpy.zeros((self.nkpts,self.nprims,self.nmo), dtype=numpy.complex128)
        mo_occ = numpy.zeros((self.nkpts,self.nmo))
        for k in range(self.nkpts):
            mo_coeff[k,:,:] = self.mo_coeff[k][:,:]
            mo_occ[k,:] = self.mo_occ[k][:]
        
        t = time.time()
        feval = 'surf_driver'
        drv = getattr(libaim, feval)
        with lib.with_omp_threads(self.nthreads):
            drv(ctypes.c_int(self.inuc), 
                self.xyzrho.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.npang), 
                ct_.ctypes.data_as(ctypes.c_void_p),
                st_.ctypes.data_as(ctypes.c_void_p),
                cp_.ctypes.data_as(ctypes.c_void_p),
                sp_.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.ntrial), 
                self.rpru.ctypes.data_as(ctypes.c_void_p), 
                ctypes.c_double(self.epsiscp), 
                ctypes.c_double(self.epsroot), 
                ctypes.c_double(self.rmaxsurf), 
                ctypes.c_int(backend),
                ctypes.c_double(self.epsilon), 
                ctypes.c_double(self.step), 
                ctypes.c_int(self.mstep),
                ctypes.c_int(self.natm), 
                self.coords.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.cart),
                ctypes.c_int(self.nmo),  
                ctypes.c_int(self.nprims), 
                self.atm.ctypes.data_as(ctypes.c_void_p), 
                ctypes.c_int(self.nbas), 
                self.bas.ctypes.data_as(ctypes.c_void_p), 
                self.env.ctypes.data_as(ctypes.c_void_p), 
                self.ao_loc.ctypes.data_as(ctypes.c_void_p),
                mo_coeff.ctypes.data_as(ctypes.c_void_p),
                mo_occ.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_double(self.occdrop), 
                #
                self.a.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(len(self.ls)), 
                self.ls.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.nkpts), 
                self.explk.ctypes.data_as(ctypes.c_void_p),
                self.rcut.ctypes.data_as(ctypes.c_void_p),
                self.non0tab.ctypes.data_as(ctypes.c_void_p),
                #
                self.nlimsurf.ctypes.data_as(ctypes.c_void_p),
                self.rsurf.ctypes.data_as(ctypes.c_void_p))
        for i in range(self.nkpts):
            print k,self.mo_occ[k][:]
        logger.info(self,'Time finding surface %.3f (sec)' % (time.time()-t))
        r = numpy.array([0.00000, 0.00000, 0.00000]) 
        r = numpy.reshape(r, (-1,3))
        ao = dft.numint.eval_ao_kpts(self.cell, r, kpts=self.kpts, deriv=1)
        print rhograd(self,[0,0,0]) 
             
        logger.info(self,'Surface of atom %d saved',self.inuc)
        logger.timer(self,'BaderSurf build', *t0)

        return self
Пример #58
0
    def build(self):

        t0 = (time.clock(), time.time())
        lib.logger.TIMER_LEVEL = 3

        mol = lib.chkfile.load_mol(self.chkfile)
        self.nelectron = mol.nelectron
        self.charge = mol.charge
        self.spin = mol.spin
        self.natm = mol.natm
        self.atm = numpy.asarray(mol._atm, dtype=numpy.int32, order='C')
        self.bas = numpy.asarray(mol._bas, dtype=numpy.int32, order='C')
        self.nbas = self.bas.shape[0]
        self.env = numpy.asarray(mol._env, dtype=numpy.double, order='C')
        self.ao_loc = mol.ao_loc_nr()
        self.shls_slice = (0, self.nbas)
        sh0, sh1 = self.shls_slice
        self.nao = self.ao_loc[sh1] - self.ao_loc[sh0]
        self.non0tab = numpy.ones((1, self.nbas), dtype=numpy.int8)
        self.coords = numpy.asarray([(numpy.asarray(atom[1])).tolist()
                                     for atom in mol._atom])
        self.charges = mol.atom_charges()
        #if (self.cas):
        #    self.mo_coeff = lib.chkfile.load(self.chkfile, 'mcscf/mo_coeff')
        #else:
        #    self.mo_coeff = lib.chkfile.load(self.chkfile, 'scf/mo_coeff')
        self.mo_coeff = lib.chkfile.load(self.chkfile, 'scf/mo_coeff')
        self.mo_occ = lib.chkfile.load(self.chkfile, 'scf/mo_occ')
        nprims, nmo = self.mo_coeff.shape
        self.nprims = nprims
        self.nmo = nmo
        self.cart = mol.cart
        if (not self.leb):
            self.npang = self.npphi * self.nptheta

        if (self.corr):
            self.rdm1 = lib.chkfile.load(self.chkfile, 'rdm/rdm1')
            nmo = self.rdm1.shape[0]
            natocc, natorb = numpy.linalg.eigh(self.rdm1)
            if (self.cas):
                self.mo_coeff = lib.chkfile.load(self.chkfile,
                                                 'mcscf/mo_coeff')
            natorb = numpy.dot(self.mo_coeff, natorb)
            self.mo_coeff = natorb
            self.mo_occ = natocc

        nocc = self.mo_occ[abs(self.mo_occ) > self.occdrop]
        nocc = len(nocc)
        self.nocc = nocc

        if (self.ntrial % 2 == 0): self.ntrial += 1
        geofac = numpy.power(((self.rmaxsurf - 0.1) / self.rprimer),
                             (1.0 / (self.ntrial - 1.0)))
        self.rpru = numpy.zeros((self.ntrial))
        for i in range(self.ntrial):
            self.rpru[i] = self.rprimer * numpy.power(geofac, (i + 1) - 1)
        self.rsurf = numpy.zeros((self.npang, self.ntrial), order='C')
        self.nlimsurf = numpy.zeros((self.npang), dtype=numpy.int32)

        if self.verbose >= logger.WARN:
            self.check_sanity()
        if self.verbose > logger.NOTE:
            self.dump_input()

        if (self.iqudt == 'legendre'):
            self.iqudt = 1

        if (self.leb):
            self.grids = grid.lebgrid(self.npang)
        else:
            self.grids = grid.anggrid(self.iqudt, self.nptheta, self.npphi)

        self.xyzrho = numpy.zeros((self.natm, 3))
        t = time.time()
        for i in range(self.natm):
            self.xyzrho[i], gradmod = gradrho(self, self.coords[i], self.step)
            if (gradmod > 1e-4):
                if (self.charges[i] > 2.0):
                    logger.info(self, 'Good rho position %.6f %.6f %.6f',
                                *self.xyzrho[i])
                else:
                    raise RuntimeError('Failed finding nucleus:',
                                       *self.xyzrho[i])
            else:
                logger.info(self, 'Check rho position %.6f %.6f %.6f',
                            *self.xyzrho[i])
                logger.info(self, 'Setting xyzrho for atom to imput coords')
                self.xyzrho[i] = self.coords[i]
        self.xnuc = numpy.asarray(self.xyzrho[self.inuc])
        logger.info(self,
                    'Time finding nucleus %.3f (sec)' % (time.time() - t))

        if (self.backend == 'rkck'):
            backend = 1
        elif (self.backend == 'rkdp'):
            backend = 2
        else:
            raise NotImplementedError(
                'Only rkck or rkdp ODE solver yet available')

        ct_ = numpy.asarray(self.grids[:, 0], order='C')
        st_ = numpy.asarray(self.grids[:, 1], order='C')
        cp_ = numpy.asarray(self.grids[:, 2], order='C')
        sp_ = numpy.asarray(self.grids[:, 3], order='C')

        t = time.time()
        feval = 'surf_driver'
        drv = getattr(libaim, feval)
        with lib.with_omp_threads(self.nthreads):
            drv(ctypes.c_int(self.inuc),
                self.xyzrho.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.npang), ct_.ctypes.data_as(ctypes.c_void_p),
                st_.ctypes.data_as(ctypes.c_void_p),
                cp_.ctypes.data_as(ctypes.c_void_p),
                sp_.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(self.ntrial),
                self.rpru.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_double(self.epsiscp), ctypes.c_double(self.epsroot),
                ctypes.c_double(self.rmaxsurf), ctypes.c_int(backend),
                ctypes.c_double(self.epsilon), ctypes.c_double(self.step),
                ctypes.c_int(self.mstep), ctypes.c_int(self.natm),
                self.coords.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.cart), ctypes.c_int(self.nmo),
                ctypes.c_int(self.nprims),
                self.atm.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_int(self.nbas),
                self.bas.ctypes.data_as(ctypes.c_void_p),
                self.env.ctypes.data_as(ctypes.c_void_p),
                self.ao_loc.ctypes.data_as(ctypes.c_void_p),
                self.mo_coeff.ctypes.data_as(ctypes.c_void_p),
                self.mo_occ.ctypes.data_as(ctypes.c_void_p),
                ctypes.c_double(self.occdrop),
                self.nlimsurf.ctypes.data_as(ctypes.c_void_p),
                self.rsurf.ctypes.data_as(ctypes.c_void_p))
        logger.info(self,
                    'Time finding surface %.3f (sec)' % (time.time() - t))

        self.rmin = 1000.0
        self.rmax = 0.0
        for i in range(self.npang):
            nsurf = int(self.nlimsurf[i])
            self.rmin = numpy.minimum(self.rmin, self.rsurf[i, 0])
            self.rmax = numpy.maximum(self.rmax, self.rsurf[i, nsurf - 1])
        logger.info(self, 'Rmin for surface %.6f', self.rmin)
        logger.info(self, 'Rmax for surface %.6f', self.rmax)

        logger.info(self, 'Write HDF5 surface file')
        atom_dic = {
            'inuc': self.inuc,
            'xnuc': self.xnuc,
            'xyzrho': self.xyzrho,
            'coords': self.grids,
            'npang': self.npang,
            'ntrial': self.ntrial,
            'rmin': self.rmin,
            'rmax': self.rmax,
            'nlimsurf': self.nlimsurf,
            'rsurf': self.rsurf
        }
        lib.chkfile.save(self.surfile, 'atom' + str(self.inuc), atom_dic)
        logger.info(self, 'Surface of atom %d saved', self.inuc)
        logger.timer(self, 'BaderSurf build', *t0)

        return self
Пример #59
0
    def get_jk(self,
               cell=None,
               dm=None,
               hermi=1,
               kpt=None,
               kpts_band=None,
               with_j=True,
               with_k=True,
               omega=None,
               **kwargs):
        r'''Get Coulomb (J) and exchange (K) following :func:`scf.hf.RHF.get_jk_`.
        for particular k-point (kpt).

        When kpts_band is given, the J, K matrices on kpts_band are evaluated.

            J_{pq} = \sum_{rs} (pq|rs) dm[s,r]
            K_{pq} = \sum_{rs} (pr|sq) dm[r,s]

        where r,s are orbitals on kpt. p and q are orbitals on kpts_band
        if kpts_band is given otherwise p and q are orbitals on kpt.
        '''
        if cell is None: cell = self.cell
        if dm is None: dm = self.make_rdm1()
        if kpt is None: kpt = self.kpt

        cpu0 = (time.clock(), time.time())
        dm = np.asarray(dm)
        nao = dm.shape[-1]

        if (not omega and kpts_band is None and
                # TODO: generate AO integrals with rsjk algorithm
                not self.rsjk and (self.exxdiv == 'ewald' or not self.exxdiv)
                and (self._eri is not None or cell.incore_anyway or
                     (not self.direct_scf and self._is_mem_enough()))):
            if self._eri is None:
                logger.debug(self, 'Building PBC AO integrals incore')
                self._eri = self.with_df.get_ao_eri(kpt, compact=True)
            vj, vk = mol_hf.dot_eri_dm(self._eri, dm, hermi, with_j, with_k)

            if with_k and self.exxdiv == 'ewald':
                from pyscf.pbc.df.df_jk import _ewald_exxdiv_for_G0
                # G=0 is not inculded in the ._eri integrals
                _ewald_exxdiv_for_G0(self.cell, kpt, dm.reshape(-1, nao, nao),
                                     vk.reshape(-1, nao, nao))
        elif self.rsjk:
            vj, vk = self.rsjk.get_jk(dm.reshape(-1, nao, nao),
                                      hermi,
                                      kpt,
                                      kpts_band,
                                      with_j,
                                      with_k,
                                      omega,
                                      exxdiv=self.exxdiv)
        else:
            vj, vk = self.with_df.get_jk(dm.reshape(-1, nao, nao),
                                         hermi,
                                         kpt,
                                         kpts_band,
                                         with_j,
                                         with_k,
                                         omega,
                                         exxdiv=self.exxdiv)

        if with_j:
            vj = _format_jks(vj, dm, kpts_band)
        if with_k:
            vk = _format_jks(vk, dm, kpts_band)
        logger.timer(self, 'vj and vk', *cpu0)
        return vj, vk
Пример #60
0
def get_veff(ks, mol=None, dm=None, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional

    .. note::
        This function will change the ks object.

    Args:
        ks : an instance of :class:`RKS`
            XC functional are controlled by ks.xc attribute.  Attribute
            ks.grids might be initialized.  The ._exc and ._ecoul attributes
            will be updated after return.  Attributes ._dm_last, ._vj_last and
            ._vk_last might be changed if direct SCF method is applied.
        dm : ndarray or list of ndarrays
            A density matrix or a list of density matrices

    Kwargs:
        dm_last : ndarray or a list of ndarrays or 0
            The density matrix baseline.  If not 0, this function computes the
            increment of HF potential w.r.t. the reference HF potential matrix.
        vhf_last : ndarray or a list of ndarrays or 0
            The reference HF potential matrix.  If vhf_last is not given,
            the function will not call direct_scf and attacalites ._dm_last,
            ._vj_last and ._vk_last will not be updated.
        hermi : int
            Whether J, K matrix is hermitian

            | 0 : no hermitian or symmetric
            | 1 : hermitian
            | 2 : anti-hermitian

    Returns:
        matrix Veff = J + Vxc.  Veff can be a list matrices, if the input
        dm is a list of density matrices.
    '''
    if mol is None: mol = ks.mol
    if dm is None: dm = ks.make_rdm1()
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.build(with_non0tab=True)
        small_rho_cutoff = ks.small_rho_cutoff
        t0 = logger.timer(ks, 'setting up grids', *t0)
    else:
        small_rho_cutoff = 0

    dm = numpy.asarray(dm)
    nao = dm.shape[-1]
    ground_state = (dm.ndim == 2)

    if hermi == 2:  # because rho = 0
        n, ks._exc, vx = 0, 0, 0
    else:
        n, ks._exc, vx = ks._numint.nr_vxc(mol, ks.grids, ks.xc, dm, hermi=hermi)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    hyb = ks._numint.hybrid_coeff(ks.xc, spin=mol.spin)
    if abs(hyb) < 1e-10:
        if (ks._eri is not None or not ks.direct_scf or
            not hasattr(ks, '_dm_last') or
            not isinstance(vhf_last, numpy.ndarray)):
            vhf = vj = ks.get_j(mol, dm, hermi)
        else:
            ddm = numpy.asarray(dm) - numpy.asarray(ks._dm_last)
            vj = ks.get_j(mol, ddm, hermi)
            vj += ks._vj_last
            ks._dm_last = dm
            vhf = ks._vj_last = vj
    else:
        raise NotImplementedError
        if (ks._eri is not None or not ks.direct_scf or
            not hasattr(ks, '_dm_last') or
            not isinstance(vhf_last, numpy.ndarray)):
            vj, vk = ks.get_jk(mol, dm, hermi)
        else:
            ddm = numpy.asarray(dm) - numpy.asarray(ks._dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi)
            vj += ks._vj_last
            vk += ks._vk_last
            ks._dm_last = dm
            ks._vj_last, ks._vk_last = vj, vk
        vhf = vj - vk * hyb

        if ground_state:
            ks._exc -= numpy.einsum('ij,ji', dm, vk) * .5 * hyb

    if ground_state:
        ks._ecoul = numpy.einsum('ij,ji', dm, vj) * .5

    if (small_rho_cutoff > 1e-20 and ground_state and
        abs(n-mol.nelectron) < 0.01*n):
        # Filter grids the first time setup grids
        idx = ks._numint.large_rho_indices(mol, dm, ks.grids, small_rho_cutoff)
        logger.debug(ks, 'Drop grids %d',
                     ks.grids.weights.size - numpy.count_nonzero(idx))
        ks.grids.coords  = numpy.asarray(ks.grids.coords [idx], order='C')
        ks.grids.weights = numpy.asarray(ks.grids.weights[idx], order='C')
        ks.grids.non0tab = ks.grids.make_mask(mol, ks.grids.coords)
    return vhf + vx