Exemple #1
0
def get_vxc_full_response(ni, mol, grids, xc_code, dms, relativity=0, hermi=1,
                          max_memory=2000, verbose=None):
    '''Full response including the response of the grids'''
    xctype = ni._xc_type(xc_code)
    make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi)
    ao_loc = mol.ao_loc_nr()

    excsum = 0
    vmat = numpy.zeros((3,nao,nao))
    if xctype == 'LDA':
        ao_deriv = 1
        vtmp = numpy.empty((3,nao,nao))
        for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)):
            ngrids = weight.size
            mask = gen_grid.make_mask(mol, coords)
            ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask)
            rho = make_rho(0, ao[0], mask, 'LDA')
            exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1,
                                  verbose=verbose)[:2]
            vrho = vxc[0]

            vtmp = numpy.zeros((3,nao,nao))
            aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
            _d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True)
            vmat += vtmp

            # response of weights
            excsum += numpy.einsum('r,r,nxr->nx', exc, rho, weight1)
            # response of grids coordinates
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2
            rho = vxc = vrho = aow = None

    elif xctype == 'GGA':
        ao_deriv = 2
        for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)):
            ngrids = weight.size
            mask = gen_grid.make_mask(mol, coords)
            ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask)
            rho = make_rho(0, ao[:4], mask, 'GGA')
            exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1,
                                  verbose=verbose)[:2]

            vtmp = numpy.zeros((3,nao,nao))
            wv = numint._rks_gga_wv0(rho, vxc, weight)
            _gga_grad_sum_(vtmp, mol, ao, wv, mask, ao_loc)
            vmat += vtmp

            # response of weights
            excsum += numpy.einsum('r,r,nxr->nx', exc, rho[0], weight1)
            # response of grids coordinates
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2
            rho = vxc = vrho = vsigma = wv = mat = None

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

    # - sign because nabla_X = -nabla_x
    return excsum, -vmat
Exemple #2
0
def get_vxc_full_response(ni, mol, grids, xc_code, dms, relativity=0, hermi=1,
                          max_memory=2000, verbose=None):
    '''Full response including the response of the grids'''
    xctype = ni._xc_type(xc_code)
    make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi)
    ao_loc = mol.ao_loc_nr()

    excsum = 0
    vmat = numpy.zeros((3,nao,nao))
    if xctype == 'LDA':
        ao_deriv = 1
        vtmp = numpy.empty((3,nao,nao))
        for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)):
            ngrids = weight.size
            mask = gen_grid.make_mask(mol, coords)
            ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask)
            rho = make_rho(0, ao[0], mask, 'LDA')
            exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[:2]
            vrho = vxc[0]

            vtmp = numpy.zeros((3,nao,nao))
            aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
            _d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True)
            vmat += vtmp

            # response of weights
            excsum += numpy.einsum('r,r,nxr->nx', exc, rho, weight1)
            # response of grids coordinates
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2
            rho = vxc = vrho = aow = None

    elif xctype == 'GGA':
        ao_deriv = 2
        for atm_id, (coords, weight, weight1) in enumerate(grids_response_cc(grids)):
            ngrids = weight.size
            mask = gen_grid.make_mask(mol, coords)
            ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask)
            rho = make_rho(0, ao[:4], mask, 'GGA')
            exc, vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[:2]

            vtmp = numpy.zeros((3,nao,nao))
            wv = numint._rks_gga_wv0(rho, vxc, weight)
            _gga_grad_sum_(vtmp, mol, ao, wv, mask, ao_loc)
            vmat += vtmp

            # response of weights
            excsum += numpy.einsum('r,r,nxr->nx', exc, rho[0], weight1)
            # response of grids coordinates
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms) * 2
            rho = vxc = vrho = vsigma = wv = mat = None

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

    # - sign because nabla_X = -nabla_x
    return excsum, -vmat
Exemple #3
0
def get_vxc(ni,
            mol,
            grids,
            xc_code,
            dms,
            relativity=0,
            hermi=1,
            max_memory=2000,
            verbose=None):
    xctype = ni._xc_type(xc_code)
    make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi)
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

    vmat = numpy.zeros((nset, 3, nao, nao))
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            for idm in range(nset):
                rho = make_rho(idm, ao[0], mask, 'LDA')
                vxc = ni.eval_xc(xc_code,
                                 rho,
                                 0,
                                 relativity,
                                 1,
                                 verbose=verbose)[1]
                vrho = vxc[0]
                aow = numpy.einsum('pi,p->pi', ao[0], weight * vrho)
                _d1_dot_(vmat[idm], mol, ao[1:4], aow, mask, ao_loc, True)
                rho = vxc = vrho = aow = None
    elif xctype == 'GGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            for idm in range(nset):
                rho = make_rho(idm, ao[:4], mask, 'GGA')
                vxc = ni.eval_xc(xc_code,
                                 rho,
                                 0,
                                 relativity,
                                 1,
                                 verbose=verbose)[1]
                wv = numint._rks_gga_wv0(rho, vxc, weight)
                _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc)
                rho = vxc = vrho = vsigma = wv = None
    elif xctype == 'NLC':
        raise NotImplementedError('NLC')
    else:
        raise NotImplementedError('meta-GGA')

    exc = None
    if nset == 1:
        vmat = vmat.reshape(3, nao, nao)
    # - sign because nabla_X = -nabla_x
    return exc, -vmat
Exemple #4
0
    def test_gga_deriv1(self):
        ng = 7
        xctype = 'GGA'
        np.random.seed(8)
        rho = np.random.rand(2, 4, ng)
        weight = 1

        exc, vxc, fxc, kxc = eval_xc(f'R-{xctype}', ng)
        ref = numint._rks_gga_wv0(rho[0], vxc, weight)
        ref[0] *= 2
        v1 = xc_deriv.transform_vxc(rho[0], vxc, xctype, spin=0)
        self.assertAlmostEqual(abs(v1 - ref).max(), 0, 12)

        exc, vxc, fxc, kxc = eval_xc(f'U-{xctype}', ng)
        ref = np.array(numint._uks_gga_wv0(rho, vxc, weight))
        ref[:, 0] *= 2
        v1 = xc_deriv.transform_vxc(rho, vxc, xctype, spin=1)
        self.assertAlmostEqual(abs(v1 - ref).max(), 0, 12)
