Esempio n. 1
0
def _mcol_lda_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi):
    '''Vxc matrix of multi-collinear LDA'''
    wv = weight * vxc
    if hermi:
        wv *= .5  # * .5 because of v+v.conj().T in r_vxc
    wr, wmx, wmy, wmz = wv

    # einsum('g,g,xgi,xgj->ij', vxc, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sx, vxc, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sy, vxc, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sz, vxc, weight, ao, ao)
    aow = None
    aow = _scale_ao(ao, wmx[0], out=aow)  # Mx
    tmpx = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(ao, wmy[0], out=aow)  # My
    tmpy = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    if hermi:
        # conj(mx+my*1j) == mx-my*1j, tmpx and tmpy should be real
        matba = (tmpx + tmpx.T) + (tmpy + tmpy.T) * 1j
        matab = np.zeros_like(matba)
    else:
        # conj(mx+my*1j) != mx-my*1j, tmpx and tmpy should be complex
        matba = tmpx + tmpy * 1j
        matab = tmpx - tmpy * 1j
    tmpx = tmpy = None
    aow = _scale_ao(ao, wr[0]+wmz[0], out=aow)  # Mz
    mataa = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(ao, wr[0]-wmz[0], out=aow)  # Mz
    matbb = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    mat = np.block([[mataa, matab], [matba, matbb]])
    return mat
Esempio n. 2
0
def _col_lda_vxc_mat(mol,
                     ao,
                     weight,
                     rho,
                     vxc,
                     mask,
                     shls_slice,
                     ao_loc,
                     hermi,
                     on_LL=True):
    '''Vxc matrix of collinear LDA'''
    # NOTE vxc in u/d representation
    aoa, aob = ao
    wv = weight * vxc
    if hermi:
        wv *= .5
    if on_LL:
        wva, wvb = wv
    else:  # for SS block
        # v_rho = (vxc_a + vxc_b) * .5
        # v_mz  = (vxc_a - vxc_b) * .5
        # For small components, M = \beta\Sigma leads to
        # (v_rho - sigma_z*v_mz) = [vxc_b, 0    ]
        #                          [0    , vxc_a]
        wvb, wva = wv
    mat = _dot_ao_ao(mol, aoa, _scale_ao(aoa, wva[0]), mask, shls_slice,
                     ao_loc)
    mat += _dot_ao_ao(mol, aob, _scale_ao(aob, wvb[0]), mask, shls_slice,
                      ao_loc)
    return mat
Esempio n. 3
0
def _col_gga_vxc_mat(mol,
                     ao,
                     weight,
                     rho,
                     vxc,
                     mask,
                     shls_slice,
                     ao_loc,
                     hermi,
                     on_LL=True):
    '''Vxc matrix of collinear GGA'''
    # NOTE vxc in u/d representation
    aoa, aob = ao
    wv = weight * vxc
    if hermi:
        wv[:, 0] *= .5
    if on_LL:
        wva, wvb = wv
    else:  # for SS block
        wvb, wva = wv
    aow = None
    aow = _scale_ao(aoa[:4], wva[:4], out=aow)
    mat = _dot_ao_ao(mol, aoa[0], aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(aob[:4], wvb[:4], out=aow)
    mat += _dot_ao_ao(mol, aob[0], aow, mask, shls_slice, ao_loc)
    if hermi != 1:
        aow = _scale_ao(aoa[1:4], wva[1:4].conj(), out=aow)
        mat += _dot_ao_ao(mol, aow, aoa[0], mask, shls_slice, ao_loc)
        aow = _scale_ao(aob[1:4], wvb[1:4].conj(), out=aow)
        mat += _dot_ao_ao(mol, aow, aob[0], mask, shls_slice, ao_loc)
    return mat
Esempio n. 4
0
def _tau_grad_dot_(vmat, mol, ao, wv, mask, ao_loc, dR1_on_bra=True):
    '''The tau part of MGGA functional'''
    aow = numint._scale_ao(ao[1], wv)
    _d1_dot_(vmat, mol, [ao[4], ao[5], ao[6]], aow, mask, ao_loc, True)
    aow = numint._scale_ao(ao[2], wv, aow)
    _d1_dot_(vmat, mol, [ao[5], ao[7], ao[8]], aow, mask, ao_loc, True)
    aow = numint._scale_ao(ao[3], wv, aow)
    _d1_dot_(vmat, mol, [ao[6], ao[8], ao[9]], aow, mask, ao_loc, True)
Esempio n. 5
0
        def mgga_sum_(vmat, ao, wv, mask):
            aow = numint._scale_ao(ao[:4], wv[:4])
            tmp = numint._dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc)
            aow = numint._scale_ao(ao[1], wv[5], aow)
            tmp += numint._dot_ao_ao(mol, ao[1], aow, mask, shls_slice, ao_loc)
            aow = numint._scale_ao(ao[2], wv[5], aow)
            tmp += numint._dot_ao_ao(mol, ao[2], aow, mask, shls_slice, ao_loc)
            aow = numint._scale_ao(ao[3], wv[5], aow)
            tmp += numint._dot_ao_ao(mol, ao[3], aow, mask, shls_slice, ao_loc)
            vmat[0] += tmp + tmp.T

            rks_grad._gga_grad_sum_(vmat[1:], mol, ao, wv[:4], mask, ao_loc)
            rks_grad._tau_grad_dot_(vmat[1:], mol, ao, wv[5] * 2, mask, ao_loc,
                                    True)
Esempio n. 6
0
def _ncol_lda_vxc_mat(mol,
                      ao,
                      weight,
                      rho_tm,
                      vxc,
                      mask,
                      shls_slice,
                      ao_loc,
                      hermi,
                      on_LL=True):
    '''Vxc matrix of non-collinear LDA'''
    # NOTE vxc in u/d representation
    aoa, aob = ao
    r, mx, my, mz = rho_tm
    vxc = xc_deriv.ud2ts(vxc)
    vr, vs = vxc[:, 0]
    s = lib.norm(rho_tm[1:4], axis=0)

    wv = weight * vr
    with numpy.errstate(divide='ignore', invalid='ignore'):
        ws = vs * weight / s
    ws[s < 1e-20] = 0
    if not on_LL:
        # flip the sign for small components because
        # M = \beta\Sigma = [sigma,  0    ]
        #                   [0    , -sigma]
        ws *= -1

    # * .5 because of v+v.conj().T in r_vxc
    if hermi:
        wv *= .5
        ws *= .5

    # einsum('g,g,xgi,xgj->ij', vr, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sx, vs*m[0]/s, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sy, vs*m[1]/s, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sz, vs*m[2]/s, weight, ao, ao)
    aow = None
    aow = _scale_ao(aoa, ws * (mx + my * 1j), out=aow)
    mat = _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc)
    if hermi:
        mat = mat + mat.conj().T
    else:
        aow = _scale_ao(aob, ws * (mx - my * 1j), out=aow)  # Mx
        mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(aoa, wv + ws * mz, out=aow)  # Mz
    mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(aob, wv - ws * mz, out=aow)  # Mz
    mat += _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc)
    return mat
