Esempio n. 1
0
def get_hcore(cell, kpts):
    '''Part of the nuclear gradients of core Hamiltonian'''
    h1 = np.asarray(cell.pbc_intor('int1e_ipkin', kpts=kpts))
    dtype = h1.dtype
    if cell._pseudo:
        SI = cell.get_SI()
        nao = cell.nao_nr()
        Gv = cell.Gv
        natom = cell.natm
        coords = cell.get_uniform_grids()
        ngrids, nkpts = len(coords), len(kpts)
        vlocG = get_vlocG(cell)
        vpplocG = -np.einsum('ij,ij->j', SI, vlocG)
        vpplocG[0] = np.sum(get_alphas(cell))
        vpplocR = tools.ifft(vpplocG, cell.mesh).real
        fakemol = _make_fakemol()
        ptr = mole.PTR_ENV_START
        for kn, kpt in enumerate(kpts):
            aos = eval_ao_kpts(cell, coords, kpt, deriv=1)[0]
            vloc = np.einsum('agi,g,gj->aij', aos[1:].conj(), vpplocR, aos[0])
            expir = np.exp(-1j * np.dot(coords, kpt))
            aokG = np.asarray([
                tools.fftk(np.asarray(ao.T, order='C'), cell.mesh, expir).T
                for ao in aos
            ])
            Gk = Gv + kpt
            G_rad = lib.norm(Gk, axis=1)
            vnl = np.zeros(vloc.shape, dtype=np.complex128)
            for ia in range(natom):
                symb = cell.atom_symbol(ia)
                if symb not in cell._pseudo:
                    continue
                pp = cell._pseudo[symb]
                for l, proj in enumerate(pp[5:]):
                    rl, nl, hl = proj
                    if nl > 0:
                        hl = np.asarray(hl)
                        fakemol._bas[0, mole.ANG_OF] = l
                        fakemol._env[ptr + 3] = .5 * rl**2
                        fakemol._env[ptr + 4] = rl**(l + 1.5) * np.pi**1.25
                        pYlm_part = fakemol.eval_gto('GTOval', Gk)
                        pYlm = np.empty((nl, l * 2 + 1, ngrids))
                        for k in range(nl):
                            qkl = _qli(G_rad * rl, l, k)
                            pYlm[k] = pYlm_part.T * qkl
                        SPG_lmi = np.einsum('g,nmg->nmg', SI[ia].conj(), pYlm)
                        SPG_lm_aoG = np.einsum('nmg,agp->anmp', SPG_lmi, aokG)
                        tmp = np.einsum('ij,ajmp->aimp', hl, SPG_lm_aoG[1:])
                        vnl += np.einsum('aimp,imq->apq', tmp.conj(),
                                         SPG_lm_aoG[0])
            vnl *= (1. / ngrids**2)
            if dtype == np.float64:
                h1[kn, :] += vloc.real + vnl.real
            else:
                h1[kn, :] += vloc + vnl
    else:
        raise NotImplementedError
    return h1
Esempio n. 2
0
    def hcore_deriv(atm_id):
        shl0, shl1, p0, p1 = aoslices[atm_id]
        symb = cell.atom_symbol(atm_id)
        fakemol = _make_fakemol()
        vloc_g = 1j * np.einsum('ga,g->ag', Gv, SI[atm_id] * vlocG[atm_id])
        nkpts, nao = h1.shape[0], h1.shape[2]
        hcore = np.zeros([3, nkpts, nao, nao], dtype=h1.dtype)
        for kn, kpt in enumerate(kpts):

            ao = eval_ao_kpts(cell, coords, kpt)[0]
            rho = np.einsum('gi,gj->gij', ao.conj(), ao)
            for ax in range(3):
                vloc_R = tools.ifft(vloc_g[ax], mesh).real
                vloc = np.einsum('gij,g->ij', rho, vloc_R)
                hcore[ax, kn] += vloc
            rho = None
            aokG = tools.fftk(np.asarray(ao.T, order='C'), mesh,
                              np.exp(-1j * np.dot(coords, kpt))).T
            ao = None
            Gk = Gv + kpt
            G_rad = lib.norm(Gk, axis=1)
            if symb not in cell._pseudo: continue
            pp = cell._pseudo[symb]
            for l, proj in enumerate(pp[5:]):
                rl, nl, hl = proj
                if nl > 0:
                    hl = np.asarray(hl)
                    fakemol._bas[0, mole.ANG_OF] = l
                    fakemol._env[ptr + 3] = .5 * rl**2
                    fakemol._env[ptr + 4] = rl**(l + 1.5) * np.pi**1.25
                    pYlm_part = fakemol.eval_gto('GTOval', Gk)
                    pYlm = np.empty((nl, l * 2 + 1, ngrids))
                    for k in range(nl):
                        qkl = _qli(G_rad * rl, l, k)
                        pYlm[k] = pYlm_part.T * qkl
                    SPG_lmi = np.einsum('g,nmg->nmg', SI[atm_id].conj(), pYlm)
                    SPG_lm_aoG = np.einsum('nmg,gp->nmp', SPG_lmi, aokG)
                    SPG_lmi_G = 1j * np.einsum('nmg, ga->anmg', SPG_lmi, Gv)
                    SPG_lm_G_aoG = np.einsum('anmg, gp->anmp', SPG_lmi_G, aokG)
                    tmp_1 = np.einsum('ij,ajmp->aimp', hl, SPG_lm_G_aoG)
                    tmp_2 = np.einsum('ij,jmp->imp', hl, SPG_lm_aoG)
                    vppnl = np.einsum(
                        'imp,aimq->apq', SPG_lm_aoG.conj(), tmp_1) + np.einsum(
                            'aimp,imq->apq', SPG_lm_G_aoG.conj(), tmp_2)
                    vppnl *= (1. / ngrids**2)
                    if dtype == np.float64:
                        hcore[:, kn] += vppnl.real
                    else:
                        hcore[:, kn] += vppnl
            hcore[:, kn, p0:p1] -= h1[kn, :, p0:p1]
            hcore[:, kn, :, p0:p1] -= h1[kn, :, p0:p1].transpose(0, 2,
                                                                 1).conj()
        return hcore