Exemple #5
0
def get_vxc(ni, mol, grids, xc_code, dms, relativity=0, hermi=1,
            max_memory=2000, verbose=None):
    xctype = ni._xc_type(xc_code)
    make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi)
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

    vmat = numpy.zeros((nset,3,nao,nao))
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            for idm in range(nset):
                rho = make_rho(idm, ao[0], mask, 'LDA')
                vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[1]
                vrho = vxc[0]
                aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
                _d1_dot_(vmat[idm], mol, ao[1:4], aow, mask, ao_loc, True)
                rho = vxc = vrho = aow = None
    elif xctype == 'GGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            for idm in range(nset):
                rho = make_rho(idm, ao[:4], mask, 'GGA')
                vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1, verbose)[1]
                wv = numint._rks_gga_wv0(rho, vxc, weight)
                _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc)
                rho = vxc = vrho = vsigma = wv = None
    elif xctype == 'NLC':
        raise NotImplementedError('NLC')
    else:
        raise NotImplementedError('meta-GGA')

    exc = None
    if nset == 1:
        vmat = vmat.reshape(3,nao,nao)
    # - sign because nabla_X = -nabla_x
    return exc, -vmat
Exemple #6
0
def _contract_xc_kernel(td_grad,
                        xc_code,
                        dmvo,
                        dmoo=None,
                        with_vxc=True,
                        with_kxc=True,
                        singlet=True,
                        max_memory=2000):
    mol = td_grad.mol
    mf = td_grad.base._scf
    grids = mf.grids

    ni = mf._numint
    xctype = ni._xc_type(xc_code)

    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

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

    f1vo = numpy.zeros((4, nao, nao))  # 0th-order, d/dx, d/dy, d/dz
    deriv = 2
    if dmoo 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

    if xctype == 'LDA':
        ao_deriv = 1
        if singlet:
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
                rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
                vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:]

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

        else:
            raise NotImplementedError('LDA triplet')

    elif xctype == 'GGA':
        if singlet:

            def gga_sum_(vmat, ao, wv, mask):
                aow = numpy.einsum('pi,p->pi', ao[0], wv[0])
                aow += numpy.einsum('npi,np->pi', ao[1:4], wv[1:])
                tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice,
                                        ao_loc)
                vmat[0] += tmp + tmp.T
                rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv, mask, ao_loc)

            ao_deriv = 2
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
                rho = ni.eval_rho2(mol, ao, mo_coeff, mo_occ, mask, 'GGA')
                vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:]

                rho1 = ni.eval_rho(mol, ao, dmvo, mask,
                                   'GGA') * 2  # *2 for alpha + beta
                wv = numint._rks_gga_wv1(rho, rho1, vxc, fxc, weight)
                gga_sum_(f1vo, ao, wv, mask)

                if dmoo is not None:
                    rho2 = ni.eval_rho(mol, ao, dmoo, mask, 'GGA') * 2
                    wv = numint._rks_gga_wv1(rho, rho2, vxc, fxc, weight)
                    gga_sum_(f1oo, ao, wv, mask)
                if with_vxc:
                    wv = numint._rks_gga_wv0(rho, vxc, weight)
                    gga_sum_(v1ao, ao, wv, mask)
                if with_kxc:
                    wv = numint._rks_gga_wv2(rho, rho1, fxc, kxc, weight)
                    gga_sum_(k1ao, ao, wv, mask)
                vxc = fxc = kxc = rho = rho1 = None

        else:
            raise NotImplementedError('GGA triplet')

    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 #7
0
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    aoslices = mol.aoslice_by_atom()
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    vmat = numpy.zeros((mol.natm, 3, nao, nao))
    max_memory = max(2000, max_memory - vmat.size * 8 / 1e6)
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
            vrho = vxc[0]
            frr = fxc[0]
            ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice,
                                       ao_loc)
            aow1 = numpy.einsum('xpi,p->xpi', ao[1:], weight * vrho)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
                # First order density = rho1 * 2.  *2 is not applied because + c.c. in the end
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                    ao_dm0[:, p0:p1])
                aow = numpy.einsum('pi,xp->xpi', ao[0], weight * frr * rho1)
                aow[:, :, p0:p1] += aow1[:, :, p0:p1]
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
            ao_dm0 = aow = aow1 = None

        for ia in range(mol.natm):
            vmat[ia] = -vmat[ia] - vmat[ia].transpose(0, 2, 1)

    elif xctype == 'GGA':
        ao_deriv = 2
        v_ip = numpy.zeros((3, nao, nao))
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc)

            ao_dm0 = [
                numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices)
                wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight)
                wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight)
                wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight)
                aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv)
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia, :, p0:p1] += v_ip[:, p0:p1]
            vmat[ia] = -vmat[ia] - vmat[ia].transpose(0, 2, 1)

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

    return vmat
Exemple #8
0
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    aoslices = mol.aoslice_by_atom()
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    vmat = numpy.zeros((mol.natm, 3, 3, nao, nao))
    ipip = numpy.zeros((3, 3, nao, nao))
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
            vrho = vxc[0]
            frr = fxc[0]
            aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight * vrho)
            _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice,
                                       ao_loc)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
                # *2 for \nabla|ket> in rho1
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                    ao_dm0[:, p0:p1]) * 2
                # aow ~ rho1 ~ d/dR1
                aow = numpy.einsum('pi,xp->xpi', ao[0], weight * frr * rho1)
                _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1]

    elif xctype == 'GGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            aow = rks_grad._make_dR_dao_w(ao, wv)
            _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0 = [
                numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices)
                wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight)
                wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight)
                wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight)

                aow = rks_grad._make_dR_dao_w(ao, wv[0])
                rks_grad._d1_dot_(vmat[ia, 0], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wv[1])
                rks_grad._d1_dot_(vmat[ia, 1], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wv[2])
                rks_grad._d1_dot_(vmat[ia, 2], mol, aow, ao[0], mask, ao_loc,
                                  True)

                aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv)
                _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2)

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

    return vmat
