Exemple #1
0
def _get_vxc(ni, mol, grids, x_id, c_id, dms, relativity=0, hermi=1,
             max_memory=2000, verbose=None):
    natocc = []
    natorb = []
    if isinstance(dms, numpy.ndarray) and dms.ndim == 2:
        e, c = scipy.linalg.eigh(dms)
        natocc.append(e)
        natorb.append(c)
        nao = dms.shape[0]
    else:
        for dm in dms:
            e, c = scipy.linalg.eigh(dm)
            natocc.append(e)
            natorb.append(c)
        nao = dms[0].shape[0]

    xctype = numint._xc_type(x_id, c_id)
    ngrids = len(grids.weights)
    BLKSIZE = numint.BLKSIZE
    blksize = min(int(max_memory/6*1e6/8/nao/BLKSIZE)*BLKSIZE, ngrids)

    nset = len(natocc)
    nelec = numpy.zeros(nset)
    excsum = numpy.zeros(nset)
    vmat = numpy.zeros((nset,3,nao,nao))
    if xctype == 'LDA':
        buf = numpy.empty((4,blksize,nao))
        for ip0, ip1 in numint.prange(0, ngrids, blksize):
            coords = grids.coords[ip0:ip1]
            weight = grids.weights[ip0:ip1]
            non0tab = ni.non0tab[ip0//BLKSIZE:]
            ao = ni.eval_ao(mol, coords, deriv=1, non0tab=non0tab, out=buf)
            for idm in range(nset):
                rho = ni.eval_rho2(mol, ao[0], natorb[idm], natocc[idm], non0tab, xctype)
                exc, vxc = ni.eval_xc(x_id, c_id, rho, 0, relativity, 1, verbose)[:2]
                vrho = vxc[0]
                den = rho * weight
                nelec[idm] += den.sum()
                excsum[idm] += (den * exc).sum()
                aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
                vmat[idm,0] += numint._dot_ao_ao(mol, ao[1], aow, nao, ip1-ip0, non0tab)
                vmat[idm,1] += numint._dot_ao_ao(mol, ao[2], aow, nao, ip1-ip0, non0tab)
                vmat[idm,2] += numint._dot_ao_ao(mol, ao[3], aow, nao, ip1-ip0, non0tab)
                rho = exc = vxc = vrho = aow = None
    elif xctype == 'GGA':
        buf = numpy.empty((10,blksize,nao))
        XX, XY, XZ = 4, 5, 6
        YX, YY, YZ = 5, 7, 8
        ZX, ZY, ZZ = 6, 8, 9
        for ip0, ip1 in numint.prange(0, ngrids, blksize):
            coords = grids.coords[ip0:ip1]
            weight = grids.weights[ip0:ip1]
            non0tab = ni.non0tab[ip0//BLKSIZE:]
            ao = ni.eval_ao(mol, coords, deriv=2, non0tab=non0tab, out=buf)
            for idm in range(nset):
                rho = ni.eval_rho2(mol, ao, natorb[idm], natocc[idm], non0tab, xctype)
                exc, vxc = ni.eval_xc(x_id, c_id, rho, 0, relativity, 1, verbose)[:2]
                vrho, vsigma = vxc[:2]
                den = rho[0] * weight
                nelec[idm] += den.sum()
                excsum[idm] += (den * exc).sum()
                wv = numpy.empty_like(rho)
                # *.5 because vmat + vmat.T implicitly
                wv[0]  = weight * vrho * .5
                wv[1:] = rho[1:] * (weight * vsigma * 2)

                aow = numpy.einsum('npi,np->pi', ao[:4], wv)
                vmat[idm,0] += numint._dot_ao_ao(mol, ao[1], aow, nao, ip1-ip0, non0tab)
                vmat[idm,1] += numint._dot_ao_ao(mol, ao[2], aow, nao, ip1-ip0, non0tab)
                vmat[idm,2] += numint._dot_ao_ao(mol, ao[3], aow, nao, ip1-ip0, non0tab)

                aow = numpy.einsum('pi,p->pi', ao[1] , wv[0])
                aow+= numpy.einsum('pi,p->pi', ao[XX], wv[1])
                aow+= numpy.einsum('pi,p->pi', ao[XY], wv[2])
                aow+= numpy.einsum('pi,p->pi', ao[XZ], wv[3])
                vmat[idm,0] += numint._dot_ao_ao(mol, aow, ao[0], nao, ip1-ip0, non0tab)
                aow = numpy.einsum('pi,p->pi', ao[2] , wv[0])
                aow+= numpy.einsum('pi,p->pi', ao[YX], wv[1])
                aow+= numpy.einsum('pi,p->pi', ao[YY], wv[2])
                aow+= numpy.einsum('pi,p->pi', ao[YZ], wv[3])
                vmat[idm,1] += numint._dot_ao_ao(mol, aow, ao[0], nao, ip1-ip0, non0tab)
                aow = numpy.einsum('pi,p->pi', ao[3] , wv[0])
                aow+= numpy.einsum('pi,p->pi', ao[ZX], wv[1])
                aow+= numpy.einsum('pi,p->pi', ao[ZY], wv[2])
                aow+= numpy.einsum('pi,p->pi', ao[ZZ], wv[3])
                vmat[idm,2] += numint._dot_ao_ao(mol, aow, ao[0], nao, ip1-ip0, non0tab)
                rho = exc = vxc = vrho = vsigma = wv = aow = None
    else:
        raise NotImplementedError('meta-GGA')

    if nset == 1:
        vmat = vmat.reshape(3,nao,nao)
    return vmat
Exemple #2
0
def _contract_xc_kernel(td, x_id, c_id, dmvo, singlet=True, max_memory=2000):
    mf = td._scf
    mol = td.mol
    ni = mf._numint
    grids = mf.grids

    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    ndm = len(dmvo)

    dmvo = numpy.asarray(dmvo)
    dmvo = (dmvo + dmvo.transpose(0,2,1)) * .5

    xctype = numint._xc_type(x_id, c_id)
    ngrids = len(grids.weights)
    BLKSIZE = numint.BLKSIZE
    blksize = min(int(max_memory*1e6/8/nao/BLKSIZE)*BLKSIZE, ngrids)

    v1ao = numpy.zeros((ndm,nao,nao))
    if xctype == 'LDA':
        buf = numpy.empty((blksize,nao))
        if singlet:
            for ip0, ip1 in numint.prange(0, ngrids, blksize):
                coords = grids.coords[ip0:ip1]
                weight = grids.weights[ip0:ip1]
                non0tab = ni.non0tab[ip0//BLKSIZE:]
                ao = ni.eval_ao(mol, coords, deriv=0, non0tab=non0tab, out=buf)
                rho = ni.eval_rho2(mol, ao, mo_coeff, mo_occ, non0tab, 'LDA')
                rho *= .5  # alpha density
                fxc = ni.eval_xc(x_id, c_id, (rho,rho), 1, deriv=2)[2]
                u_u, u_d, d_d = v2rho2 = fxc[0].T
                frho = u_u + u_d
                for i, dm in enumerate(dmvo):
                    rho1 = ni.eval_rho(mol, ao, dm, non0tab, xctype)
                    aow = numpy.einsum('pi,p->pi', ao, weight*frho*rho1)
                    v1ao[i] += numint._dot_ao_ao(mol, aow, ao, nao, ip1-ip0, non0tab)
                    rho1 = aow = None

            for i in range(ndm):
                v1ao[i] = (v1ao[i] + v1ao[i].T) * .5
        else:
            # because frho = u_u - u_d = 0
            pass

    elif xctype == 'GGA':
        buf = numpy.empty((4,blksize,nao))
        for ip0, ip1 in numint.prange(0, ngrids, blksize):
            coords = grids.coords[ip0:ip1]
            weight = grids.weights[ip0:ip1]
            non0tab = ni.non0tab[ip0//BLKSIZE:]
            ao = ni.eval_ao(mol, coords, deriv=1, non0tab=non0tab, out=buf)
            rho = ni.eval_rho2(mol, ao, mo_coeff, mo_occ, non0tab, 'GGA')
            rho *= .5  # alpha density
            vxc, fxc = ni.eval_xc(x_id, c_id, (rho,rho), 1, deriv=2)[1:3]

            vsigma = vxc[1].T
            u_u, u_d, d_d = fxc[0].T  # v2rho2
            u_uu, u_ud, u_dd, d_uu, d_ud, d_dd = fxc[1].T  # v2rhosigma
            uu_uu, uu_ud, uu_dd, ud_ud, ud_dd, dd_dd = fxc[2].T  # v2sigma2
            if singlet:
                fgamma = 2*vsigma[0] + vsigma[1]
                frho = u_u + u_d
                fgg = uu_uu + .5*ud_ud + 2*uu_ud + uu_dd
                frhogamma = u_uu + u_dd + u_ud
            else:
                fgamma = 2*vsigma[0] - vsigma[1]
                frho = u_u - u_d
                fgg = uu_uu - uu_dd
                frhogamma = u_uu - u_dd

            for i, dm in enumerate(dmvo):
                # rho1[0 ] = |b><j| z_{bj}
                # rho1[1:] = \nabla(|b><j|) z_{bj}
                rho1 = ni.eval_rho(mol, ao, dm, non0tab, 'GGA')
                # sigma1 = \nabla(\rho_\alpha+\rho_\beta) dot \nabla(|b><j|) z_{bj}
                # *2 for alpha + beta
                sigma1 = numpy.einsum('xi,xi->i', rho[1:], rho1[1:]) * 2

                wv  = frho * rho1[0]
                wv += frhogamma * sigma1
                wv *= weight
                if c_id == 131 or x_id in (402, 404, 411, 416, 419):
                    # second derivative of LYP functional in libxc library diverge
                    wv[rho[0] < 4.57e-11] = 0
                aow = numpy.einsum('pi,p->pi', ao[0], wv)
                v1ao[i] += numint._dot_ao_ao(mol, aow, ao[0], nao, ip1-ip0, non0tab)

                for k in range(3):
                    wv  = fgg * sigma1 * rho[1+k]
                    wv += frhogamma * rho1[0] * rho[1+k]
                    wv *= 2 # *2 because \nabla\rho = \nabla(\rho_\alpha+\rho_\beta)
                    wv += fgamma * rho1[1+k]
                    wv *= weight
                    if c_id == 131 or x_id in (402, 404, 411, 416, 419):
                        # second derivative of LYP functional in libxc library diverge
                        wv[rho[0] < 4.57e-11] = 0
                    aow = numpy.einsum('ip,i->ip', ao[0], wv)
                    #v1ao += numint._dot_ao_ao(mol, aow, ao[1+k], nao, ip1-ip0, non0tab)
                    #v1ao += numint._dot_ao_ao(mol, ao[1+k], aow, nao, ip1-ip0, non0tab)
                    # v1ao+v1ao.T at the end
                    v1ao[i] += 2*numint._dot_ao_ao(mol, aow, ao[1+k], nao, ip1-ip0, non0tab)
                aow = None
        for i in range(ndm):
            v1ao[i] = (v1ao[i] + v1ao[i].T) * .5
    else:
        raise NotImplementedError('meta-GGA')

    return v1ao
Exemple #3
0
def _contract_xc_kernel(td_grad, x_id, c_id, xai, oovv=None, with_vxc=True,
                        with_kxc=True, singlet=True, max_memory=4000):
    mol = td_grad.mol
    mf = td_grad._scf
    ni = mf._numint
    grids = mf.grids

    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    nocc = (mo_occ>0).sum()
    orbv = mo_coeff[:,nocc:]
    orbo = mo_coeff[:,:nocc]

    # dmvo ~ reduce(numpy.dot, (orbv, Xai, orbo.T))
    dmvo = (xai + xai.T) * .5 # because K_{ai,bj} == K_{ai,bj}

    f1vo = numpy.zeros((4,nao,nao))
    deriv = 2
    if oovv is not None:
        f1oo = numpy.zeros((4,nao,nao))
    else:
        f1oo = None
    if with_vxc:
        v1ao = numpy.zeros((4,nao,nao))
    else:
        v1ao = None
    if with_kxc:
        k1ao = numpy.zeros((4,nao,nao))
        deriv = 3
    else:
        k1ao = None

    xctype = numint._xc_type(x_id, c_id)
    ngrids = len(grids.weights)
    BLKSIZE = numint.BLKSIZE
    max_memory = max_memory - 4*nao**2*8/1e6
    blksize = min(int(max_memory/6*1e6/8/nao/BLKSIZE)*BLKSIZE, ngrids)

    if xctype == 'LDA':
        buf = numpy.empty((4,blksize,nao))
        for ip0, ip1 in numint.prange(0, ngrids, blksize):
            coords = grids.coords[ip0:ip1]
            weight = grids.weights[ip0:ip1]
            non0tab = ni.non0tab[ip0//BLKSIZE:]
            ao = ni.eval_ao(mol, coords, deriv=1, non0tab=non0tab, out=buf)
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, non0tab, 'LDA')
            vxc, fxc, kxc = ni.eval_xc(x_id, c_id, rho, 0, deriv=deriv)[1:]

            wfxc = fxc[0] * weight * 2  # *2 for alpha+beta
            if singlet:
                rho1 = ni.eval_rho(mol, ao[0], dmvo, non0tab, 'LDA')
                aow = numpy.einsum('pi,p->pi', ao[0], wfxc*rho1)
                for k in range(4):
                    f1vo[k] += numint._dot_ao_ao(mol, ao[k], aow, nao, ip1-ip0, non0tab)
            if oovv is not None:
                rho2 = ni.eval_rho(mol, ao[0], oovv, non0tab, 'LDA')
                aow = numpy.einsum('pi,p->pi', ao[0], wfxc*rho2)
                for k in range(4):
                    f1oo[k] += numint._dot_ao_ao(mol, ao[k], aow, nao, ip1-ip0, non0tab)
            if with_vxc:
                aow = numpy.einsum('pi,p->pi', ao[0], vxc[0]*weight)
                for k in range(4):
                    v1ao[k] += numint._dot_ao_ao(mol, ao[k], aow, nao, ip1-ip0, non0tab)
            if singlet and with_kxc:
                aow = numpy.einsum('pi,p->pi', ao[0], kxc[0]*weight*rho1**2)
                for k in range(4):
                    k1ao[k] += numint._dot_ao_ao(mol, ao[k], aow, nao, ip1-ip0, non0tab)
            vxc = fxc = kxc = aow = rho = rho1 = rho2 = None
        if singlet and with_kxc:
            k1ao *= 4

    elif xctype == 'GGA':
        raise NotImplementedError('GGA')
    else:
        raise NotImplementedError('meta-GGA')

    f1vo[1:] *= -1
    if f1oo is not None: f1oo[1:] *= -1
    if v1ao is not None: v1ao[1:] *= -1
    if k1ao is not None: k1ao[1:] *= -1
    return f1vo, f1oo, v1ao, k1ao
Exemple #4
0
def _get_vxc_giao(ni, mol, grids, x_id, c_id, dm,
                  max_memory=2000, verbose=None):
    natocc, natorb = scipy.linalg.eigh(dm)
    nao = dm.shape[0]

    xctype = numint._xc_type(x_id, c_id)
    ngrids = len(grids.weights)
    BLKSIZE = numint.BLKSIZE
    blksize = min(int(max_memory/6*1e6/12/nao/BLKSIZE)*BLKSIZE, ngrids)

    vmat = numpy.zeros((3,nao,nao))
    if xctype == 'LDA':
        buf = numpy.empty((4,blksize,nao))
        for ip0, ip1 in numint.prange(0, ngrids, blksize):
            coords = grids.coords[ip0:ip1]
            weight = grids.weights[ip0:ip1]
            non0tab = ni.non0tab[ip0//BLKSIZE:]
            ao = ni.eval_ao(mol, coords, deriv=0, non0tab=non0tab, out=buf)
            rho = ni.eval_rho2(mol, ao, natorb, natocc, non0tab, xctype)
            vxc = ni.eval_xc(x_id, c_id, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            aow = numpy.einsum('pi,p->pi', ao, weight*vrho)
            giao = mol.eval_gto('GTOval_ig_sph', coords, comp=3,
                                non0tab=non0tab, out=buf[1:])
            vmat[0] += numint._dot_ao_ao(mol, aow, giao[0], nao, ip1-ip0, non0tab)
            vmat[1] += numint._dot_ao_ao(mol, aow, giao[1], nao, ip1-ip0, non0tab)
            vmat[2] += numint._dot_ao_ao(mol, aow, giao[2], nao, ip1-ip0, non0tab)
            rho = vxc = vrho = aow = giao = None
    elif xctype == 'GGA':
        buf = numpy.empty((10,blksize,nao))
        XX, XY, XZ = 0, 1, 2
        YX, YY, YZ = 3, 4, 5
        ZX, ZY, ZZ = 6, 7, 8
        for ip0, ip1 in numint.prange(0, ngrids, blksize):
            coords = grids.coords[ip0:ip1]
            weight = grids.weights[ip0:ip1]
            non0tab = ni.non0tab[ip0//BLKSIZE:]
            ao = ni.eval_ao(mol, coords, deriv=1, non0tab=non0tab, out=buf)
            rho = ni.eval_rho2(mol, ao, natorb, natocc, non0tab, xctype)
            vxc = ni.eval_xc(x_id, c_id, rho, 0, deriv=1)[1]
            vrho, vsigma = vxc[:2]
            wv = numpy.empty_like(rho)
            wv[0]  = weight * vrho
            wv[1:] = rho[1:] * (weight * vsigma * 2)

            aow = numpy.einsum('npi,np->pi', ao[:4], wv)
            giao = mol.eval_gto('GTOval_ig_sph', coords, 3,
                                non0tab=non0tab, out=buf[4:])
            vmat[0] += numint._dot_ao_ao(mol, aow, giao[0], nao, ip1-ip0, non0tab)
            vmat[1] += numint._dot_ao_ao(mol, aow, giao[1], nao, ip1-ip0, non0tab)
            vmat[2] += numint._dot_ao_ao(mol, aow, giao[2], nao, ip1-ip0, non0tab)

            giao = mol.eval_gto('GTOval_ipig_sph', coords, 9,
                                non0tab=non0tab, out=buf[1:])
            aow = numpy.einsum('pi,p->pi', giao[XX], wv[1])
            aow+= numpy.einsum('pi,p->pi', giao[YX], wv[2])
            aow+= numpy.einsum('pi,p->pi', giao[ZX], wv[3])
            vmat[0] += numint._dot_ao_ao(mol, ao[0], aow, nao, ip1-ip0, non0tab)
            aow = numpy.einsum('pi,p->pi', giao[XY], wv[1])
            aow+= numpy.einsum('pi,p->pi', giao[YY], wv[2])
            aow+= numpy.einsum('pi,p->pi', giao[ZY], wv[3])
            vmat[1] += numint._dot_ao_ao(mol, ao[0], aow, nao, ip1-ip0, non0tab)
            aow = numpy.einsum('pi,p->pi', giao[XZ], wv[1])
            aow+= numpy.einsum('pi,p->pi', giao[YZ], wv[2])
            aow+= numpy.einsum('pi,p->pi', giao[ZZ], wv[3])
            vmat[2] += numint._dot_ao_ao(mol, ao[0], aow, nao, ip1-ip0, non0tab)
            rho = vxc = vrho = vsigma = wv = aow = giao = None
    else:
        raise NotImplementedError('meta-GGA')

    return vmat - vmat.transpose(0,2,1)