Esempio n. 7
0
def _mcol_mgga_vxc_mat(mol,
                       ao,
                       weight,
                       rho,
                       vxc,
                       mask,
                       shls_slice,
                       ao_loc,
                       hermi,
                       on_LL=True):
    '''Vxc matrix of multi-collinear MGGA'''
    # NOTE vxc in t/m representation
    aoa, aob = ao
    wv = weight * vxc
    tau_idx = 4
    wv[:, tau_idx] *= .5  # *.5 for 1/2 in tau
    if hermi:
        wv[:, 0] *= .5
        wv[:, tau_idx] *= .5
    if not on_LL:
        # flip the sign for small components because
        # M = \beta\Sigma = [sigma,  0    ]
        #                   [0    , -sigma]
        wv[1:4] *= -1
    wr, wmx, wmy, wmz = wv

    aow = None
    aow = _scale_ao(aoa[:4], wmx[:4] + wmy[:4] * 1j, out=aow)
    mat = _dot_ao_ao(mol, aob[0], aow, mask, shls_slice, ao_loc)
    mat += _tau_dot(mol, aob, aoa, wmx[tau_idx] + wmy[tau_idx] * 1j, mask,
                    shls_slice, ao_loc)
    if hermi:
        assert vxc.dtype == numpy.double
        mat = mat + mat.conj().T
    else:
        aow = _scale_ao(aob[:4], wmx[:4] - wmy[:4] * 1j, out=aow)
        mat += _dot_ao_ao(mol, aoa[0], aow, mask, shls_slice, ao_loc)
        mat += _tau_dot(mol, aoa, aob, wmx[tau_idx] - wmy[tau_idx] * 1j, mask,
                        shls_slice, ao_loc)

        aow = _scale_ao(aob[1:4], (wmx[1:4] + wmy[1:4] * 1j).conj(), out=aow)
        mat += _dot_ao_ao(mol, aow, aoa[0], mask, shls_slice, ao_loc)
        aow = _scale_ao(aoa[1:4], (wmx[1:4] - wmy[1:4] * 1j).conj(), out=aow)
        mat += _dot_ao_ao(mol, aow, aob[0], mask, shls_slice, ao_loc)
        aow = _scale_ao(aoa[1:4], (wr[1:4] + wmz[1:4]).conj(), out=aow)  # Mz
        mat += _dot_ao_ao(mol, aow, aoa[0], mask, shls_slice, ao_loc)
        aow = _scale_ao(aob[1:4], (wr[1:4] - wmz[1:4]).conj(), out=aow)  # Mz
        mat += _dot_ao_ao(mol, aow, aob[0], mask, shls_slice, ao_loc)

    aow = _scale_ao(aoa, wr[:4] + wmz[:4], out=aow)  # Mz
    mat += _dot_ao_ao(mol, aoa[0], aow, mask, shls_slice, ao_loc)
    mat += _tau_dot(mol, aoa, aoa, wr[tau_idx] + wmz[tau_idx], mask,
                    shls_slice, ao_loc)
    aow = _scale_ao(aob, wr[:4] - wmz[:4], out=aow)  # Mz
    mat += _dot_ao_ao(mol, aob[0], aow, mask, shls_slice, ao_loc)
    mat += _tau_dot(mol, aob, aob, wr[tau_idx] - wmz[tau_idx], mask,
                    shls_slice, ao_loc)
    return mat
Esempio n. 8
0
def _gga_grad_sum_(vmat, mol, ao, wv, mask, ao_loc):
    #:aow = numpy.einsum('npi,np->pi', ao[:4], wv[:4])
    aow = numint._scale_ao(ao[:4], wv[:4])
    _d1_dot_(vmat, mol, ao[1:4], aow, mask, ao_loc, True)
    aow = _make_dR_dao_w(ao, wv[:4])
    _d1_dot_(vmat, mol, aow, ao[0], mask, ao_loc, True)
    return vmat
Esempio n. 9
0
    def get_veff_nuc_epc(self, mol, dm, dm_last=None, vhf_last=None, hermi=1):
        '''Add EPC contribution to nuclear veff'''
        nao = mol.nao_nr()
        shls_slice = (0, mol.nbas)
        ao_loc = mol.ao_loc_nr()
        nnuc = 0
        excsum = 0
        vmat = numpy.zeros((nao, nao))

        grids = self.mf_elec.grids
        ni = self.mf_elec._numint

        aow = None
        for ao, mask, weight, coords in ni.block_loop(mol, grids, nao):
            aow = numpy.ndarray(ao.shape, order='F', buffer=aow)
            ao_elec = eval_ao(self.mol.elec, coords)
            if self.dm_elec.ndim > 2:
                rho_elec = eval_rho(self.mol.elec, ao_elec, self.dm_elec[0] + self.dm_elec[1])
            else:
                rho_elec = eval_rho(self.mol.elec, ao_elec, self.dm_elec)
            ao_nuc = eval_ao(mol, coords)
            rho_nuc = eval_rho(mol, ao_nuc, dm)
            exc, vxc = eval_xc_nuc(self.epc, rho_elec, rho_nuc)
            den = rho_nuc * weight
            nnuc += den.sum()
            excsum += numpy.dot(den, exc)
            # times 0.5 because vmat + vmat.T
            aow = _scale_ao(ao_nuc, 0.5 * weight * vxc, out=aow)
            vmat += _dot_ao_ao(mol, ao_nuc, aow, mask, shls_slice, ao_loc)
        logger.debug(self, 'The number of nuclei: %.5f', nnuc)
        vmat += vmat.conj().T
        # attach E_ep to vmat to retrieve later
        vmat = lib.tag_array(vmat, exc=excsum, ecoul=0, vj=0, vk=0)
        return vmat
Esempio n. 10
0
    def get_veff_elec_epc(self, mol, dm, dm_last=None, vhf_last=None, hermi=1):
        '''Add EPC contribution to electronic veff'''
        nao = mol.nao_nr()
        shls_slice = (0, mol.nbas)
        ao_loc = mol.ao_loc_nr()
        vmat = numpy.zeros((nao, nao))

        grids = self.mf_elec.grids
        ni = self.mf_elec._numint

        aow = None
        for i in range(self.mol.nuc_num):
            ia = self.mol.nuc[i].atom_index
            if self.mol.atom_symbol(ia) == 'H':
                for ao, mask, weight, coords in ni.block_loop(mol, grids, nao):
                    aow = numpy.ndarray(ao.shape, order='F', buffer=aow)
                    ao_elec = eval_ao(mol, coords)
                    if dm.ndim > 2:
                        rho_elec = eval_rho(mol, ao_elec, dm[0] + dm[1])
                    else:
                        rho_elec = eval_rho(mol, ao_elec, dm)
                    ao_nuc = eval_ao(self.mol.nuc[i], coords)
                    rho_nuc = eval_rho(self.mol.nuc[i], ao_nuc, self.dm_nuc[i])
                    vxc_i = eval_xc_elec(self.epc, rho_elec, rho_nuc)
                    # times 0.5 because vmat + vmat.T
                    aow = _scale_ao(ao_elec, 0.5 * weight * vxc_i, out=aow)
                    vmat += _dot_ao_ao(mol, ao_elec, aow, mask, shls_slice, ao_loc)
        vmat += vmat.conj().T
        if dm.ndim > 2:
            veff = dft.uks.get_veff(self.mf_elec, mol, dm, dm_last, vhf_last, hermi)
        else:
            veff = dft.rks.get_veff(self.mf_elec, mol, dm, dm_last, vhf_last, hermi)
        vxc = lib.tag_array(veff + vmat, ecoul=veff.ecoul, exc=veff.exc, vj=veff.vj, vk=veff.vk)
        return vxc