Exemple #9
0
def _get_vxc_diag(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

    vmat = numpy.zeros((6, nao, nao))
    if xctype == 'LDA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            aow = numpy.einsum('pi,p->pi', ao[0], weight * vrho)
            for i in range(6):
                vmat[i] += numint._dot_ao_ao(mol, ao[i + 4], aow, mask,
                                             shls_slice, ao_loc)
            aow = None

    elif xctype == 'GGA':

        def contract_(mat, ao, aoidx, wv, mask):
            aow = numpy.einsum('pi,p->pi', ao[aoidx[0]], wv[1])
            aow += numpy.einsum('pi,p->pi', ao[aoidx[1]], wv[2])
            aow += numpy.einsum('pi,p->pi', ao[aoidx[2]], wv[3])
            mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)

        ao_deriv = 3
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            # *2 because v.T is not applied. Only v is computed in the next _dot_ao_ao
            wv[0] *= 2
            aow = numpy.einsum('npi,np->pi', ao[:4], wv)
            for i in range(6):
                vmat[i] += numint._dot_ao_ao(mol, ao[i + 4], aow, mask,
                                             shls_slice, ao_loc)

            contract_(vmat[0], ao, [XXX, XXY, XXZ], wv, mask)
            contract_(vmat[1], ao, [XXY, XYY, XYZ], wv, mask)
            contract_(vmat[2], ao, [XXZ, XYZ, XZZ], wv, mask)
            contract_(vmat[3], ao, [XYY, YYY, YYZ], wv, mask)
            contract_(vmat[4], ao, [XYZ, YYZ, YZZ], wv, mask)
            contract_(vmat[5], ao, [XZZ, YZZ, ZZZ], wv, mask)
            rho = vxc = wv = aow = None

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

    vmat = vmat[[0, 1, 2, 1, 3, 4, 2, 4, 5]]
    return vmat.reshape(3, 3, nao, nao)
Exemple #10
0
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    aoslices = mol.aoslice_by_atom()
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    vmat = numpy.zeros((mol.natm,3,nao,nao))
    max_memory = max(2000, max_memory-vmat.size*8/1e6)
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
            vrho = vxc[0]
            frr = fxc[0]
            ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc)
            aow1 = numpy.einsum('xpi,p->xpi', ao[1:], weight*vrho)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
# First order density = rho1 * 2.  *2 is not applied because + c.c. in the end
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:,:,p0:p1], ao_dm0[:,p0:p1])
                aow = numpy.einsum('pi,xp->xpi', ao[0], weight*frr*rho1)
                aow[:,:,p0:p1] += aow1[:,:,p0:p1]
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True)
            ao_dm0 = aow = aow1 = None

        for ia in range(mol.natm):
            vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1)

    elif xctype == 'GGA':
        ao_deriv = 2
        v_ip = numpy.zeros((3,nao,nao))
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc)

            ao_dm0 = [numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                      for i in range(4)]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices)
                wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight)
                wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight)
                wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight)
                aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv)
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia,:,p0:p1] += v_ip[:,p0:p1]
            vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1)

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

    return vmat
Exemple #11
0
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    aoslices = mol.aoslice_by_atom()
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    vmat = numpy.zeros((mol.natm,3,3,nao,nao))
    ipip = numpy.zeros((3,3,nao,nao))
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
            vrho = vxc[0]
            frr = fxc[0]
            aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight*vrho)
            _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
                # *2 for \nabla|ket> in rho1
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:,:,p0:p1], ao_dm0[:,p0:p1]) * 2
                # aow ~ rho1 ~ d/dR1
                aow = numpy.einsum('pi,xp->xpi', ao[0], weight*frr*rho1)
                _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia,:,:,:,p0:p1] += ipip[:,:,:,p0:p1]

    elif xctype == 'GGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            aow = rks_grad._make_dR_dao_w(ao, wv)
            _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0 = [numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                      for i in range(4)]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices)
                wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight)
                wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight)
                wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight)

                aow = rks_grad._make_dR_dao_w(ao, wv[0])
                rks_grad._d1_dot_(vmat[ia,0], mol, aow, ao[0], mask, ao_loc, True)
                aow = rks_grad._make_dR_dao_w(ao, wv[1])
                rks_grad._d1_dot_(vmat[ia,1], mol, aow, ao[0], mask, ao_loc, True)
                aow = rks_grad._make_dR_dao_w(ao, wv[2])
                rks_grad._d1_dot_(vmat[ia,2], mol, aow, ao[0], mask, ao_loc, True)

                aow = numpy.einsum('npi,Xnp->Xpi', ao[:4], wv)
                _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia,:,:,:,p0:p1] += ipip[:,:,:,p0:p1]
            vmat[ia,:,:,:,p0:p1] += ipip[:,:,p0:p1].transpose(1,0,3,2)

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

    return vmat
