Exemplo n.º 1
0
def gen_g_hop_rhf(mf, mo_coeff, mo_occ, fock_ao=None):
    mol = mf.mol
    occidx = numpy.where(mo_occ==2)[0]
    viridx = numpy.where(mo_occ==0)[0]
    nocc = len(occidx)
    nvir = len(viridx)

    if fock_ao is None:
        dm1 = mf.make_rdm1(mo_coeff, mo_occ)
        fock_ao = mf.get_hcore() + mf.get_veff(mol, dm1)
    fock = reduce(numpy.dot, (mo_coeff.T, fock_ao, mo_coeff))

    g = fock[viridx[:,None],occidx] * 2

    foo = fock[occidx[:,None],occidx]
    fvv = fock[viridx[:,None],viridx]

    h_diag = (fvv.diagonal().reshape(-1,1)-foo.diagonal()) * 2

    if hasattr(mf, 'xc'):
        if APPROX_XC_HESSIAN:
            from pyscf.dft import vxc
            x_code = vxc.parse_xc_name(mf.xc)[0]
            hyb = vxc.hybrid_coeff(x_code, spin=(mol.spin>0)+1)
        else:
            save_for_dft = [None, None]  # (dm, veff)

    def h_op(x):
        x = x.reshape(nvir,nocc)
        x2 =-numpy.einsum('sq,ps->pq', foo, x) * 2
        x2+= numpy.einsum('pr,rq->pq', fvv, x) * 2

        d1 = reduce(numpy.dot, (mo_coeff[:,viridx], x, mo_coeff[:,occidx].T))
        if hasattr(mf, 'xc'):
            if APPROX_XC_HESSIAN:
                vj, vk = mf.get_jk(mol, d1+d1.T)
                if abs(hyb) < 1e-10:
                    dvhf = vj
                else:
                    dvhf = vj - vk * hyb * .5
            else:
                if save_for_dft[0] is None:
                    save_for_dft[0] = mf.make_rdm1(mo_coeff, mo_occ)
                    save_for_dft[1] = mf.get_veff(mol, save_for_dft[0])
                dm1 = save_for_dft[0] + d1 + d1.T
                vhf1 = mf.get_veff(mol, dm1, dm_last=save_for_dft[0],
                                   vhf_last=save_for_dft[1])
                dvhf = vhf1 - save_for_dft[1]
                save_for_dft[0] = dm1
                save_for_dft[1] = vhf1
        else:
            dvhf = mf.get_veff(mol, d1+d1.T)
        x2 += reduce(numpy.dot, (mo_coeff[:,viridx].T, dvhf,
                                 mo_coeff[:,occidx])) * 4
        return x2.reshape(-1)

    return g.reshape(-1), h_op, h_diag.reshape(-1)