Esempio n. 11
0
def _contract_vot_ao(vot, ao, out=None):
    ''' REQUIRES array in shape = (nderiv,nao,ngrids) and data layout = (nderiv,ngrids,nao)/row-major '''
    nderiv = vot.shape[0]
    ao = np.ascontiguousarray(ao.transpose(0, 2, 1))
    #vao = (ao[0][None,:,:] * vot[:,None,:]).transpose (0,2,1)
    #ao = ao.transpose (0,2,1)
    #if nderiv > 1:
    #vao[0] += (ao[1:4] * vot[1:4,:,None]).sum (0)
    #vao[0] += numint._scale_ao (ao[1:4], vot[1:4])
    nao, ngrids = ao.shape[1:]
    vao = np.ndarray((nderiv, nao, ngrids), dtype=ao.dtype,
                     buffer=out).transpose(0, 2, 1)
    ao = ao.transpose(0, 2, 1)
    vao[0] = numint._scale_ao(ao[:nderiv], vot, out=vao[0])
    if nderiv > 1:
        for i in range(1, 4):
            vao[i] = numint._scale_ao(ao[0:1, :, :],
                                      vot[i:i + 1, :],
                                      out=vao[i])
    return vao
Esempio n. 12
0
def _mcol_lda_vxc_mat(mol,
                      ao,
                      weight,
                      rho,
                      vxc,
                      mask,
                      shls_slice,
                      ao_loc,
                      hermi,
                      on_LL=True):
    '''Vxc matrix of multi-collinear LDA'''
    # NOTE vxc in t/m representation
    aoa, aob = ao
    wv = weight * vxc
    if hermi:
        wv *= .5  # * .5 because of v+v.conj().T in r_vxc
    if not on_LL:
        # flip the sign for small components because
        # M = \beta\Sigma = [sigma,  0    ]
        #                   [0    , -sigma]
        wv[1:4] *= -1
    wr, wmx, wmy, wmz = wv

    # einsum('g,g,xgi,xgj->ij', vxc, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sx, vxc, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sy, vxc, weight, ao, ao)
    # + einsum('xy,g,g,xgi,ygj->ij', sz, vxc, weight, ao, ao)
    aow = None
    aow = _scale_ao(aoa, wmx[0] + wmy[0] * 1j, out=aow)
    mat = _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc)
    if hermi:
        assert vxc.dtype == numpy.double
        mat = mat + mat.conj().T
    else:
        aow = _scale_ao(aob, wmx[0] - wmy[0] * 1j, out=aow)
        mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(aoa, wr[0] + wmz[0], out=aow)  # Mz
    mat += _dot_ao_ao(mol, aoa, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(aob, wr[0] - wmz[0], out=aow)  # Mz
    mat += _dot_ao_ao(mol, aob, aow, mask, shls_slice, ao_loc)
    return mat
Esempio n. 13
0
def _ncol_lda_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi):
    '''Vxc matrix of non-collinear LDA'''
    # NOTE vxc in u/d representation
    r, mx, my, mz = rho
    vxc = xc_deriv.ud2ts(vxc)
    vr, vs = vxc[:,0]
    s = lib.norm(rho[1:4], axis=0)

    wv = weight * vr
    with np.errstate(divide='ignore',invalid='ignore'):
        ws = vs * weight / s
    ws[s < 1e-20] = 0

    # * .5 because of v+v.conj().T in r_vxc
    if hermi:
        wv *= .5
        ws *= .5
    aow = None
    aow = _scale_ao(ao, ws*mx, out=aow)  # Mx
    tmpx = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(ao, ws*my, out=aow)  # My
    tmpy = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    if hermi:
        # conj(mx+my*1j) == mx-my*1j, tmpx and tmpy should be real
        matba = (tmpx + tmpx.T) + (tmpy + tmpy.T) * 1j
        matab = np.zeros_like(matba)
    else:
        # conj(mx+my*1j) != mx-my*1j, tmpx and tmpy should be complex
        matba = tmpx + tmpy * 1j
        matab = tmpx - tmpy * 1j
    tmpx = tmpy = None
    aow = _scale_ao(ao, wv+ws*mz, out=aow)  # Mz
    mataa = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    aow = _scale_ao(ao, wv-ws*mz, out=aow)  # Mz
    matbb = _dot_ao_ao(mol, ao, aow, mask, shls_slice, ao_loc)
    mat = np.block([[mataa, matab], [matba, matbb]])
    return mat
Esempio n. 14
0
def _mcol_mgga_vxc_mat(mol, ao, weight, rho, vxc, mask, shls_slice, ao_loc, hermi):
    '''Vxc matrix of multi-collinear MGGA'''
    wv = weight * vxc
    tau_idx = 4
    wv[:,tau_idx] *= .5  # *.5 for 1/2 in tau
    if hermi:
        wv[:,0] *= .5  # * .5 because of v+v.conj().T in r_vxc
        wv[:,tau_idx] *= .5
    wr, wmx, wmy, wmz = wv

    aow = None
    aow = _scale_ao(ao[:4], wr[:4]+wmz[:4], out=aow)  # Mz
    mataa = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc)
    mataa += _tau_dot(mol, ao, ao, wr[tau_idx]+wmz[tau_idx], mask, shls_slice, ao_loc)
    aow = _scale_ao(ao[:4], wr[:4]-wmz[:4], out=aow)  # Mz
    matbb = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc)
    matbb += _tau_dot(mol, ao, ao, wr[tau_idx]-wmz[tau_idx], mask, shls_slice, ao_loc)

    aow = _scale_ao(ao[:4], wmx[:4], out=aow)  # Mx
    tmpx = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc)
    tmpx += _tau_dot(mol, ao, ao, wmx[tau_idx], mask, shls_slice, ao_loc)
    aow = _scale_ao(ao[:4], wmy[:4], out=aow)  # My
    tmpy = _dot_ao_ao(mol, ao[0], aow, mask, shls_slice, ao_loc)
    tmpy += _tau_dot(mol, ao, ao, wmy[tau_idx], mask, shls_slice, ao_loc)
    if hermi:
        assert vxc.dtype == np.double
        # conj(mx+my*1j) == mx-my*1j, tmpx and tmpy should be real
        matba = (tmpx + tmpx.T) + (tmpy + tmpy.T) * 1j
        matab = np.zeros_like(matba)
    else:
        # conj(mx+my*1j) != mx-my*1j, tmpx and tmpy should be complex
        aow = _scale_ao(ao[1:4], wmx[1:4].conj(), out=aow)  # Mx
        tmpx += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)
        aow = _scale_ao(ao[1:4], wmy[1:4].conj(), out=aow)  # My
        tmpy += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)
        matba = tmpx + tmpy * 1j
        matab = tmpx - tmpy * 1j
        aow = _scale_ao(ao[1:4], (wr[1:4]+wmz[1:4]).conj(), out=aow)  # Mz
        mataa += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)
        aow = _scale_ao(ao[1:4], (wr[1:4]-wmz[1:4]).conj(), out=aow)  # Mz
        matbb += _dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)

    mat = np.block([[mataa, matab], [matba, matbb]])
    return mat