Exemple #12
0
def _get_vxc_diag(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

    vmat = numpy.zeros((6,nao,nao))
    if xctype == 'LDA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
            for i in range(6):
                vmat[i] += numint._dot_ao_ao(mol, ao[i+4], aow, mask, shls_slice, ao_loc)
            aow = None

    elif xctype == 'GGA':
        def contract_(mat, ao, aoidx, wv, mask):
            aow = numpy.einsum('pi,p->pi', ao[aoidx[0]], wv[1])
            aow+= numpy.einsum('pi,p->pi', ao[aoidx[1]], wv[2])
            aow+= numpy.einsum('pi,p->pi', ao[aoidx[2]], wv[3])
            mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)

        ao_deriv = 3
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            # *2 because v.T is not applied. Only v is computed in the next _dot_ao_ao 
            wv[0] *= 2
            aow = numpy.einsum('npi,np->pi', ao[:4], wv)
            for i in range(6):
                vmat[i] += numint._dot_ao_ao(mol, ao[i+4], aow, mask, shls_slice, ao_loc)

            contract_(vmat[0], ao, [XXX,XXY,XXZ], wv, mask)
            contract_(vmat[1], ao, [XXY,XYY,XYZ], wv, mask)
            contract_(vmat[2], ao, [XXZ,XYZ,XZZ], wv, mask)
            contract_(vmat[3], ao, [XYY,YYY,YYZ], wv, mask)
            contract_(vmat[4], ao, [XYZ,YYZ,YZZ], wv, mask)
            contract_(vmat[5], ao, [XZZ,YZZ,ZZZ], wv, mask)
            rho = vxc = wv = aow = None

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

    vmat = vmat[[0,1,2,
                 1,3,4,
                 2,4,5]]
    return vmat.reshape(3,3,nao,nao)
Exemple #13
0
def dia(magobj, gauge_orig=None):
    mol = magobj.mol
    mf = magobj._scf
    mo_energy = mf.mo_energy
    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    orbo = mo_coeff[:, mo_occ > 0]
    dm0 = numpy.dot(orbo, orbo.T) * 2
    dm0 = lib.tag_array(dm0, mo_coeff=mo_coeff, mo_occ=mo_occ)
    dme0 = numpy.dot(orbo * mo_energy[mo_occ > 0], orbo.T) * 2

    e2 = rhf_mag._get_dia_1e(magobj, gauge_orig, dm0, dme0)

    if gauge_orig is not None:
        return -e2

    # Computing the 2nd order Vxc integrals from GIAO
    grids = mf.grids
    ni = mf._numint
    xc_code = mf.xc
    xctype = ni._xc_type(xc_code)
    omega, alpha, hyb = ni.rsh_and_hybrid_coeff(xc_code, mol.spin)

    make_rho, nset, nao = ni._gen_rho_evaluator(mol, dm0, hermi=1)
    ngrids = len(grids.weights)
    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .9 - mem_now)
    BLKSIZE = numint.BLKSIZE
    blksize = min(
        int(max_memory / 12 * 1e6 / 8 / nao / BLKSIZE) * BLKSIZE, ngrids)

    vmat = numpy.zeros((3, 3, nao, nao))
    if xctype == 'LDA':
        ao_deriv = 0
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory,
                                 blksize=blksize):
            rho = make_rho(0, ao, mask, 'LDA')
            vxc = ni.eval_xc(xc_code, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            r_ao = numpy.einsum('pi,px->pxi', ao, coords)
            aow = numpy.einsum('pxi,p,p->pxi', r_ao, weight, vrho)
            vmat += lib.einsum('pxi,pyj->xyij', r_ao, aow)
            rho = vxc = vrho = aow = None

    elif xctype == 'GGA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory,
                                 blksize=blksize):
            rho = make_rho(0, ao, mask, 'GGA')
            vxc = ni.eval_xc(xc_code, rho, 0, deriv=1)[1]
            wv = numint._rks_gga_wv0(rho, vxc, weight)

            # Computing \nabla (r * AO) = r * \nabla AO + [\nabla,r]_- * AO
            r_ao = numpy.einsum('npi,px->npxi', ao, coords)
            r_ao[1, :, 0] += ao[0]
            r_ao[2, :, 1] += ao[0]
            r_ao[3, :, 2] += ao[0]

            aow = numpy.einsum('npxi,np->pxi', r_ao, wv)
            vmat += lib.einsum('pxi,pyj->xyij', r_ao[0], aow)
            rho = vxc = vrho = vsigma = wv = aow = None

        vmat = vmat + vmat.transpose(0, 1, 3, 2)

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

    vmat = _add_giao_phase(mol, vmat)
    e2 += numpy.einsum('qp,xypq->xy', dm0, vmat)
    vmat = None

    e2 = e2.ravel()
    # Handle the hybrid functional and the range-separated functional
    if abs(hyb) > 1e-10:
        vs = jk.get_jk(mol, [dm0] * 3,
                       ['ijkl,ji->s2kl', 'ijkl,jk->s1il', 'ijkl,li->s1kj'],
                       'int2e_gg1',
                       's4',
                       9,
                       hermi=1)
        e2 += numpy.einsum('xpq,qp->x', vs[0], dm0)
        e2 -= numpy.einsum('xpq,qp->x', vs[1], dm0) * .25 * hyb
        e2 -= numpy.einsum('xpq,qp->x', vs[2], dm0) * .25 * hyb
        vk = jk.get_jk(mol,
                       dm0,
                       'ijkl,jk->s1il',
                       'int2e_g1g2',
                       'aa4',
                       9,
                       hermi=0)
        e2 -= numpy.einsum('xpq,qp->x', vk, dm0) * .5 * hyb

        if abs(omega) > 1e-10:
            with mol.with_range_coulomb(omega):
                vs = jk.get_jk(mol, [dm0] * 2,
                               ['ijkl,jk->s1il', 'ijkl,li->s1kj'],
                               'int2e_gg1',
                               's4',
                               9,
                               hermi=1)
                e2 -= numpy.einsum('xpq,qp->x', vs[0],
                                   dm0) * .25 * (alpha - hyb)
                e2 -= numpy.einsum('xpq,qp->x', vs[1],
                                   dm0) * .25 * (alpha - hyb)
                vk = jk.get_jk(mol,
                               dm0,
                               'ijkl,jk->s1il',
                               'int2e_g1g2',
                               'aa4',
                               9,
                               hermi=0)
                e2 -= numpy.einsum('xpq,qp->x', vk, dm0) * .5 * (alpha - hyb)

    else:
        vj = jk.get_jk(mol,
                       dm0,
                       'ijkl,ji->s2kl',
                       'int2e_gg1',
                       's4',
                       9,
                       hermi=1)
        e2 += numpy.einsum('xpq,qp->x', vj, dm0)

    return -e2.reshape(3, 3)