Exemplo n.º 2
0
Arquivo: uks.py Projeto: raybrad/pyscf
def get_veff_(ks, mol, dm, 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 isinstance(dm, numpy.ndarray) and dm.ndim == 2:
        dm = numpy.array((dm*.5,dm*.5))
    nset = len(dm) // 2
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.setup_grids_()
        t0 = logger.timer(ks, 'seting up grids', *t0)

    x_code, c_code = vxc.parse_xc_name(ks.xc)
    n, ks._exc, vx = \
            ks._numint.nr_uks(mol, ks.grids, x_code, c_code,
                                dm, verbose=ks.verbose)
    logger.debug(ks, 'nelec by numeric integration = %s', n)
    t0 = logger.timer(ks, 'vxc', *t0)

    hyb = vxc.hybrid_coeff(x_code, spin=(mol.spin>0)+1)

    if abs(hyb) < 1e-10:
        vj = ks.get_j(mol, dm, hermi)
    elif (ks._eri is not None or ks._is_mem_enough() or not ks.direct_scf):
        vj, vk = ks.get_jk(mol, dm, hermi)
    else:
        if (ks.direct_scf and isinstance(vhf_last, numpy.ndarray) and
            hasattr(ks, '_dm_last')):
            ddm = numpy.asarray(dm) - numpy.asarray(ks._dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi=hermi)
            vj += ks._vj_last
            vk += ks._vk_last
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
        ks._dm_last = dm
        ks._vj_last, ks._vk_last = vj, vk

    if abs(hyb) > 1e-10:
        if nset == 1:
            ks._exc -=(numpy.einsum('ij,ji', dm[0], vk[0])
                        +numpy.einsum('ij,ji', dm[1], vk[1])) * .5 * hyb
        vhf = pyscf.scf.uhf._makevhf(vj, vk*hyb, nset)
    else:
        if nset == 1:
            vhf = vj[0] + vj[1]
        else:
            vhf = vj[:nset] + vj[nset:]
        vhf = numpy.array((vhf,vhf))
    if nset == 1:
        ks._ecoul = numpy.einsum('ij,ji', dm[0]+dm[1], vj[0]+vj[1]) * .5
    return vhf + vx
Exemplo n.º 3
0
def get_veff_(ks, mol, dm, dm_last=0, vhf_last=0, hermi=1):
    '''Coulomb + XC functional'''
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.setup_grids_()
        t0 = logger.timer(ks, 'seting up grids', *t0)

    x_code, c_code = vxc.parse_xc_name(ks.xc)
    #n, ks._exc, vx = vxc.nr_vxc(mol, ks.grids, x_code, c_code,
    #                              dm, spin=1, relativity=0)
    if ks._numint is None:
        n, ks._exc, vx = numint.nr_vxc(mol, ks.grids, x_code, c_code,
                                       dm, spin=mol.spin, relativity=0)
    else:
        n, ks._exc, vx = \
                ks._numint.nr_vxc(mol, ks.grids, x_code, c_code,
                                  dm, spin=mol.spin, relativity=0)
    logger.debug(ks, 'nelec by numeric integration = %s', n)
    t0 = logger.timer(ks, 'vxc', *t0)

    hyb = vxc.hybrid_coeff(x_code, spin=1)

    if abs(hyb) < 1e-10:
        vj = ks.get_j(mol, dm, hermi)
    elif (ks._eri is not None or ks._is_mem_enough() or
        not ks.direct_scf):
        vj, vk = ks.get_jk(mol, dm, hermi)
    else:
        if isinstance(vhf_last, numpy.ndarray):
            ddm = numpy.asarray(dm) - numpy.asarray(dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi=hermi)
            vj += ks._vj_last
            vk += ks._vk_last
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
        ks._vj_last, ks._vk_last = vj, vk

    if abs(hyb) > 1e-10:
        if isinstance(dm, numpy.ndarray) and dm.ndim == 2:
            ks._exc -= numpy.einsum('ij,ji', dm, vk) * .5 * hyb*.5
        vhf = vj - vk * (hyb * .5)
    else:
        vhf = vj

    if isinstance(dm, numpy.ndarray) and dm.ndim == 2:
        ks._ecoul = numpy.einsum('ij,ji', dm, vj) * .5
    return vhf + vx
Exemplo n.º 4
0
def gen_g_hop_rohf(mf, mo_coeff, mo_occ, fock_ao=None):
    mol = mf.mol
    occidxa = numpy.where(mo_occ>0)[0]
    occidxb = numpy.where(mo_occ==2)[0]
    viridxa = numpy.where(mo_occ==0)[0]
    viridxb = numpy.where(mo_occ<2)[0]
    mask = pyscf.scf.hf.uniq_var_indices(mo_occ)

    if fock_ao is None:
        dm1 = mf.make_rdm1(mo_coeff, mo_occ)
        fock_ao = mf.get_hcore() + mf.get_veff(mol, dm1)
    focka = reduce(numpy.dot, (mo_coeff.T, fock_ao[0], mo_coeff))
    fockb = reduce(numpy.dot, (mo_coeff.T, fock_ao[1], mo_coeff))

    g = numpy.zeros_like(focka)
    g[viridxa[:,None],occidxa]  = focka[viridxa[:,None],occidxa]
    g[viridxb[:,None],occidxb] += fockb[viridxb[:,None],occidxb]
    g = g[mask]

    h_diag = numpy.zeros_like(focka)
    h_diag[viridxa[:,None],occidxa] -= focka[occidxa,occidxa]
    h_diag[viridxa[:,None],occidxa] += focka[viridxa,viridxa].reshape(-1,1)
    h_diag[viridxb[:,None],occidxb] -= fockb[occidxb,occidxb]
    h_diag[viridxb[:,None],occidxb] += fockb[viridxb,viridxb].reshape(-1,1)
    h_diag = h_diag[mask]

    if hasattr(mf, 'xc'):
        if APPROX_XC_HESSIAN:
            from pyscf.dft import vxc
            x_code = vxc.parse_xc_name(mf.xc)[0]
            hyb = vxc.hybrid_coeff(x_code, spin=(mol.spin>0)+1)
        else:
            save_for_dft = [None, None]  # (dm, veff)
    def h_op(x):
        x1 = numpy.zeros_like(focka)
        x1[mask] = x
        x1 = x1 - x1.T
        x2 = numpy.zeros_like(focka)

        #: x2[nb:,:na] = numpy.einsum('sp,qs->pq', focka[:na,nb:], x1[:na,:na])
        #: x2[nb:,:na] += numpy.einsum('rq,rp->pq', focka[:na,:na], x1[:na,nb:])
        #: x2[na:,:na] -= numpy.einsum('sp,rp->rs', focka[:na,:na], x1[na:,:na])
        #: x2[na:,:na] -= numpy.einsum('ps,qs->pq', focka[na:], x1[:na]) * 2
        #: x2[nb:na,:nb] += numpy.einsum('qr,pr->pq', focka[:nb], x1[nb:na])
        #: x2[nb:na,:nb] -= numpy.einsum('rq,sq->rs', focka[nb:na], x1[:nb])
        #: x2[nb:,:na] += numpy.einsum('sp,qs->pq', fockb[:nb,nb:], x1[:na,:nb])
        #: x2[nb:,:na] += numpy.einsum('rq,rp->pq', fockb[:nb,:na], x1[:nb,nb:])
        #: x2[nb:,:nb] -= numpy.einsum('sp,rp->rs', fockb[:nb], x1[nb:])
        #: x2[nb:,:nb] -= numpy.einsum('rq,sq->rs', fockb[nb:], x1[:nb]) * 2
        x2[viridxb[:,None],occidxa] = \
                (numpy.einsum('sp,qs->pq', focka[occidxa[:,None],viridxb], x1[occidxa[:,None],occidxa])
                +numpy.einsum('rq,rp->pq', focka[occidxa[:,None],occidxa], x1[occidxa[:,None],viridxb]))
        x2[viridxa[:,None],occidxa] -= \
                (numpy.einsum('sp,rp->rs', focka[occidxa[:,None],occidxa], x1[viridxa[:,None],occidxa])
                +numpy.einsum('ps,qs->pq', focka[viridxa], x1[occidxa]) * 2)
        x2[occidxa[:,None],occidxb] += \
                (numpy.einsum('qr,pr->pq', focka[occidxb], x1[occidxa])
                -numpy.einsum('rq,sq->rs', focka[occidxa], x1[occidxb]))

        x2[viridxb[:,None],occidxa] += \
                (numpy.einsum('sp,qs->pq', fockb[occidxb[:,None],viridxb], x1[occidxa[:,None],occidxb])
                +numpy.einsum('rq,rp->pq', fockb[occidxb[:,None],occidxa], x1[occidxb[:,None],viridxb]))
        x2[viridxb[:,None],occidxb] -= \
                (numpy.einsum('sp,rp->rs', fockb[occidxb], x1[viridxb])
                +numpy.einsum('rq,sq->rs', fockb[viridxb], x1[occidxb]) * 2)
        x2 *= .5

        d1a = reduce(numpy.dot, (mo_coeff[:,viridxa], x1[viridxa[:,None],occidxa], mo_coeff[:,occidxa].T))
        d1b = reduce(numpy.dot, (mo_coeff[:,viridxb], x1[viridxb[:,None],occidxb], mo_coeff[:,occidxb].T))
        if hasattr(mf, 'xc'):
            if APPROX_XC_HESSIAN:
                vj, vk = mf.get_jk(mol, numpy.array((d1a+d1a.T,d1b+d1b.T)))
                if abs(hyb) < 1e-10:
                    dvhf = vj[0] + vj[1]
                else:
                    dvhf = (vj[0] + vj[1]) - vk * hyb
            else:
                from pyscf.dft import uks
                if save_for_dft[0] is None:
                    save_for_dft[0] = mf.make_rdm1(mo_coeff, mo_occ)
                    save_for_dft[1] = mf.get_veff(mol, save_for_dft[0])
                dm1 = numpy.array((save_for_dft[0][0]+d1a+d1a.T,
                                   save_for_dft[0][1]+d1b+d1b.T))
                vhf1 = uks.get_veff_(mf, mol, dm1, dm_last=save_for_dft[0],
                                     vhf_last=save_for_dft[1])
                dvhf = (vhf1[0]-save_for_dft[1][0], vhf1[1]-save_for_dft[1][1])
                save_for_dft[0] = dm1
                save_for_dft[1] = vhf1
        else:
            dvhf = mf.get_veff(mol, numpy.array((d1a+d1a.T,d1b+d1b.T)))
        x2[viridxa[:,None],occidxa] += reduce(numpy.dot, (mo_coeff[:,viridxa].T, dvhf[0], mo_coeff[:,occidxa]))
        x2[viridxb[:,None],occidxb] += reduce(numpy.dot, (mo_coeff[:,viridxb].T, dvhf[1], mo_coeff[:,occidxb]))
        return x2[mask]

    return g, h_op, h_diag
Exemplo n.º 5
0
def gen_g_hop_uhf(mf, mo_coeff, mo_occ, fock_ao=None):
    mol = mf.mol
    occidxa = numpy.where(mo_occ[0]>0)[0]
    occidxb = numpy.where(mo_occ[1]>0)[0]
    viridxa = numpy.where(mo_occ[0]==0)[0]
    viridxb = numpy.where(mo_occ[1]==0)[0]
    nocca = len(occidxa)
    noccb = len(occidxb)
    nvira = len(viridxa)
    nvirb = len(viridxb)

    if fock_ao is None:
        dm1 = mf.make_rdm1(mo_coeff, mo_occ)
        fock_ao = mf.get_hcore() + mf.get_veff(mol, dm1)
    focka = reduce(numpy.dot, (mo_coeff[0].T, fock_ao[0], mo_coeff[0]))
    fockb = reduce(numpy.dot, (mo_coeff[1].T, fock_ao[1], mo_coeff[1]))

    g = numpy.hstack((focka[viridxa[:,None],occidxa].reshape(-1),
                      fockb[viridxb[:,None],occidxb].reshape(-1)))

    h_diaga =(focka[viridxa,viridxa].reshape(-1,1) - focka[occidxa,occidxa])
    h_diagb =(fockb[viridxb,viridxb].reshape(-1,1) - fockb[occidxb,occidxb])
    h_diag = numpy.hstack((h_diaga.reshape(-1), h_diagb.reshape(-1)))

    if hasattr(mf, 'xc'):
        if APPROX_XC_HESSIAN:
            from pyscf.dft import vxc
            x_code = vxc.parse_xc_name(mf.xc)[0]
            hyb = vxc.hybrid_coeff(x_code, spin=(mol.spin>0)+1)
        else:
            save_for_dft = [None, None]  # (dm, veff)
    def h_op(x):
        x1a = x[:nvira*nocca].reshape(nvira,nocca)
        x1b = x[nvira*nocca:].reshape(nvirb,noccb)
        x2a = numpy.zeros((nvira,nocca))
        x2b = numpy.zeros((nvirb,noccb))
        x2a -= numpy.einsum('sq,ps->pq', focka[occidxa[:,None],occidxa], x1a)
        x2a += numpy.einsum('rp,rq->pq', focka[viridxa[:,None],viridxa], x1a)
        x2b -= numpy.einsum('sq,ps->pq', fockb[occidxb[:,None],occidxb], x1b)
        x2b += numpy.einsum('rp,rq->pq', fockb[viridxb[:,None],viridxb], x1b)

        d1a = reduce(numpy.dot, (mo_coeff[0][:,viridxa], x1a,
                                 mo_coeff[0][:,occidxa].T))
        d1b = reduce(numpy.dot, (mo_coeff[1][:,viridxb], x1b,
                                 mo_coeff[1][:,occidxb].T))
        if hasattr(mf, 'xc'):
            if APPROX_XC_HESSIAN:
                vj, vk = mf.get_jk(mol, numpy.array((d1a+d1a.T,d1b+d1b.T)))
                if abs(hyb) < 1e-10:
                    dvhf = vj[0] + vj[1]
                    dvhf = (dvhf, dvhf)
                else:
                    dvhf = (vj[0] + vj[1]) - vk * hyb
            else:
                if save_for_dft[0] is None:
                    save_for_dft[0] = mf.make_rdm1(mo_coeff, mo_occ)
                    save_for_dft[1] = mf.get_veff(mol, save_for_dft[0])
                dm1 = numpy.array((save_for_dft[0][0]+d1a+d1a.T,
                                   save_for_dft[0][1]+d1b+d1b.T))
                vhf1 = mf.get_veff(mol, dm1, dm_last=save_for_dft[0],
                                   vhf_last=save_for_dft[1])
                dvhf = (vhf1[0]-save_for_dft[1][0], vhf1[1]-save_for_dft[1][1])
                save_for_dft[0] = dm1
                save_for_dft[1] = vhf1
        else:
            dvhf = mf.get_veff(mol, numpy.array((d1a+d1a.T,d1b+d1b.T)))
        x2a += reduce(numpy.dot, (mo_coeff[0][:,viridxa].T, dvhf[0],
                                  mo_coeff[0][:,occidxa]))
        x2b += reduce(numpy.dot, (mo_coeff[1][:,viridxb].T, dvhf[1],
                                  mo_coeff[1][:,occidxb]))
        return numpy.hstack((x2a.ravel(), x2b.ravel()))

    return g, h_op, h_diag
Exemplo n.º 6
0
Arquivo: rks.py Projeto: matk86/pyscf
def get_veff_(ks, mol, dm, 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.
    '''
    t0 = (time.clock(), time.time())
    if ks.grids.coords is None:
        ks.grids.setup_grids_()
        t0 = logger.timer(ks, 'seting up grids', *t0)

    x_code, c_code = vxc.parse_xc_name(ks.xc)
    hyb = vxc.hybrid_coeff(x_code, spin=(mol.spin>0)+1)

    if hermi == 2:  # because rho = 0
        n, ks._exc, vx = 0, 0, 0
    else:
        if ks._numint is None:
            n, ks._exc, vx = numint.nr_rks_vxc(mol, ks.grids, x_code, c_code,
                                               dm, hermi=hermi)
        else:
            n, ks._exc, vx = ks._numint.nr_rks(mol, ks.grids, x_code, c_code,
                                               dm, hermi=hermi)
        logger.debug(ks, 'nelec by numeric integration = %s', n)
        t0 = logger.timer(ks, 'vxc', *t0)

    if abs(hyb) < 1e-10:
        vj = ks.get_j(mol, dm, hermi)
    elif (ks._eri is not None or ks._is_mem_enough() or not ks.direct_scf):
        vj, vk = ks.get_jk(mol, dm, hermi)
    else:
        if (ks.direct_scf and isinstance(vhf_last, numpy.ndarray) and
            hasattr(ks, '_dm_last')):
            ddm = numpy.asarray(dm) - numpy.asarray(ks._dm_last)
            vj, vk = ks.get_jk(mol, ddm, hermi=hermi)
            vj += ks._vj_last
            vk += ks._vk_last
        else:
            vj, vk = ks.get_jk(mol, dm, hermi)
        ks._dm_last = dm
        ks._vj_last, ks._vk_last = vj, vk

    if abs(hyb) > 1e-10:
        if isinstance(dm, numpy.ndarray) and dm.ndim == 2:
            ks._exc -= numpy.einsum('ij,ji', dm, vk) * .5 * hyb*.5
        vhf = vj - vk * (hyb * .5)
    else:
        vhf = vj

    if isinstance(dm, numpy.ndarray) and dm.ndim == 2:
        ks._ecoul = numpy.einsum('ij,ji', dm, vj) * .5
    return vhf + vx