Esempio n. 15
0
def make_psi_vmat(pcmobj,
                  dm,
                  r_vdw,
                  ui,
                  ylm_1sph,
                  cached_pol,
                  Xvec,
                  L,
                  with_nuc=True):
    '''
    The first order derivative of E_ddCOSMO wrt density matrix

    Kwargs:
        with_nuc (bool): Mute the contribution of nuclear charges when
            computing the second order derivatives of energy.
    '''
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    nlm = (lmax + 1)**2

    dms = numpy.asarray(dm)
    is_single_dm = dms.ndim == 2
    grids = pcmobj.grids

    ni = numint.NumInt()
    max_memory = pcmobj.max_memory - lib.current_memory()[0]
    make_rho, n_dm, nao = ni._gen_rho_evaluator(mol, dms)
    dms = dms.reshape(n_dm, nao, nao)
    Xvec = Xvec.reshape(n_dm, natm, nlm)

    i1 = 0
    scaled_weights = numpy.empty((n_dm, grids.weights.size))
    for ia in range(natm):
        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        fac_pol = _vstack_factor_fak_pol(fak_pol, lmax)
        i0, i1 = i1, i1 + fac_pol.shape[1]
        scaled_weights[:, i0:i1] = numpy.einsum('mn,im->in', fac_pol, Xvec[:,
                                                                           ia])
    scaled_weights *= grids.weights

    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()
    den = numpy.empty((n_dm, grids.weights.size))
    vmat = numpy.zeros((n_dm, nao, nao))
    p1 = 0
    aow = None
    for ao, mask, weight, coords \
            in ni.block_loop(mol, grids, nao, 0, max_memory):
        p0, p1 = p1, p1 + weight.size
        for i in range(n_dm):
            den[i, p0:p1] = make_rho(i, ao, mask, 'LDA')
            aow = numint._scale_ao(ao, scaled_weights[i, p0:p1], out=aow)
            vmat[i] -= numint._dot_ao_ao(mol, ao, aow, mask, shls_slice,
                                         ao_loc)
    den *= grids.weights
    ao = aow = scaled_weights = None

    nelec_leak = 0
    psi = numpy.zeros((n_dm, natm, nlm))
    i1 = 0
    for ia in range(natm):
        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        fac_pol = _vstack_factor_fak_pol(fak_pol, lmax)
        i0, i1 = i1, i1 + fac_pol.shape[1]
        nelec_leak += den[:, i0:i1][:, leak_idx].sum(axis=1)
        psi[:, ia] = -numpy.einsum('in,mn->im', den[:, i0:i1], fac_pol)
    logger.debug(pcmobj, 'electron leaks %s', nelec_leak)

    # Contribution of nuclear charges to the total density
    # The factor numpy.sqrt(4*numpy.pi) is due to the product of 4*pi * Y_0^0
    if with_nuc:
        for ia in range(natm):
            psi[:, ia, 0] += numpy.sqrt(
                4 * numpy.pi) / r_vdw[ia] * mol.atom_charge(ia)

    # <Psi, L^{-1}g> -> Psi = SL the adjoint equation to LX = g
    L_S = numpy.linalg.solve(
        L.reshape(natm * nlm, -1).T,
        psi.reshape(n_dm, -1).T)
    L_S = L_S.reshape(natm, nlm, n_dm).transpose(2, 0, 1)
    coords_1sph, weights_1sph = make_grids_one_sphere(pcmobj.lebedev_order)
    # JCP, 141, 184108, Eq (39)
    xi_jn = numpy.einsum('n,jn,xn,ijx->ijn', weights_1sph, ui, ylm_1sph, L_S)
    extern_point_idx = ui > 0
    cav_coords = (mol.atom_coords().reshape(natm, 1, 3) +
                  numpy.einsum('r,gx->rgx', r_vdw, coords_1sph))
    cav_coords = cav_coords[extern_point_idx]
    xi_jn = xi_jn[:, extern_point_idx]

    max_memory = pcmobj.max_memory - lib.current_memory()[0]
    blksize = int(max(max_memory * .9e6 / 8 / nao**2, 400))

    cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env,
                                         'int3c2e')
    vmat_tril = 0
    for i0, i1 in lib.prange(0, cav_coords.shape[0], blksize):
        fakemol = gto.fakemol_for_charges(cav_coords[i0:i1])
        v_nj = df.incore.aux_e2(mol,
                                fakemol,
                                intor='int3c2e',
                                aosym='s2ij',
                                cintopt=cintopt)
        vmat_tril += numpy.einsum('xn,in->ix', v_nj, xi_jn[:, i0:i1])
    vmat += lib.unpack_tril(vmat_tril)

    if is_single_dm:
        psi = psi[0]
        L_S = L_S[0]
        vmat = vmat[0]
    return psi, vmat, L_S