Exemple #14
0
def _contract_xc_kernel(td_grad, xc_code, dmvo, dmoo=None, with_vxc=True,
                        with_kxc=True, singlet=True, max_memory=2000):
    mol = td_grad.mol
    mf = td_grad.base._scf
    grids = mf.grids

    ni = mf._numint
    xctype = ni._xc_type(xc_code)

    mo_coeff = mf.mo_coeff
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

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

    f1vo = numpy.zeros((4,nao,nao))  # 0th-order, d/dx, d/dy, d/dz
    deriv = 2
    if dmoo 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

    if xctype == 'LDA':
        ao_deriv = 1
        if singlet:
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
                rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
                vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:]

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

        else:
            raise NotImplementedError('LDA triplet')

    elif xctype == 'GGA':
        if singlet:
            def gga_sum_(vmat, ao, wv, mask):
                aow  = numpy.einsum('pi,p->pi', ao[0], wv[0])
                aow += numpy.einsum('npi,np->pi', ao[1:4], wv[1:])
                tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc)
                vmat[0] += tmp + tmp.T
                rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv, mask, ao_loc)
            ao_deriv = 2
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
                rho = ni.eval_rho2(mol, ao, mo_coeff, mo_occ, mask, 'GGA')
                vxc, fxc, kxc = ni.eval_xc(xc_code, rho, 0, deriv=deriv)[1:]

                rho1 = ni.eval_rho(mol, ao, dmvo, mask, 'GGA') * 2  # *2 for alpha + beta
                wv = numint._rks_gga_wv1(rho, rho1, vxc, fxc, weight)
                gga_sum_(f1vo, ao, wv, mask)

                if dmoo is not None:
                    rho2 = ni.eval_rho(mol, ao, dmoo, mask, 'GGA') * 2
                    wv = numint._rks_gga_wv1(rho, rho2, vxc, fxc, weight)
                    gga_sum_(f1oo, ao, wv, mask)
                if with_vxc:
                    wv = numint._rks_gga_wv0(rho, vxc, weight)
                    gga_sum_(v1ao, ao, wv, mask)
                if with_kxc:
                    wv = numint._rks_gga_wv2(rho, rho1, fxc, kxc, weight)
                    gga_sum_(k1ao, ao, wv, mask)
                vxc = fxc = kxc = rho = rho1 = None

        else:
            raise NotImplementedError('GGA triplet')

    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 #15
0
def get_vxc(ni,
            cell,
            grids,
            xc_code,
            dms,
            kpts,
            kpts_band=None,
            relativity=0,
            hermi=1,
            max_memory=2000,
            verbose=None):
    xctype = ni._xc_type(xc_code)
    make_rho, nset, nao = ni._gen_rho_evaluator(cell, dms, hermi)
    ao_loc = cell.ao_loc_nr()
    nkpts = len(kpts)
    vmat = np.zeros((3, nset, nkpts, nao, nao), dtype=dms.dtype)
    if xctype == 'LDA':
        ao_deriv = 1
        for ao_k1, ao_k2, mask, weight, coords \
                in ni.block_loop(cell, grids, nao, ao_deriv, kpts, kpts_band, max_memory):
            ao_k1 = np.asarray(ao_k1)
            ao_k2 = np.asarray(ao_k2)
            for i in range(nset):
                rho = make_rho(i, ao_k2[:, 0], mask, xctype)
                vxc = ni.eval_xc(xc_code, rho, 0, relativity, 1)[1]
                vrho = vxc[0]
                aow = np.einsum('xpi,p->xpi', ao_k1[:, 0], weight * vrho)
                for kn in range(nkpts):
                    rks_grad._d1_dot_(vmat[:, i, kn], cell, ao_k1[kn, 1:4],
                                      aow[kn], mask, ao_loc, True)
                rho = vrho = aow = None

    elif xctype == 'GGA':
        ao_deriv = 2
        for ao_k1, ao_k2, mask, weight, coords \
                in ni.block_loop(cell, grids, nao, ao_deriv, kpts, kpts_band, max_memory):
            ao_k1 = np.asarray(ao_k1)
            ao_k2 = np.asarray(ao_k2)
            for i in range(nset):
                rho = make_rho(i, ao_k2[:, :4], mask, xctype)
                vxc = ni.eval_xc(xc_code,
                                 rho,
                                 0,
                                 relativity,
                                 1,
                                 verbose=verbose)[1]
                wv = numint._rks_gga_wv0(rho, vxc, weight)
                for kn in range(nkpts):
                    rks_grad._gga_grad_sum_(vmat[:, i, kn], cell, ao_k1[kn],
                                            wv, mask, ao_loc)
                rho = vxc = wv = None

    elif xctype == 'NLC':
        raise NotImplementedError("NLC")
    else:
        raise NotImplementedError("metaGGA")

    if nset == 1:
        return -vmat[:, 0]
    else:
        return -vmat