Esempio n. 16
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[0].shape
    ni = mf._numint
    xctype = ni._xc_type(mf.xc)
    shls_slice = (0, mol.nbas)
    ao_loc = mol.ao_loc_nr()

    vmata = numpy.zeros((6, nao, nao))
    vmatb = 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):
            rhoa = ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask,
                                xctype)
            rhob = ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask,
                                xctype)
            vxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=1)[1]
            vrho = vxc[0]
            aowa = numint._scale_ao(ao[0], weight * vrho[:, 0])
            aowb = numint._scale_ao(ao[0], weight * vrho[:, 1])
            for i in range(6):
                vmata[i] += numint._dot_ao_ao(mol, ao[i + 4], aowa, mask,
                                              shls_slice, ao_loc)
                vmatb[i] += numint._dot_ao_ao(mol, ao[i + 4], aowb, mask,
                                              shls_slice, ao_loc)
            aowa = aowb = None

    elif xctype == 'GGA':

        def contract_(mat, ao, aoidx, wv, mask):
            aow = numint._scale_ao(ao[aoidx[0]], wv[1])
            aow += numint._scale_ao(ao[aoidx[1]], wv[2])
            aow += numint._scale_ao(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):
            rhoa = ni.eval_rho2(mol, ao[:4], mo_coeff[0], mo_occ[0], mask,
                                xctype)
            rhob = ni.eval_rho2(mol, ao[:4], mo_coeff[1], mo_occ[1], mask,
                                xctype)
            vxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=1)[1]

            wva, wvb = numint._uks_gga_wv0((rhoa, rhob), vxc, weight)
            # *2 because v.T is not applied.
            wva[0] *= 2
            wvb[0] *= 2
            aowa = numint._scale_ao(ao[:4], wva[:4])
            aowb = numint._scale_ao(ao[:4], wvb[:4])
            for i in range(6):
                vmata[i] += numint._dot_ao_ao(mol, ao[i + 4], aowa, mask,
                                              shls_slice, ao_loc)
                vmatb[i] += numint._dot_ao_ao(mol, ao[i + 4], aowb, mask,
                                              shls_slice, ao_loc)
            contract_(vmata[0], ao, [XXX, XXY, XXZ], wva, mask)
            contract_(vmata[1], ao, [XXY, XYY, XYZ], wva, mask)
            contract_(vmata[2], ao, [XXZ, XYZ, XZZ], wva, mask)
            contract_(vmata[3], ao, [XYY, YYY, YYZ], wva, mask)
            contract_(vmata[4], ao, [XYZ, YYZ, YZZ], wva, mask)
            contract_(vmata[5], ao, [XZZ, YZZ, ZZZ], wva, mask)
            contract_(vmatb[0], ao, [XXX, XXY, XXZ], wvb, mask)
            contract_(vmatb[1], ao, [XXY, XYY, XYZ], wvb, mask)
            contract_(vmatb[2], ao, [XXZ, XYZ, XZZ], wvb, mask)
            contract_(vmatb[3], ao, [XYY, YYY, YYZ], wvb, mask)
            contract_(vmatb[4], ao, [XYZ, YYZ, YZZ], wvb, mask)
            contract_(vmatb[5], ao, [XZZ, YZZ, ZZZ], wvb, mask)
            vxc = aowa = aowb = None

    elif xctype == 'MGGA':

        def contract_(mat, ao, aoidx, wv, mask):
            aow = numint._scale_ao(ao[aoidx[0]], wv[1])
            aow += numint._scale_ao(ao[aoidx[1]], wv[2])
            aow += numint._scale_ao(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):
            rhoa = ni.eval_rho2(mol, ao[:10], mo_coeff[0], mo_occ[0], mask,
                                xctype)
            rhob = ni.eval_rho2(mol, ao[:10], mo_coeff[1], mo_occ[1], mask,
                                xctype)
            vxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=1)[1]

            wva, wvb = numint._uks_mgga_wv0((rhoa, rhob), vxc, weight)
            # *2 because v.T is not applied.
            wva[0] *= 2
            wvb[0] *= 2
            wva[5] *= 2
            wvb[5] *= 2
            aowa = numint._scale_ao(ao[:4], wva[:4])
            aowb = numint._scale_ao(ao[:4], wvb[:4])
            for i in range(6):
                vmata[i] += numint._dot_ao_ao(mol, ao[i + 4], aowa, mask,
                                              shls_slice, ao_loc)
                vmatb[i] += numint._dot_ao_ao(mol, ao[i + 4], aowb, mask,
                                              shls_slice, ao_loc)
            contract_(vmata[0], ao, [XXX, XXY, XXZ], wva, mask)
            contract_(vmata[1], ao, [XXY, XYY, XYZ], wva, mask)
            contract_(vmata[2], ao, [XXZ, XYZ, XZZ], wva, mask)
            contract_(vmata[3], ao, [XYY, YYY, YYZ], wva, mask)
            contract_(vmata[4], ao, [XYZ, YYZ, YZZ], wva, mask)
            contract_(vmata[5], ao, [XZZ, YZZ, ZZZ], wva, mask)
            contract_(vmatb[0], ao, [XXX, XXY, XXZ], wvb, mask)
            contract_(vmatb[1], ao, [XXY, XYY, XYZ], wvb, mask)
            contract_(vmatb[2], ao, [XXZ, XYZ, XZZ], wvb, mask)
            contract_(vmatb[3], ao, [XYY, YYY, YYZ], wvb, mask)
            contract_(vmatb[4], ao, [XYZ, YYZ, YZZ], wvb, mask)
            contract_(vmatb[5], ao, [XZZ, YZZ, ZZZ], wvb, mask)

            aowa = [numint._scale_ao(ao[i], wva[5]) for i in range(1, 4)]
            aowb = [numint._scale_ao(ao[i], wvb[5]) for i in range(1, 4)]
            for i, j in enumerate([XXX, XXY, XXZ, XYY, XYZ, XZZ]):
                vmata[i] += numint._dot_ao_ao(mol, ao[j], aowa[0], mask,
                                              shls_slice, ao_loc)
                vmatb[i] += numint._dot_ao_ao(mol, ao[j], aowb[0], mask,
                                              shls_slice, ao_loc)
            for i, j in enumerate([XXY, XYY, XYZ, YYY, YYZ, YZZ]):
                vmata[i] += numint._dot_ao_ao(mol, ao[j], aowa[1], mask,
                                              shls_slice, ao_loc)
                vmatb[i] += numint._dot_ao_ao(mol, ao[j], aowb[1], mask,
                                              shls_slice, ao_loc)
            for i, j in enumerate([XXZ, XYZ, XZZ, YYZ, YZZ, ZZZ]):
                vmata[i] += numint._dot_ao_ao(mol, ao[j], aowa[2], mask,
                                              shls_slice, ao_loc)
                vmatb[i] += numint._dot_ao_ao(mol, ao[j], aowb[2], mask,
                                              shls_slice, ao_loc)

    vmata = vmata[[0, 1, 2, 1, 3, 4, 2, 4, 5]].reshape(3, 3, nao, nao)
    vmatb = vmatb[[0, 1, 2, 1, 3, 4, 2, 4, 5]].reshape(3, 3, nao, nao)
    return vmata, vmatb