Exemple #16
0
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    aoslices = mol.aoslice_by_atom()
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    v_ip = numpy.zeros((3, nao, nao))
    vmat = numpy.zeros((mol.natm, 3, nao, nao))
    max_memory = max(2000, max_memory - vmat.size * 8 / 1e6)
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, xctype)
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
            vrho = vxc[0]
            frr = fxc[0]
            aow = numint._scale_ao(ao[0], weight * vrho)
            rks_grad._d1_dot_(v_ip, mol, ao[1:4], aow, mask, ao_loc, True)

            ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice,
                                       ao_loc)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
                # First order density = rho1 * 2.  *2 is not applied because + c.c. in the end
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                    ao_dm0[:, p0:p1])
                wv = weight * frr * rho1
                aow = [numint._scale_ao(ao[0], wv[i]) for i in range(3)]
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
            ao_dm0 = aow = None

    elif xctype == 'GGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, xctype)
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc)

            ao_dm0 = [
                numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices)
                wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight)
                wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight)
                wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight)
                aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)]
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
            ao_dm0 = aow = None

    elif xctype == 'MGGA':
        if grids.level < 5:
            logger.warn(mol, 'MGGA Hessian is sensitive to dft grids.')
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:10], mo_coeff, mo_occ, mask, xctype)
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_mgga_wv0(rho, vxc, weight)
            rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc)

            # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv0
            rks_grad._tau_grad_dot_(v_ip, mol, ao, wv[5] * 2, mask, ao_loc,
                                    True)

            ao_dm0 = [
                numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices, xctype)
                wv[0] = numint._rks_mgga_wv1(rho, dR_rho1[0], vxc, fxc, weight)
                wv[1] = numint._rks_mgga_wv1(rho, dR_rho1[1], vxc, fxc, weight)
                wv[2] = numint._rks_mgga_wv1(rho, dR_rho1[2], vxc, fxc, weight)
                aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)]
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)

                for j in range(1, 4):
                    aow = [numint._scale_ao(ao[j], wv[i, 5]) for i in range(3)]
                    rks_grad._d1_dot_(vmat[ia], mol, aow, ao[j], mask, ao_loc,
                                      True)
            ao_dm0 = aow = None

    for ia in range(mol.natm):
        p0, p1 = aoslices[ia][2:]
        vmat[ia, :, p0:p1] += v_ip[:, p0:p1]
        vmat[ia] = -vmat[ia] - vmat[ia].transpose(0, 2, 1)

    return vmat
Exemple #17
0
def _get_vxc_deriv2(hessobj, mo_coeff, mo_occ, max_memory):
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    aoslices = mol.aoslice_by_atom()
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    vmat = numpy.zeros((mol.natm, 3, 3, nao, nao))
    ipip = numpy.zeros((3, 3, nao, nao))
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, xctype)
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
            vrho = vxc[0]
            frr = fxc[0]
            wv = weight * vrho
            aow = [numint._scale_ao(ao[i], wv) for i in range(1, 4)]
            _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice,
                                       ao_loc)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
                # *2 for \nabla|ket> in rho1
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                    ao_dm0[:, p0:p1]) * 2
                # aow ~ rho1 ~ d/dR1
                wv = weight * frr * rho1
                aow = [numint._scale_ao(ao[0], wv[i]) for i in range(3)]
                _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1]

    elif xctype == 'GGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, xctype)
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            aow = rks_grad._make_dR_dao_w(ao, wv)
            _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0 = [
                numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices)
                for i in range(3):
                    wv[i] = numint._rks_gga_wv1(rho, dR_rho1[i], vxc, fxc,
                                                weight)
                    aow = rks_grad._make_dR_dao_w(ao, wv[i])
                    rks_grad._d1_dot_(vmat[ia, i], mol, aow, ao[0], mask,
                                      ao_loc, True)

                aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)]
                _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2)

    elif xctype == 'MGGA':
        XX, XY, XZ = 4, 5, 6
        YX, YY, YZ = 5, 7, 8
        ZX, ZY, ZZ = 6, 8, 9
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:10], mo_coeff, mo_occ, mask, xctype)
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_mgga_wv0(rho, vxc, weight)
            aow = rks_grad._make_dR_dao_w(ao, wv)
            _d1d2_dot_(ipip, mol, aow, ao[1:4], mask, ao_loc, False)

            aow = [numint._scale_ao(ao[i], wv[5]) for i in range(4, 10)]
            _d1d2_dot_(ipip, mol, [aow[0], aow[1], aow[2]],
                       [ao[XX], ao[XY], ao[XZ]], mask, ao_loc, False)
            _d1d2_dot_(ipip, mol, [aow[1], aow[3], aow[4]],
                       [ao[YX], ao[YY], ao[YZ]], mask, ao_loc, False)
            _d1d2_dot_(ipip, mol, [aow[2], aow[4], aow[5]],
                       [ao[ZX], ao[ZY], ao[ZZ]], mask, ao_loc, False)

            ao_dm0 = [
                numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wv = dR_rho1 = _make_dR_rho1(ao, ao_dm0, ia, aoslices, xctype)
                for i in range(3):
                    wv[i] = numint._rks_mgga_wv1(rho, dR_rho1[i], vxc, fxc,
                                                 weight)
                    aow = rks_grad._make_dR_dao_w(ao, wv[i])
                    rks_grad._d1_dot_(vmat[ia, i], mol, aow, ao[0], mask,
                                      ao_loc, True)

                aow = [numint._scale_ao(ao[:4], wv[i, :4]) for i in range(3)]
                _d1d2_dot_(vmat[ia], mol, ao[1:4], aow, mask, ao_loc, False)

                # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv1
                wv[:, 5] *= 2
                aow = [numint._scale_ao(ao[1], wv[i, 5]) for i in range(3)]
                _d1d2_dot_(vmat[ia], mol, [ao[XX], ao[XY], ao[XZ]], aow, mask,
                           ao_loc, False)
                aow = [numint._scale_ao(ao[2], wv[i, 5]) for i in range(3)]
                _d1d2_dot_(vmat[ia], mol, [ao[YX], ao[YY], ao[YZ]], aow, mask,
                           ao_loc, False)
                aow = [numint._scale_ao(ao[3], wv[i, 5]) for i in range(3)]
                _d1d2_dot_(vmat[ia], mol, [ao[ZX], ao[ZY], ao[ZZ]], aow, mask,
                           ao_loc, False)

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, :, p0:p1]
            vmat[ia, :, :, :, p0:p1] += ipip[:, :, p0:p1].transpose(1, 0, 3, 2)

    return vmat
Exemple #18
0
def _get_vxc_deriv1(hessobj, mo_coeff, mo_occ, max_memory):
    """" This functions is slightly different from hessian.rks._get_vxc_deriv1 in that <\nabla u|Vxc|v> is removed"""
    mol = hessobj.mol
    mf = hessobj.base
    if hessobj.grids is not None:
        grids = hessobj.grids
    else:
        grids = mf.grids
    if grids.coords is None:
        grids.build(with_non0tab=True)

    nao, nmo = mo_coeff.shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    aoslices = mol.aoslice_by_atom()
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)
    vmat = np.zeros((mol.natm,3,nao,nao))
    max_memory = max(2000, max_memory-vmat.size*8/1e6)
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
            frr = fxc[0]
            ao_dm0 = numint._dot_ao_dm(mol, ao[0], dm0, mask, shls_slice, ao_loc)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
                rho1 = np.einsum('xpi,pi->xp', ao[1:,:,p0:p1], ao_dm0[:,p0:p1])
                aow = np.einsum('pi,xp->xpi', ao[0], weight*frr*rho1)
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1)

    elif xctype == 'GGA':
        ao_deriv = 2
        # v_ip = np.zeros((3,nao,nao))
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]

            wv = numint._rks_gga_wv0(rho, vxc, weight)
            # rks_grad._gga_grad_sum_(v_ip, mol, ao, wv, mask, ao_loc)
            ao_dm0 = [numint._dot_ao_dm(mol, ao[i], dm0, mask, shls_slice, ao_loc)
                      for i in range(4)]
            for ia in range(mol.natm):
                wv = dR_rho1 = rks_hess._make_dR_rho1(ao, ao_dm0, ia, aoslices)
                wv[0] = numint._rks_gga_wv1(rho, dR_rho1[0], vxc, fxc, weight)
                wv[1] = numint._rks_gga_wv1(rho, dR_rho1[1], vxc, fxc, weight)
                wv[2] = numint._rks_gga_wv1(rho, dR_rho1[2], vxc, fxc, weight)
                aow = np.einsum('npi,Xnp->Xpi', ao[:4], wv)
                rks_grad._d1_dot_(vmat[ia], mol, aow, ao[0], mask, ao_loc, True)
            ao_dm0 = aow = None

        for ia in range(mol.natm):
            vmat[ia] = -vmat[ia] - vmat[ia].transpose(0,2,1)

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

    return vmat
Exemple #19
0
def get_vxc(ni,
            mol,
            grids,
            xc_code,
            dms,
            relativity=0,
            hermi=1,
            max_memory=2000,
            verbose=None):
    xctype = ni._xc_type(xc_code)
    make_rho, nset, nao = ni._gen_rho_evaluator(mol, dms, hermi)
    ao_loc = mol.ao_loc_nr()

    vmat = numpy.zeros((nset, 3, nao, nao))
    if xctype == 'LDA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            for idm in range(nset):
                rho = make_rho(idm, ao[0], mask, xctype)
                vxc = ni.eval_xc(xc_code,
                                 rho,
                                 0,
                                 relativity,
                                 1,
                                 verbose=verbose)[1]
                vrho = vxc[0]
                #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
                aow = numint._scale_ao(ao[0], weight * vrho)
                _d1_dot_(vmat[idm], mol, ao[1:4], aow, mask, ao_loc, True)

    elif xctype == 'GGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            for idm in range(nset):
                rho = make_rho(idm, ao[:4], mask, xctype)
                vxc = ni.eval_xc(xc_code,
                                 rho,
                                 0,
                                 relativity,
                                 1,
                                 verbose=verbose)[1]
                wv = numint._rks_gga_wv0(rho, vxc, weight)
                _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc)

    elif xctype == 'NLC':
        raise NotImplementedError('NLC')

    elif xctype == 'MGGA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            for idm in range(nset):
                rho = make_rho(idm, ao[:10], mask, xctype)
                vxc = ni.eval_xc(xc_code,
                                 rho,
                                 0,
                                 relativity,
                                 1,
                                 verbose=verbose)[1]
                wv = numint._rks_mgga_wv0(rho, vxc, weight)
                _gga_grad_sum_(vmat[idm], mol, ao, wv, mask, ao_loc)

                # *2 because wv[5] is scaled by 0.5 in _rks_mgga_wv0
                _tau_grad_dot_(vmat[idm], mol, ao, wv[5] * 2, mask, ao_loc,
                               True)

    exc = None
    if nset == 1:
        vmat = vmat[0]
    # - sign because nabla_X = -nabla_x
    return exc, -vmat