Esempio n. 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[0].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()
    dm0a, dm0b = mf.make_rdm1(mo_coeff, mo_occ)

    vmata = numpy.zeros((mol.natm, 3, 3, nao, nao))
    vmatb = numpy.zeros((mol.natm, 3, 3, nao, nao))
    ipipa = numpy.zeros((3, 3, nao, nao))
    ipipb = 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):
            rhoa = ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask,
                                xctype)
            rhob = ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask,
                                xctype)
            vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3]
            vrho = vxc[0]
            u_u, u_d, d_d = fxc[0].T

            aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight * vrho[:, 0])
            rks_hess._d1d2_dot_(ipipa, mol, aow, ao[1:4], mask, ao_loc, False)
            aow = numpy.einsum('xpi,p->xpi', ao[1:4], weight * vrho[:, 1])
            rks_hess._d1d2_dot_(ipipb, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0a = numint._dot_ao_dm(mol, ao[0], dm0a, mask, shls_slice,
                                        ao_loc)
            ao_dm0b = numint._dot_ao_dm(mol, ao[0], dm0b, mask, shls_slice,
                                        ao_loc)
            for ia in range(mol.natm):
                p0, p1 = aoslices[ia][2:]
                # *2 for \nabla|ket> in rho1
                rho1a = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                     ao_dm0a[:, p0:p1]) * 2
                rho1b = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                     ao_dm0b[:, p0:p1]) * 2

                wv = u_u * rho1a + u_d * rho1b
                wv *= weight
                # aow ~ rho1 ~ d/dR1
                aow = numpy.einsum('pi,xp->xpi', ao[0], wv)
                rks_hess._d1d2_dot_(vmata[ia], mol, ao[1:4], aow, mask, ao_loc,
                                    False)

                wv = u_d * rho1a + d_d * rho1b
                wv *= weight
                aow = numpy.einsum('pi,xp->xpi', ao[0], wv)
                rks_hess._d1d2_dot_(vmatb[ia], mol, ao[1:4], aow, mask, ao_loc,
                                    False)
            ao_dm0a = ao_dm0b = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmata[ia, :, :, :, p0:p1] += ipipa[:, :, :, p0:p1]
            vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, :, p0:p1]

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

            wva, wvb = numint._uks_gga_wv0((rhoa, rhob), vxc, weight)
            aow = rks_grad._make_dR_dao_w(ao, wva)
            rks_hess._d1d2_dot_(ipipa, mol, aow, ao[1:4], mask, ao_loc, False)
            aow = rks_grad._make_dR_dao_w(ao, wvb)
            rks_hess._d1d2_dot_(ipipb, mol, aow, ao[1:4], mask, ao_loc, False)

            ao_dm0a = [
                numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            ao_dm0b = [
                numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wva = dR_rho1a = rks_hess._make_dR_rho1(
                    ao, ao_dm0a, ia, aoslices)
                wvb = dR_rho1b = rks_hess._make_dR_rho1(
                    ao, ao_dm0b, ia, aoslices)
                wva[0], wvb[0] = numint._uks_gga_wv1(
                    (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight)
                wva[1], wvb[1] = numint._uks_gga_wv1(
                    (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight)
                wva[2], wvb[2] = numint._uks_gga_wv1(
                    (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight)

                aow = rks_grad._make_dR_dao_w(ao, wva[0])
                rks_grad._d1_dot_(vmata[ia, 0], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wva[1])
                rks_grad._d1_dot_(vmata[ia, 1], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wva[2])
                rks_grad._d1_dot_(vmata[ia, 2], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)]
                rks_hess._d1d2_dot_(vmata[ia], mol, ao[1:4], aow, mask, ao_loc,
                                    False)

                aow = rks_grad._make_dR_dao_w(ao, wvb[0])
                rks_grad._d1_dot_(vmatb[ia, 0], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wvb[1])
                rks_grad._d1_dot_(vmatb[ia, 1], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wvb[2])
                rks_grad._d1_dot_(vmatb[ia, 2], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)]
                rks_hess._d1d2_dot_(vmatb[ia], mol, ao[1:4], aow, mask, ao_loc,
                                    False)
            ao_dm0a = ao_dm0b = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmata[ia, :, :, :, p0:p1] += ipipa[:, :, :, p0:p1]
            vmata[ia, :, :, :, p0:p1] += ipipa[:, :,
                                               p0:p1].transpose(1, 0, 3, 2)
            vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, :, p0:p1]
            vmatb[ia, :, :, :, p0:p1] += ipipb[:, :,
                                               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):
            rhoa = ni.eval_rho2(mol, ao[:10], mo_coeff[0], mo_occ[0], mask,
                                xctype)
            rhob = ni.eval_rho2(mol, ao[:10], mo_coeff[1], mo_occ[1], mask,
                                xctype)
            vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3]

            wva, wvb = numint._uks_mgga_wv0((rhoa, rhob), vxc, weight)
            aow = rks_grad._make_dR_dao_w(ao, wva)
            rks_hess._d1d2_dot_(ipipa, mol, aow, ao[1:4], mask, ao_loc, False)
            aow = rks_grad._make_dR_dao_w(ao, wvb)
            rks_hess._d1d2_dot_(ipipb, mol, aow, ao[1:4], mask, ao_loc, False)

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

            ao_dm0a = [
                numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            ao_dm0b = [
                numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wva = dR_rho1a = rks_hess._make_dR_rho1(
                    ao, ao_dm0a, ia, aoslices, xctype)
                wvb = dR_rho1b = rks_hess._make_dR_rho1(
                    ao, ao_dm0b, ia, aoslices, xctype)
                wva[0], wvb[0] = numint._uks_mgga_wv1(
                    (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight)
                wva[1], wvb[1] = numint._uks_mgga_wv1(
                    (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight)
                wva[2], wvb[2] = numint._uks_mgga_wv1(
                    (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight)

                aow = rks_grad._make_dR_dao_w(ao, wva[0])
                rks_grad._d1_dot_(vmata[ia, 0], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wva[1])
                rks_grad._d1_dot_(vmata[ia, 1], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wva[2])
                rks_grad._d1_dot_(vmata[ia, 2], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)]
                rks_hess._d1d2_dot_(vmata[ia], mol, ao[1:4], aow, mask, ao_loc,
                                    False)

                aow = rks_grad._make_dR_dao_w(ao, wvb[0])
                rks_grad._d1_dot_(vmatb[ia, 0], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wvb[1])
                rks_grad._d1_dot_(vmatb[ia, 1], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = rks_grad._make_dR_dao_w(ao, wvb[2])
                rks_grad._d1_dot_(vmatb[ia, 2], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)]
                rks_hess._d1d2_dot_(vmatb[ia], mol, ao[1:4], aow, mask, ao_loc,
                                    False)

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

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmata[ia, :, :, :, p0:p1] += ipipa[:, :, :, p0:p1]
            vmata[ia, :, :, :, p0:p1] += ipipa[:, :,
                                               p0:p1].transpose(1, 0, 3, 2)
            vmatb[ia, :, :, :, p0:p1] += ipipb[:, :, :, p0:p1]
            vmatb[ia, :, :, :, p0:p1] += ipipb[:, :,
                                               p0:p1].transpose(1, 0, 3, 2)

    return vmata, vmatb
Esempio n. 18
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[0].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()
    dm0a, dm0b = mf.make_rdm1(mo_coeff, mo_occ)

    vmata = numpy.zeros((mol.natm, 3, nao, nao))
    vmatb = numpy.zeros((mol.natm, 3, nao, nao))
    max_memory = max(2000, max_memory - (vmata.size + vmatb.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):
            rhoa = ni.eval_rho2(mol, ao[0], mo_coeff[0], mo_occ[0], mask,
                                xctype)
            rhob = ni.eval_rho2(mol, ao[0], mo_coeff[1], mo_occ[1], mask,
                                xctype)
            vxc, fxc = ni.eval_xc(mf.xc, (rhoa, rhob), 1, deriv=2)[1:3]
            vrho = vxc[0]
            u_u, u_d, d_d = fxc[0].T

            ao_dm0a = numint._dot_ao_dm(mol, ao[0], dm0a, mask, shls_slice,
                                        ao_loc)
            ao_dm0b = numint._dot_ao_dm(mol, ao[0], dm0b, mask, shls_slice,
                                        ao_loc)
            aow1a = numpy.einsum('xpi,p->xpi', ao[1:], weight * vrho[:, 0])
            aow1b = numpy.einsum('xpi,p->xpi', ao[1:], weight * vrho[:, 1])
            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
                rho1a = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                     ao_dm0a[:, p0:p1])
                rho1b = numpy.einsum('xpi,pi->xp', ao[1:, :, p0:p1],
                                     ao_dm0b[:, p0:p1])

                wv = u_u * rho1a + u_d * rho1b
                wv *= weight
                aow = numpy.einsum('pi,xp->xpi', ao[0], wv)
                aow[:, :, p0:p1] += aow1a[:, :, p0:p1]
                rks_grad._d1_dot_(vmata[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)

                wv = u_d * rho1a + d_d * rho1b
                wv *= weight
                aow = numpy.einsum('pi,xp->xpi', ao[0], wv)
                aow[:, :, p0:p1] += aow1b[:, :, p0:p1]
                rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
            ao_dm0a = ao_dm0b = aow = aow1a = aow1b = None

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

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

            wva, wvb = numint._uks_gga_wv0((rhoa, rhob), vxc, weight)
            rks_grad._gga_grad_sum_(vipa, mol, ao, wva, mask, ao_loc)
            rks_grad._gga_grad_sum_(vipb, mol, ao, wvb, mask, ao_loc)

            ao_dm0a = [
                numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            ao_dm0b = [
                numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wva = dR_rho1a = rks_hess._make_dR_rho1(
                    ao, ao_dm0a, ia, aoslices)
                wvb = dR_rho1b = rks_hess._make_dR_rho1(
                    ao, ao_dm0b, ia, aoslices)
                wva[0], wvb[0] = numint._uks_gga_wv1(
                    (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight)
                wva[1], wvb[1] = numint._uks_gga_wv1(
                    (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight)
                wva[2], wvb[2] = numint._uks_gga_wv1(
                    (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight)

                aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)]
                rks_grad._d1_dot_(vmata[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)]
                rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
            ao_dm0a = ao_dm0b = aow = None

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmata[ia, :, p0:p1] += vipa[:, p0:p1]
            vmatb[ia, :, p0:p1] += vipb[:, p0:p1]
            vmata[ia] = -vmata[ia] - vmata[ia].transpose(0, 2, 1)
            vmatb[ia] = -vmatb[ia] - vmatb[ia].transpose(0, 2, 1)

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

            wva, wvb = numint._uks_mgga_wv0((rhoa, rhob), vxc, weight)
            rks_grad._gga_grad_sum_(vipa, mol, ao, wva, mask, ao_loc)
            rks_grad._gga_grad_sum_(vipb, mol, ao, wvb, mask, ao_loc)

            rks_grad._tau_grad_dot_(vipa, mol, ao, wva[5] * 2, mask, ao_loc,
                                    True)
            rks_grad._tau_grad_dot_(vipb, mol, ao, wvb[5] * 2, mask, ao_loc,
                                    True)

            ao_dm0a = [
                numint._dot_ao_dm(mol, ao[i], dm0a, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            ao_dm0b = [
                numint._dot_ao_dm(mol, ao[i], dm0b, mask, shls_slice, ao_loc)
                for i in range(4)
            ]
            for ia in range(mol.natm):
                wva = dR_rho1a = rks_hess._make_dR_rho1(
                    ao, ao_dm0a, ia, aoslices, xctype)
                wvb = dR_rho1b = rks_hess._make_dR_rho1(
                    ao, ao_dm0b, ia, aoslices, xctype)
                wva[0], wvb[0] = numint._uks_mgga_wv1(
                    (rhoa, rhob), (dR_rho1a[0], dR_rho1b[0]), vxc, fxc, weight)
                wva[1], wvb[1] = numint._uks_mgga_wv1(
                    (rhoa, rhob), (dR_rho1a[1], dR_rho1b[1]), vxc, fxc, weight)
                wva[2], wvb[2] = numint._uks_mgga_wv1(
                    (rhoa, rhob), (dR_rho1a[2], dR_rho1b[2]), vxc, fxc, weight)

                aow = [numint._scale_ao(ao[:4], wva[i, :4]) for i in range(3)]
                rks_grad._d1_dot_(vmata[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)
                aow = [numint._scale_ao(ao[:4], wvb[i, :4]) for i in range(3)]
                rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[0], mask, ao_loc,
                                  True)

                for j in range(1, 4):
                    aow = [
                        numint._scale_ao(ao[j], wva[i, 5]) for i in range(3)
                    ]
                    rks_grad._d1_dot_(vmata[ia], mol, aow, ao[j], mask, ao_loc,
                                      True)
                    aow = [
                        numint._scale_ao(ao[j], wvb[i, 5]) for i in range(3)
                    ]
                    rks_grad._d1_dot_(vmatb[ia], mol, aow, ao[j], mask, ao_loc,
                                      True)

        for ia in range(mol.natm):
            p0, p1 = aoslices[ia][2:]
            vmata[ia, :, p0:p1] += vipa[:, p0:p1]
            vmatb[ia, :, p0:p1] += vipb[:, p0:p1]
            vmata[ia] = -vmata[ia] - vmata[ia].transpose(0, 2, 1)
            vmatb[ia] = -vmatb[ia] - vmatb[ia].transpose(0, 2, 1)

    return vmata, vmatb
Esempio n. 19
0
File: rks.py Progetto: pyscf/pyscf
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
Esempio n. 20
0
def _make_dR_dao_w(ao, wv):
    #:aow = numpy.einsum('npi,p->npi', ao[1:4], wv[0])
    aow = [
        numint._scale_ao(ao[1], wv[0]),  # dX nabla_x
        numint._scale_ao(ao[2], wv[0]),  # dX nabla_y
        numint._scale_ao(ao[3], wv[0]),  # dX nabla_z
    ]
    # XX, XY, XZ = 4, 5, 6
    # YX, YY, YZ = 5, 7, 8
    # ZX, ZY, ZZ = 6, 8, 9
    aow[0] += numint._scale_ao(ao[4], wv[1])  # dX nabla_x
    aow[0] += numint._scale_ao(ao[5], wv[2])  # dX nabla_y
    aow[0] += numint._scale_ao(ao[6], wv[3])  # dX nabla_z
    aow[1] += numint._scale_ao(ao[5], wv[1])  # dY nabla_x
    aow[1] += numint._scale_ao(ao[7], wv[2])  # dY nabla_y
    aow[1] += numint._scale_ao(ao[8], wv[3])  # dY nabla_z
    aow[2] += numint._scale_ao(ao[6], wv[1])  # dZ nabla_x
    aow[2] += numint._scale_ao(ao[8], wv[2])  # dZ nabla_y
    aow[2] += numint._scale_ao(ao[9], wv[3])  # dZ nabla_z
    return aow
Esempio n. 21
0
File: rks.py Progetto: pyscf/pyscf
 def contract_(mat, ao, aoidx, wv, mask):
     aow = numint._scale_ao(ao[aoidx[0]], wv[1])
     aow += numint._scale_ao(ao[aoidx[1]], wv[2])
     aow += numint._scale_ao(ao[aoidx[2]], wv[3])
     mat += numint._dot_ao_ao(mol, aow, ao[0], mask, shls_slice, ao_loc)
Esempio n. 22
0
File: rks.py Progetto: pyscf/pyscf
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
Esempio n. 23
0
File: rks.py Progetto: pyscf/pyscf
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, xctype)
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            aow = numint._scale_ao(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 = numint._scale_ao(ao[aoidx[0]], wv[1])
            aow += numint._scale_ao(ao[aoidx[1]], wv[2])
            aow += numint._scale_ao(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, xctype)
            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[:4])
            aow = numint._scale_ao(ao[:4], wv[:4])
            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':

        def contract_(mat, ao, aoidx, wv, mask):
            aow = numint._scale_ao(ao[aoidx[0]], wv[1])
            aow += numint._scale_ao(ao[aoidx[1]], wv[2])
            aow += numint._scale_ao(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[:10], mo_coeff, mo_occ, mask, xctype)
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]

            wv = numint._rks_mgga_wv0(rho, vxc, weight)
            # *2 because v.T is not applied. Only v is computed in the next _dot_ao_ao
            wv[0] *= 2
            wv[5] *= 2
            #:aow = numpy.einsum('npi,np->pi', ao[:4], wv[:4])
            aow = numint._scale_ao(ao[:4], wv[:4])
            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)

            aow = [numint._scale_ao(ao[i], wv[5]) for i in range(1, 4)]
            for i, j in enumerate([XXX, XXY, XXZ, XYY, XYZ, XZZ]):
                vmat[i] += numint._dot_ao_ao(mol, ao[j], aow[0], mask,
                                             shls_slice, ao_loc)
            for i, j in enumerate([XXY, XYY, XYZ, YYY, YYZ, YZZ]):
                vmat[i] += numint._dot_ao_ao(mol, ao[j], aow[1], mask,
                                             shls_slice, ao_loc)
            for i, j in enumerate([XXZ, XYZ, XZZ, YYZ, YZZ, ZZZ]):
                vmat[i] += numint._dot_ao_ao(mol, ao[j], aow[2], mask,
                                             shls_slice, ao_loc)

    vmat = vmat[[0, 1, 2, 1, 3, 4, 2, 4, 5]]
    return vmat.reshape(3, 3, nao, nao)
Esempio n. 24
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)):
            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, xctype)
            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)
            aow = numint._scale_ao(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)):
            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, xctype)
            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 = wv = None

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

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

            vtmp = numpy.zeros((3, nao, nao))
            wv = numint._rks_mgga_wv0(rho, vxc, weight)
            _gga_grad_sum_(vtmp, mol, ao, wv, mask, ao_loc)
            _tau_grad_dot_(vtmp, mol, ao, wv[5] * 2, mask, ao_loc, True)
            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 = wv = None

    # - sign because nabla_X = -nabla_x
    return excsum, -vmat
Esempio n. 25
0
File: uks.py Progetto: pyscf/pyscf
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((2, 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_a = make_rho(0, ao[0], mask, xctype)
            rho_b = make_rho(1, ao[0], mask, xctype)
            vxc = ni.eval_xc(xc_code, (rho_a, rho_b),
                             1,
                             relativity,
                             1,
                             verbose=verbose)[1]
            vrho = vxc[0]
            #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,0])
            aow = numint._scale_ao(ao[0], weight * vrho[:, 0])
            rks_grad._d1_dot_(vmat[0], mol, ao[1:4], aow, mask, ao_loc, True)
            #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,1])
            aow = numint._scale_ao(ao[0], weight * vrho[:, 1])
            rks_grad._d1_dot_(vmat[1], 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):
            rho_a = make_rho(0, ao[:4], mask, xctype)
            rho_b = make_rho(1, ao[:4], mask, xctype)
            vxc = ni.eval_xc(xc_code, (rho_a, rho_b),
                             1,
                             relativity,
                             1,
                             verbose=verbose)[1]
            wva, wvb = numint._uks_gga_wv0((rho_a, rho_b), vxc, weight)
            rks_grad._gga_grad_sum_(vmat[0], mol, ao, wva, mask, ao_loc)
            rks_grad._gga_grad_sum_(vmat[1], mol, ao, wvb, 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):
            rho_a = make_rho(0, ao[:10], mask, xctype)
            rho_b = make_rho(1, ao[:10], mask, xctype)
            vxc = ni.eval_xc(xc_code, (rho_a, rho_b),
                             1,
                             relativity,
                             1,
                             verbose=verbose)[1]
            wva, wvb = numint._uks_mgga_wv0((rho_a, rho_b), vxc, weight)
            rks_grad._gga_grad_sum_(vmat[0], mol, ao, wva, mask, ao_loc)
            rks_grad._gga_grad_sum_(vmat[1], mol, ao, wvb, mask, ao_loc)

            # *2 because wv[5] is scaled by 0.5 in _uks_mgga_wv0
            rks_grad._tau_grad_dot_(vmat[0], mol, ao, wva[5] * 2, mask, ao_loc,
                                    True)
            rks_grad._tau_grad_dot_(vmat[1], mol, ao, wvb[5] * 2, mask, ao_loc,
                                    True)

    exc = numpy.zeros((mol.natm, 3))
    # - sign because nabla_X = -nabla_x
    return exc, -vmat
Esempio n. 26
0
 def lda_sum_(vmat, ao, wv, mask):
     aow = numint._scale_ao(ao[0], wv)
     for k in range(4):
         vmat[k] += numint._dot_ao_ao(mol, ao[k], aow, mask,
                                      shls_slice, ao_loc)
Esempio n. 27
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
Esempio n. 28
0
 def gga_sum_(vmat, ao, wv, mask):
     aow = numint._scale_ao(ao[:4], wv[:4])
     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)
Esempio n. 29
0
File: uks.py Progetto: pyscf/pyscf
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()
    aoslices = mol.aoslice_by_atom()

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

            vtmp = numpy.zeros((3, nao, nao))
            #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,0])
            aow = numint._scale_ao(ao[0], weight * vrho[:, 0])
            rks_grad._d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True)
            vmat[0] += vtmp
            excsum += numpy.einsum('r,r,nxr->nx', exc, rho_a + rho_b, weight1)
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[0]) * 2

            vtmp = numpy.zeros((3, nao, nao))
            #:aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho[:,1])
            aow = numint._scale_ao(ao[0], weight * vrho[:, 1])
            rks_grad._d1_dot_(vtmp, mol, ao[1:4], aow, mask, ao_loc, True)
            vmat[1] += vtmp
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[1]) * 2

    elif xctype == 'GGA':
        ao_deriv = 2
        for atm_id, (coords, weight, weight1) \
                in enumerate(rks_grad.grids_response_cc(grids)):
            sh0, sh1 = aoslices[atm_id][:2]
            mask = gen_grid.make_mask(mol, coords)
            ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask)
            rho_a = make_rho(0, ao[:4], mask, xctype)
            rho_b = make_rho(1, ao[:4], mask, xctype)
            exc, vxc = ni.eval_xc(xc_code, (rho_a, rho_b),
                                  1,
                                  relativity,
                                  1,
                                  verbose=verbose)[:2]
            wva, wvb = numint._uks_gga_wv0((rho_a, rho_b), vxc, weight)

            vtmp = numpy.zeros((3, nao, nao))
            rks_grad._gga_grad_sum_(vtmp, mol, ao, wva, mask, ao_loc)
            vmat[0] += vtmp
            excsum += numpy.einsum('r,r,nxr->nx', exc, rho_a[0] + rho_b[0],
                                   weight1)
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[0]) * 2

            vtmp = numpy.zeros((3, nao, nao))
            rks_grad._gga_grad_sum_(vtmp, mol, ao, wvb, mask, ao_loc)
            vmat[1] += vtmp
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[1]) * 2

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

    elif xctype == 'MGGA':
        ao_deriv = 2
        for atm_id, (coords, weight, weight1) \
                in enumerate(rks_grad.grids_response_cc(grids)):
            sh0, sh1 = aoslices[atm_id][:2]
            mask = gen_grid.make_mask(mol, coords)
            ao = ni.eval_ao(mol, coords, deriv=ao_deriv, non0tab=mask)
            rho_a = make_rho(0, ao[:10], mask, xctype)
            rho_b = make_rho(1, ao[:10], mask, xctype)
            exc, vxc = ni.eval_xc(xc_code, (rho_a, rho_b),
                                  1,
                                  relativity,
                                  1,
                                  verbose=verbose)[:2]
            wva, wvb = numint._uks_mgga_wv0((rho_a, rho_b), vxc, weight)

            vtmp = numpy.zeros((3, nao, nao))
            rks_grad._gga_grad_sum_(vtmp, mol, ao, wva, mask, ao_loc)
            # *2 because wv[5] is scaled by 0.5 in _uks_mgga_wv0
            rks_grad._tau_grad_dot_(vtmp, mol, ao, wva[5] * 2, mask, ao_loc,
                                    True)
            vmat[0] += vtmp
            excsum += numpy.einsum('r,r,nxr->nx', exc, rho_a[0] + rho_b[0],
                                   weight1)
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[0]) * 2

            vtmp = numpy.zeros((3, nao, nao))
            rks_grad._gga_grad_sum_(vtmp, mol, ao, wvb, mask, ao_loc)
            rks_grad._tau_grad_dot_(vtmp, mol, ao, wvb[5] * 2, mask, ao_loc,
                                    True)
            vmat[1] += vtmp
            excsum[atm_id] += numpy.einsum('xij,ji->x', vtmp, dms[1]) * 2

    # - sign because nabla_X = -nabla_x
    return excsum, -vmat