def exc_rks(mf,
            emb_dm,
            dm,
            relativity=0,
            hermi=0,
            max_memory=2000,
            verbose=None):

    ni = mf._numint
    mol = mf.mol
    grids = mf.grids
    xc_code = mf.xc

    xctype = ni._xc_type(xc_code)
    make_rho_emb, nset, nao = ni._gen_rho_evaluator(mol, emb_dm, hermi)
    make_rho_sub, nset_2, nao_2 = ni._gen_rho_evaluator(mol, dm, hermi)

    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

    nelec = np.zeros(nset)
    excsum = np.zeros(nset)
    vmat = np.zeros((nset, nao, nao))
    aow = None

    if xctype == 'LDA':
        ao_deriv = 0
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            aow = np.ndarray(ao.shape, order='F', buffer=aow)
            for idm in range(nset):
                rho_emb = make_rho_emb(idm, ao, mask, 'LDA')
                rho_sub = make_rho_sub(idm, ao, mask, 'LDA')
                exc, vxc = ni.eval_xc(xc_code, rho_emb, 0, relativity, 1,
                                      verbose)[:2]
                vrho = vxc[0]
                den = rho_sub * weight
                nelec[idm] += den.sum()
                excsum[idm] += np.dot(den, exc)
                # *.5 because vmat + vmat.T
                aow = np.einsum('pi,p->pi', ao, .5 * weight * vrho, out=aow)
                vmat[idm] += numint._dot_ao_ao(mol, ao, aow, mask, shls_slice,
                                               ao_loc)
                rho_emb = rho_sub = exc = vxc = vrho = None
    elif xctype == 'GGA':
        ao_deriv = 1
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            ngrid = weight.size
            aow = np.ndarray(ao[0].shape, order='F', buffer=aow)
            for idm in range(nset):
                rho_emb = make_rho_emb(idm, ao, mask, 'GGA')
                rho_sub = make_rho_sub(idm, ao, mask, 'GGA')
                exc, vxc = ni.eval_xc(xc_code, rho_emb, 0, relativity, 1,
                                      verbose)[:2]
                den = rho_sub[0] * weight
                nelec[idm] += den.sum()
                excsum[idm] += np.dot(den, exc)
                # ref eval_mat function
                wv = numint._rks_gga_wv0(rho_sub, vxc, weight)
                aow = np.einsum('npi,np->pi', ao, wv, out=aow)
                vmat[idm] += numint._dot_ao_ao(mol, ao[0], aow, mask,
                                               shls_slice, ao_loc)
                rho_emb = rho_sub = exc = vxc = wv = None
    elif xctype == 'NLC':
        nlc_pars = ni.nlc_coeff(xc_code[:-6])
        if nlc_pars == [0, 0]:
            raise NotImplementedError('VV10 cannot be used with %s. '
                                      'The supported functionals are %s' %
                                      (xc_code[:-6], ni.libxc.VV10_XC))
        ao_deriv = 1
        vvrho = np.empty([nset, 4, 0])
        vvweight = np.empty([nset, 0])
        vvcoords = np.empty([nset, 0, 3])
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            rhotmp = np.empty([0, 4, weight.size])
            weighttmp = np.empty([0, weight.size])
            coordstmp = np.empty([0, weight.size, 3])
            for idm in range(nset):
                rho_emb = make_rho_emb(idm, ao, mask, 'GGA')
                rho_sub = make_rho_sub(idm, ao, mask, 'GGA')
                rho_emb = np.expand_dims(rho, axis=0)
                rhotmp = np.concatenate((rhotmp, rho_emb), axis=0)
                weighttmp = np.concatenate(
                    (weighttmp, np.expand_dims(weight, axis=0)), axis=0)
                coordstmp = np.concatenate(
                    (coordstmp, np.expand_dims(coords, axis=0)), axis=0)
                rho = None
            vvrho = np.concatenate((vvrho, rhotmp), axis=2)
            vvweight = np.concatenate((vvweight, weighttmp), axis=1)
            vvcoords = np.concatenate((vvcoords, coordstmp), axis=1)
            rhotmp = weighttmp = coordstmp = None
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            ngrid = weight.size
            aow = np.ndarray(ao[0].shape, order='F', buffer=aow)
            for idm in range(nset):
                rho_emb = make_rho_emb(idm, ao, mask, 'GGA')
                rho_sub = make_rho_sub(idm, ao, mask, 'GGA')
                exc, vxc = numint._vv10nlc(rho_emb, coords, vvrho[idm],
                                           vvweight[idm], vvcoords[idm],
                                           nlc_pars)
                den = rho_sub[0] * weight
                nelec[idm] += den.sum()
                excsum[idm] += np.dot(den, exc)
                # ref eval_mat function
                wv = numint._rks_gga_wv0(rho_emb, vxc, weight)
                aow = np.einsum('npi,np->pi', ao, wv, out=aow)
                vmat[idm] += numint._dot_ao_ao(mol, ao[0], aow, mask,
                                               shls_slice, ao_loc)
                rho = exc = vxc = wv = None
        vvrho = vvweight = vvcoords = None
    elif xctype == 'MGGA':
        if (any(x in xc_code.upper() for x in ('CC06', 'CS', 'BR89', 'MK00'))):
            raise NotImplementedError('laplacian in meta-GGA method')
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory):
            ngrid = weight.size
            aow = np.ndarray(ao[0].shape, order='F', buffer=aow)
            for idm in range(nset):
                rho_emb = make_rho_emb(idm, ao, mask, 'MGGA')
                rho_sub = make_rho_sub(idm, ao, mask, 'MGGA')
                exc, vxc = ni.eval_xc(xc_code, rho_emb, 0, relativity, 1,
                                      verbose)[:2]
                vrho, vsigma, vlapl, vtau = vxc[:4]
                den = rho_sub[0] * weight
                nelec[idm] += den.sum()
                excsum[idm] += np.dot(den, exc)

                wv = numint._rks_gga_wv0(rho_emb, vxc, weight)
                aow = np.einsum('npi,np->pi', ao[:4], wv, out=aow)
                vmat[idm] += numint._dot_ao_ao(mol, ao[0], aow, mask,
                                               shls_slice, ao_loc)

                # FIXME: .5 * .5   First 0.5 for v+v.T symmetrization.
                # Second 0.5 is due to the Libxc convention tau = 1/2 \nabla\phi\dot\nabla\phi
                wv = (.5 * .5 * weight * vtau).reshape(-1, 1)
                vmat[idm] += numint._dot_ao_ao(mol, ao[1], wv * ao[1], mask,
                                               shls_slice, ao_loc)
                vmat[idm] += numint._dot_ao_ao(mol, ao[2], wv * ao[2], mask,
                                               shls_slice, ao_loc)
                vmat[idm] += numint._dot_ao_ao(mol, ao[3], wv * ao[3], mask,
                                               shls_slice, ao_loc)

                rho_emb = rho_sub = exc = vxc = vrho = vsigma = wv = None

    for i in range(nset):
        vmat[i] = vmat[i] + vmat[i].T
    if nset == 1:
        nelec = nelec[0]
        excsum = excsum[0]
        vmat = vmat.reshape(nao, nao)
    return nelec, excsum, vmat