Example #1
0
        def get_phi1(pcmojb):
            pcmobj.grids.build()
            mol = pcmobj.mol
            natm = mol.natm
            lmax = pcmobj.lmax

            r_vdw = pcmobj.get_atomic_radii()
            coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
            ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))

            fi = ddcosmo.make_fi(pcmobj, r_vdw)
            ui = 1 - fi
            ui[ui<0] = 0
            nexposed = numpy.count_nonzero(ui==1)
            nbury = numpy.count_nonzero(ui==0)
            on_shell = numpy.count_nonzero(ui>0) - nexposed

            nlm = (lmax+1)**2
            Lmat = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)
            Lmat = Lmat.reshape(natm*nlm,-1)

            cached_pol = ddcosmo.cache_fake_multipoles(pcmobj.grids, r_vdw, lmax)

            phi = ddcosmo.make_phi(pcmobj, dm, r_vdw, ui)
            L_X = numpy.linalg.solve(Lmat, phi.ravel()).reshape(natm,-1)
            psi, vmat, L_S = \
                    ddcosmo.make_psi_vmat(pcmobj, dm, r_vdw, ui, pcmobj.grids, ylm_1sph,
                                          cached_pol, L_X, Lmat)
            phi1 = ddcosmo_grad.make_phi1(pcmobj, dm, r_vdw, ui)
            phi1 = numpy.einsum('izjx,jx->iz', phi1, L_S)
            return L_S, phi, phi1
Example #2
0
    def test_psi_vmat(self):
        pcm = ddcosmo.DDCOSMO(mol)
        pcm.lmax = 2
        r_vdw = ddcosmo.get_atomic_radii(pcm)
        fi = ddcosmo.make_fi(pcm, r_vdw)
        ui = 1 - fi
        ui[ui<0] = 0
        grids = dft.gen_grid.Grids(mol).build()
        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcm.lebedev_order)
        ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcm.lmax, True))
        cached_pol = ddcosmo.cache_fake_multipoles(grids, r_vdw, pcm.lmax)

        numpy.random.seed(1)
        nao = mol.nao_nr()
        dm = numpy.random.random((nao,nao))
        dm = dm + dm.T
        natm = mol.natm
        nlm = (pcm.lmax+1)**2
        LX = numpy.random.random((natm,nlm))

        L = ddcosmo.make_L(pcm, r_vdw, ylm_1sph, fi)
        psi, vmat = ddcosmo.make_psi_vmat(pcm, dm, r_vdw, ui, grids,
                                          ylm_1sph, cached_pol, LX, L)[:2]
        psi_ref = make_psi(pcm.mol, dm, r_vdw, pcm.lmax)
        self.assertAlmostEqual(abs(psi_ref - psi).max(), 0, 12)

        LS = numpy.linalg.solve(L.T.reshape(natm*nlm,-1),
                                psi_ref.ravel()).reshape(natm,nlm)
        vmat_ref = make_vmat(pcm, r_vdw, pcm.lebedev_order, pcm.lmax, LX, LS)
        self.assertAlmostEqual(abs(vmat_ref - vmat).max(), 0, 12)
Example #3
0
    def test_L_x(self):
        pcm = ddcosmo.DDCOSMO(mol)
        r_vdw = ddcosmo.get_atomic_radii(pcm)
        n = mol.natm * (pcm.lmax+1)**2
        Lref = make_L(pcm, r_vdw, pcm.lebedev_order, pcm.lmax, pcm.eta).reshape(n,n)

        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcm.lebedev_order)
        ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcm.lmax, True))
        fi = ddcosmo.make_fi(pcm, r_vdw)
        L = ddcosmo.make_L(pcm, r_vdw, ylm_1sph, fi).reshape(n,n)

        numpy.random.seed(1)
        x = numpy.random.random(n)
        self.assertTrue(abs(Lref.dot(n)-L.dot(n)).max() < 1e-12)
Example #4
0
def make_L1(pcmobj, r_vdw, ylm_1sph, fi):
    # See JCTC, 9, 3637, Eq (18)
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    eta = pcmobj.eta
    nlm = (lmax+1)**2

    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    ngrid_1sph = weights_1sph.size
    atom_coords = mol.atom_coords()
    ylm_1sph = ylm_1sph.reshape(nlm,ngrid_1sph)

    Lmat = numpy.zeros((natm,3,natm,nlm,natm,nlm))
    fi1 = make_fi1(pcmobj, pcmobj.get_atomic_radii())

    for ja in range(natm):
        part_weights = weights_1sph.copy()
        part_weights[fi[ja]>1] /= fi[ja,fi[ja]>1]

        part_weights1 = numpy.zeros((natm,3,ngrid_1sph))
        tmp = part_weights[fi[ja]>1] / fi[ja,fi[ja]>1]
        part_weights1[:,:,fi[ja]>1] = -tmp * fi1[:,:,ja,fi[ja]>1]

        for ka in ddcosmo.atoms_with_vdw_overlap(ja, atom_coords, r_vdw):
            vjk = r_vdw[ja] * coords_1sph + atom_coords[ja] - atom_coords[ka]
            rv = lib.norm(vjk, axis=1)
            tjk = rv / r_vdw[ka]
            wjk0 = pcmobj.regularize_xt(tjk, eta, r_vdw[ka])
            wjk1 = regularize_xt1(tjk, eta*r_vdw[ka])
            sjk = vjk.T / rv
            wjk1 = 1./r_vdw[ka] * wjk1 * sjk

            wjk01 = wjk0 * part_weights1
            wjk0 *= part_weights
            wjk1 *= part_weights

            pol0 = sph.multipoles(vjk, lmax)
            pol1 = multipoles1(vjk, lmax)
            p1 = 0
            for l in range(lmax+1):
                fac = 4*numpy.pi/(l*2+1) / r_vdw[ka]**(l+1)
                p0, p1 = p1, p1 + (l*2+1)
                a = numpy.einsum('xn,zn,mn->zxm', ylm_1sph, wjk1, pol0[l])
                a+= numpy.einsum('xn,n,zmn->zxm', ylm_1sph, wjk0, pol1[l])
                Lmat[ja,:,ja,:,ka,p0:p1] += -fac * a
                Lmat[ka,:,ja,:,ka,p0:p1] -= -fac * a
                a = numpy.einsum('xn,azn,mn->azxm', ylm_1sph, wjk01, pol0[l])
                Lmat[:,:,ja,:,ka,p0:p1] += -fac * a
    return Lmat
Example #5
0
    def test_L1(self):
        pcmobj = ddcosmo.DDCOSMO(mol0)
        r_vdw = pcmobj.get_atomic_radii()
        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
        ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcmobj.lmax, True))

        fi = ddcosmo.make_fi(pcmobj, r_vdw)
        L1 = ddcosmo_grad.make_L1(pcmobj, r_vdw, ylm_1sph, fi)

        pcmobj = ddcosmo.DDCOSMO(mol1)
        fi = ddcosmo.make_fi(pcmobj, r_vdw)
        L_1 = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)

        pcmobj = ddcosmo.DDCOSMO(mol2)
        fi = ddcosmo.make_fi(pcmobj, r_vdw)
        L_2 = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)
        self.assertAlmostEqual(abs((L_2-L_1)/dx - L1[0,2]).max(), 0, 7)
Example #6
0
def gen_ddpcm_solver(pcmobj, verbose=None):
    mol = pcmobj.mol
    if pcmobj.grids.coords is None:
        pcmobj.grids.build(with_non0tab=True)

    natm = mol.natm
    lmax = pcmobj.lmax

    r_vdw = ddcosmo.get_atomic_radii(pcmobj)
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))

    fi = ddcosmo.make_fi(pcmobj, r_vdw)
    ui = 1 - fi
    ui[ui<0] = 0
    nexposed = numpy.count_nonzero(ui==1)
    nbury = numpy.count_nonzero(ui==0)
    on_shell = numpy.count_nonzero(ui>0) - nexposed
    logger.debug(pcmobj, 'Num points exposed %d', nexposed)
    logger.debug(pcmobj, 'Num points buried %d', nbury)
    logger.debug(pcmobj, 'Num points on shell %d', on_shell)

    nlm = (lmax+1)**2
    Lmat = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)
    Lmat = Lmat.reshape(natm*nlm,-1)

    Amat = make_A(pcmobj, r_vdw, ylm_1sph, ui).reshape(natm*nlm,-1)
    fac = 2*numpy.pi * (pcmobj.eps+1) / (pcmobj.eps-1)
    A_diele = Amat + fac * numpy.eye(natm*nlm)
    A_inf = Amat + 2*numpy.pi * numpy.eye(natm*nlm)

    cached_pol = ddcosmo.cache_fake_multipoles(pcmobj.grids, r_vdw, lmax)

    def gen_vind(dm):
        phi = ddcosmo.make_phi(pcmobj, dm, r_vdw, ui)
        phi = numpy.linalg.solve(A_diele, A_inf.dot(phi.ravel()))

        L_X = numpy.linalg.solve(Lmat, phi.ravel()).reshape(natm,-1)
        psi, vmat = ddcosmo.make_psi_vmat(pcmobj, dm, r_vdw, ui, pcmobj.grids,
                                          ylm_1sph, cached_pol, L_X, Lmat)[:2]
        dielectric = pcmobj.eps
        f_epsilon = (dielectric-1.)/dielectric
        epcm = .5 * f_epsilon * numpy.einsum('jx,jx', psi, L_X)
        return epcm, .5 * f_epsilon * vmat
    return gen_vind
Example #7
0
def make_v_phi(mol, dm, r_vdw, lebedev_order):
    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()
    natm = mol.natm
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(lebedev_order)

    pmol = mol.copy()
    v_phi = []
    for ia in range(natm):
        for i, c in enumerate(coords_1sph):
            r = atom_coords[ia] + r_vdw[ia] * c
            dr = atom_coords - r
            v_nuc = (atom_charges / numpy.linalg.norm(dr, axis=1)).sum()
            pmol.set_rinv_orig(r)
            v_e = numpy.einsum('ij,ji', pmol.intor('int1e_rinv'), dm)
            v_phi.append(v_nuc - v_e)
    v_phi = numpy.array(v_phi).reshape(natm, -1)
    return v_phi
Example #8
0
def make_v_phi(mol, dm, r_vdw, lebedev_order):
    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()
    natm = mol.natm
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(lebedev_order)

    pmol = mol.copy()
    v_phi = []
    for ia in range(natm):
        for i,c in enumerate(coords_1sph):
            r = atom_coords[ia] + r_vdw[ia] * c
            dr = atom_coords - r
            v_nuc = (atom_charges / numpy.linalg.norm(dr, axis=1)).sum()
            pmol.set_rinv_orig(r)
            v_e = numpy.einsum('ij,ji', pmol.intor('int1e_rinv'), dm)
            v_phi.append(v_nuc - v_e)
    v_phi = numpy.array(v_phi).reshape(natm,-1)
    return v_phi
Example #9
0
    def test_phi(self):
        pcm = ddcosmo.DDCOSMO(mol)
        r_vdw = ddcosmo.get_atomic_radii(pcm)
        fi = ddcosmo.make_fi(pcm, r_vdw)
        ui = 1 - fi
        ui[ui<0] = 0

        numpy.random.seed(1)
        nao = mol.nao_nr()
        dm = numpy.random.random((nao,nao))
        dm = dm + dm.T

        v_phi = make_v_phi(mol, dm, r_vdw, pcm.lebedev_order)
        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcm.lebedev_order)
        ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcm.lmax, True))
        phi = -numpy.einsum('n,xn,jn,jn->jx', weights_1sph, ylm_1sph, ui, v_phi)
        phi1 = ddcosmo.make_phi(pcm, dm, r_vdw, ui)
        self.assertTrue(abs(phi - phi1).max() < 1e-12)
Example #10
0
def kernel(pcmobj, dm, verbose=None):
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    if pcmobj.grids.coords is None:
        pcmobj.grids.build(with_non0tab=True)

    if not (isinstance(dm, numpy.ndarray) and dm.ndim == 2):
        # UHF density matrix
        dm = dm[0] + dm[1]

    r_vdw = ddcosmo.get_atomic_radii(pcmobj)
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))

    fi = ddcosmo.make_fi(pcmobj, r_vdw)
    ui = 1 - fi
    ui[ui < 0] = 0

    cached_pol = ddcosmo.cache_fake_multipoles(pcmobj.grids, r_vdw, lmax)

    nlm = (lmax + 1)**2
    L0 = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)
    L0 = L0.reshape(natm * nlm, -1)
    L1 = make_L1(pcmobj, r_vdw, ylm_1sph, fi)

    phi0 = ddcosmo.make_phi(pcmobj, dm, r_vdw, ui)
    phi1 = make_phi1(pcmobj, dm, r_vdw, ui)
    L0_X = numpy.linalg.solve(L0, phi0.ravel()).reshape(natm, -1)
    psi0, vmat, L0_S = \
            ddcosmo.make_psi_vmat(pcmobj, dm, r_vdw, ui, pcmobj.grids, ylm_1sph,
                                  cached_pol, L0_X, L0)
    e_psi1 = make_e_psi1(pcmobj, dm, r_vdw, ui, pcmobj.grids, ylm_1sph,
                         cached_pol, L0_X, L0)
    dielectric = pcmobj.eps
    if dielectric > 0:
        f_epsilon = (dielectric - 1.) / dielectric
    else:
        f_epsilon = 1
    de = .5 * f_epsilon * e_psi1
    de += .5 * f_epsilon * numpy.einsum('jx,azjx->az', L0_S, phi1)
    de -= .5 * f_epsilon * numpy.einsum('aziljm,il,jm->az', L1, L0_S, L0_X)
    return de
Example #11
0
def kernel(pcmobj, dm, verbose=None):
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    if pcmobj.grids.coords is None:
        pcmobj.grids.build(with_non0tab=True)

    if not (isinstance(dm, numpy.ndarray) and dm.ndim == 2):
        # UHF density matrix
        dm = dm[0] + dm[1]

    r_vdw = ddcosmo.get_atomic_radii(pcmobj)
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))

    fi = ddcosmo.make_fi(pcmobj, r_vdw)
    ui = 1 - fi
    ui[ui<0] = 0

    cached_pol = ddcosmo.cache_fake_multipoles(pcmobj.grids, r_vdw, lmax)

    nlm = (lmax+1)**2
    L0 = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)
    L0 = L0.reshape(natm*nlm,-1)
    L1 = make_L1(pcmobj, r_vdw, ylm_1sph, fi)

    phi0 = ddcosmo.make_phi(pcmobj, dm, r_vdw, ui)
    phi1 = make_phi1(pcmobj, dm, r_vdw, ui)
    L0_X = numpy.linalg.solve(L0, phi0.ravel()).reshape(natm,-1)
    psi0, vmat, L0_S = \
            ddcosmo.make_psi_vmat(pcmobj, dm, r_vdw, ui, pcmobj.grids, ylm_1sph,
                                  cached_pol, L0_X, L0)
    e_psi1 = make_e_psi1(pcmobj, dm, r_vdw, ui, pcmobj.grids, ylm_1sph,
                         cached_pol, L0_X, L0)
    dielectric = pcmobj.eps
    if dielectric > 0:
        f_epsilon = (dielectric-1.)/dielectric
    else:
        f_epsilon = 1
    de = .5 * f_epsilon * e_psi1
    de+= .5 * f_epsilon * numpy.einsum('jx,azjx->az', L0_S, phi1)
    de-= .5 * f_epsilon * numpy.einsum('aziljm,il,jm->az', L1, L0_S, L0_X)
    return de
Example #12
0
 def getB(mol):
     pcm = ddcosmo.DDCOSMO(mol)
     pcm.lmax = 2
     pcm.eps = 0
     natm = mol.natm
     nao = mol.nao
     nlm = (pcm.lmax + 1)**2
     r_vdw = ddcosmo.get_atomic_radii(pcm)
     fi = ddcosmo.make_fi(pcm, r_vdw)
     ui = 1 - fi
     ui[ui < 0] = 0
     pcm.grids = grids = dft.gen_grid.Grids(mol).run(level=0)
     coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
         pcm.lebedev_order)
     ylm_1sph = numpy.vstack(
         sph.real_sph_vec(coords_1sph, pcm.lmax, True))
     cached_pol = ddcosmo.cache_fake_multipoles(grids, r_vdw, pcm.lmax)
     L = ddcosmo.make_L(pcm, r_vdw, ylm_1sph, fi)
     return make_B(pcm, r_vdw, ui, ylm_1sph, cached_pol, L)
Example #13
0
    def test_L1(self):
        pcmobj = ddcosmo.DDCOSMO(mol0)
        r_vdw = pcmobj.get_atomic_radii()
        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
            pcmobj.lebedev_order)
        ylm_1sph = numpy.vstack(
            sph.real_sph_vec(coords_1sph, pcmobj.lmax, True))

        fi = ddcosmo.make_fi(pcmobj, r_vdw)
        L1 = ddcosmo_grad.make_L1(pcmobj, r_vdw, ylm_1sph, fi)

        pcmobj = ddcosmo.DDCOSMO(mol1)
        fi = ddcosmo.make_fi(pcmobj, r_vdw)
        L_1 = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)

        pcmobj = ddcosmo.DDCOSMO(mol2)
        fi = ddcosmo.make_fi(pcmobj, r_vdw)
        L_2 = ddcosmo.make_L(pcmobj, r_vdw, ylm_1sph, fi)
        self.assertAlmostEqual(abs((L_2 - L_1) / dx - L1[0, 2]).max(), 0, 7)
Example #14
0
    def build(self):
        if self.grids.coords is None:
            self.grids.build(with_non0tab=True)

        mol = self.mol
        natm = mol.natm
        lmax = self.lmax

        r_vdw = ddcosmo.get_atomic_radii(self)
        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
            self.lebedev_order)
        ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))

        fi = ddcosmo.make_fi(self, r_vdw)
        ui = 1 - fi
        ui[ui < 0] = 0
        nexposed = numpy.count_nonzero(ui == 1)
        nbury = numpy.count_nonzero(ui == 0)
        on_shell = numpy.count_nonzero(ui > 0) - nexposed
        logger.debug(self, 'Num points exposed %d', nexposed)
        logger.debug(self, 'Num points buried %d', nbury)
        logger.debug(self, 'Num points on shell %d', on_shell)

        nlm = (lmax + 1)**2
        Lmat = ddcosmo.make_L(self, r_vdw, ylm_1sph, fi)
        Lmat = Lmat.reshape(natm * nlm, -1)

        Amat = make_A(self, r_vdw, ylm_1sph, ui).reshape(natm * nlm, -1)
        fac = 2 * numpy.pi * (self.eps + 1) / (self.eps - 1)
        A_diele = Amat + fac * numpy.eye(natm * nlm)
        A_inf = Amat + 2 * numpy.pi * numpy.eye(natm * nlm)

        cached_pol = ddcosmo.cache_fake_multipoles(self.grids, r_vdw, lmax)

        self._intermediates = {
            'r_vdw': r_vdw,
            'ylm_1sph': ylm_1sph,
            'ui': ui,
            'Lmat': Lmat,
            'A_diele': A_diele,
            'A_inf': A_inf,
            'cached_pol': cached_pol,
        }
Example #15
0
    def test_phi(self):
        pcm = ddcosmo.DDCOSMO(mol)
        r_vdw = ddcosmo.get_atomic_radii(pcm)
        fi = ddcosmo.make_fi(pcm, r_vdw)
        ui = 1 - fi
        ui[ui < 0] = 0

        numpy.random.seed(1)
        nao = mol.nao_nr()
        dm = numpy.random.random((nao, nao))
        dm = dm + dm.T

        v_phi = make_v_phi(mol, dm, r_vdw, pcm.lebedev_order)
        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
            pcm.lebedev_order)
        ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcm.lmax, True))
        phi = -numpy.einsum('n,xn,jn,jn->jx', weights_1sph, ylm_1sph, ui,
                            v_phi)
        phi1 = ddcosmo.make_phi(pcm, dm, r_vdw, ui, ylm_1sph)
        self.assertTrue(abs(phi - phi1).max() < 1e-12)
Example #16
0
def make_L(pcmobj, r_vdw, lebedev_order, lmax, eta=0.1):
    mol = pcmobj.mol
    natm = mol.natm
    nlm = (lmax + 1)**2

    leb_coords, leb_weights = ddcosmo.make_grids_one_sphere(lebedev_order)
    nleb_grid = leb_weights.size
    atom_coords = mol.atom_coords()
    Ylm_sphere = numpy.vstack(sph.real_sph_vec(leb_coords, lmax, True))
    fi = ddcosmo.make_fi(pcmobj, r_vdw)

    L_diag = numpy.zeros((natm, nlm))
    p1 = 0
    for l in range(lmax + 1):
        p0, p1 = p1, p1 + (l * 2 + 1)
        L_diag[:, p0:p1] = 4 * numpy.pi / (l * 2 + 1)
    L_diag /= r_vdw.reshape(-1, 1)
    L = numpy.diag(L_diag.ravel()).reshape(natm, nlm, natm, nlm)
    for ja in range(natm):
        for ka in range(natm):
            if ja == ka:
                continue
            vjk = r_vdw[ja] * leb_coords + atom_coords[ja] - atom_coords[ka]
            v = lib.norm(vjk, axis=1)
            tjk = v / r_vdw[ka]
            sjk = vjk / v.reshape(-1, 1)
            Ys = sph.real_sph_vec(sjk, lmax, True)
            # scale the weight, see JCTC 9, 3637, Eq (16)
            wjk = pcmobj.regularize_xt(tjk, eta, r_vdw[ka])
            wjk[fi[ja] > 1] /= fi[ja, fi[ja] > 1]
            tt = numpy.ones_like(wjk)
            p1 = 0
            for l in range(lmax + 1):
                fac = 4 * numpy.pi / (l * 2 + 1) / r_vdw[ka]
                p0, p1 = p1, p1 + (l * 2 + 1)
                val = numpy.einsum('n,xn,n,mn->xm', leb_weights, Ylm_sphere,
                                   wjk * tt, Ys[l])
                L[ja, :, ka, p0:p1] += -fac * val
                tt *= tjk
    return L.reshape(natm * nlm, natm * nlm)
Example #17
0
def make_vmat(pcm, r_vdw, lebedev_order, lmax, LX, LS):
    mol = pcm.mol
    grids = dft.gen_grid.Grids(mol)
    atom_grids_tab = grids.gen_atomic_grids(mol)
    grids.build()
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(lebedev_order)
    ao = dft.numint.eval_ao(mol, grids.coords)
    nao = ao.shape[1]
    vmat = numpy.zeros((nao,nao))
    i1 = 0
    for ia in range(mol.natm):
        xnj, w = atom_grids_tab[mol.atom_symbol(ia)]
        i0, i1 = i1, i1 + w.size
        r = lib.norm(xnj, axis=1)
        Ys = sph.real_sph_vec(xnj/r.reshape(-1,1), lmax, True)
        p1 = 0
        for l in range(lmax+1):
            fac = 4*numpy.pi/(l*2+1)
            p0, p1 = p1, p1 + (l*2+1)
            rr = numpy.zeros_like(r)
            rr[r<=r_vdw[ia]] = r[r<=r_vdw[ia]]**l / r_vdw[ia]**(l+1)
            rr[r> r_vdw[ia]] = r_vdw[ia]**l / r[r>r_vdw[ia]]**(l+1)
            eta_nj = fac * numpy.einsum('n,mn,m->n', rr, Ys[l], LX[ia,p0:p1])
            vmat -= numpy.einsum('n,np,nq->pq', grids.weights[i0:i1] * eta_nj,
                                 ao[i0:i1], ao[i0:i1])

    atom_coords = mol.atom_coords()
    Ylm_sphere = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))
    fi = ddcosmo.make_fi(pcm, r_vdw)
    ui = 1 - fi
    ui[ui<0] = 0
    xi_nj = numpy.einsum('n,jn,xn,jx->jn', weights_1sph, ui, Ylm_sphere, LS)

    pmol = mol.copy()
    for ia in range(mol.natm):
        for i,c in enumerate(coords_1sph):
            r = atom_coords[ia] + r_vdw[ia] * c
            pmol.set_rinv_orig(r)
            vmat += pmol.intor('int1e_rinv') * xi_nj[ia,i]
    return vmat
Example #18
0
def make_vmat(pcm, r_vdw, lebedev_order, lmax, LX, LS):
    mol = pcm.mol
    grids = dft.gen_grid.Grids(mol)
    atom_grids_tab = grids.gen_atomic_grids(mol)
    grids.build()
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(lebedev_order)
    ao = dft.numint.eval_ao(mol, grids.coords)
    nao = ao.shape[1]
    vmat = numpy.zeros((nao, nao))
    i1 = 0
    for ia in range(mol.natm):
        xnj, w = atom_grids_tab[mol.atom_symbol(ia)]
        i0, i1 = i1, i1 + w.size
        r = lib.norm(xnj, axis=1)
        Ys = sph.real_sph_vec(xnj / r.reshape(-1, 1), lmax, True)
        p1 = 0
        for l in range(lmax + 1):
            fac = 4 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            rr = numpy.zeros_like(r)
            rr[r <= r_vdw[ia]] = r[r <= r_vdw[ia]]**l / r_vdw[ia]**(l + 1)
            rr[r > r_vdw[ia]] = r_vdw[ia]**l / r[r > r_vdw[ia]]**(l + 1)
            eta_nj = fac * numpy.einsum('n,mn,m->n', rr, Ys[l], LX[ia, p0:p1])
            vmat -= numpy.einsum('n,np,nq->pq', grids.weights[i0:i1] * eta_nj,
                                 ao[i0:i1], ao[i0:i1])

    atom_coords = mol.atom_coords()
    Ylm_sphere = numpy.vstack(sph.real_sph_vec(coords_1sph, lmax, True))
    fi = ddcosmo.make_fi(pcm, r_vdw)
    ui = 1 - fi
    ui[ui < 0] = 0
    xi_nj = numpy.einsum('n,jn,xn,jx->jn', weights_1sph, ui, Ylm_sphere, LS)

    pmol = mol.copy()
    for ia in range(mol.natm):
        for i, c in enumerate(coords_1sph):
            r = atom_coords[ia] + r_vdw[ia] * c
            pmol.set_rinv_orig(r)
            vmat += pmol.intor('int1e_rinv') * xi_nj[ia, i]
    return vmat
Example #19
0
def make_fi1(pcmobj, r_vdw):
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    mol = pcmobj.mol
    eta = pcmobj.eta
    natm = mol.natm
    atom_coords = mol.atom_coords()
    ngrid_1sph = coords_1sph.shape[0]
    fi1 = numpy.zeros((natm,3,natm,ngrid_1sph))
    for ia in range(natm):
        for ja in ddcosmo.atoms_with_vdw_overlap(ia, atom_coords, r_vdw):
            v = r_vdw[ia]*coords_1sph + atom_coords[ia] - atom_coords[ja]
            rv = lib.norm(v, axis=1)
            t = rv / r_vdw[ja]
            xt1 = regularize_xt1(t, eta*r_vdw[ja])
            s_ij = v.T / rv
            xt1 = 1./r_vdw[ja] * xt1 * s_ij
            fi1[ia,:,ia] += xt1
            fi1[ja,:,ia] -= xt1

    fi = ddcosmo.make_fi(pcmobj, r_vdw)
    fi1[:,:,fi<1e-20] = 0
    return fi1
Example #20
0
def make_fi1(pcmobj, r_vdw):
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    mol = pcmobj.mol
    eta = pcmobj.eta
    natm = mol.natm
    atom_coords = mol.atom_coords()
    ngrid_1sph = coords_1sph.shape[0]
    fi1 = numpy.zeros((natm,3,natm,ngrid_1sph))
    for ia in range(natm):
        for ja in ddcosmo.atoms_with_vdw_overlap(ia, atom_coords, r_vdw):
            v = r_vdw[ia]*coords_1sph + atom_coords[ia] - atom_coords[ja]
            rv = lib.norm(v, axis=1)
            t = rv / r_vdw[ja]
            xt1 = regularize_xt1(t, eta*r_vdw[ja])
            s_ij = v.T / rv
            xt1 = 1./r_vdw[ja] * xt1 * s_ij
            fi1[ia,:,ia] += xt1
            fi1[ja,:,ia] -= xt1

    fi = ddcosmo.make_fi(pcmobj, r_vdw)
    fi1[:,:,fi<1e-20] = 0
    return fi1
Example #21
0
def make_L(pcmobj, r_vdw, lebedev_order, lmax, eta=0.1):
    mol = pcmobj.mol
    natm = mol.natm
    nlm = (lmax+1)**2

    leb_coords, leb_weights = ddcosmo.make_grids_one_sphere(lebedev_order)
    nleb_grid = leb_weights.size
    atom_coords = mol.atom_coords()
    Ylm_sphere = numpy.vstack(sph.real_sph_vec(leb_coords, lmax, True))
    fi = ddcosmo.make_fi(pcmobj, r_vdw)

    L_diag = numpy.zeros((natm,nlm))
    p1 = 0
    for l in range(lmax+1):
        p0, p1 = p1, p1 + (l*2+1)
        L_diag[:,p0:p1] = 4*numpy.pi/(l*2+1)
    L_diag /= r_vdw.reshape(-1,1)
    L = numpy.diag(L_diag.ravel()).reshape(natm,nlm,natm,nlm)
    for ja in range(natm):
        for ka in range(natm):
            if ja == ka:
                continue
            vjk = r_vdw[ja] * leb_coords + atom_coords[ja] - atom_coords[ka]
            v = lib.norm(vjk, axis=1)
            tjk = v / r_vdw[ka]
            sjk = vjk / v.reshape(-1,1)
            Ys = sph.real_sph_vec(sjk, lmax, True)
            # scale the weight, see JCTC 9, 3637, Eq (16)
            wjk = pcmobj.regularize_xt(tjk, eta, r_vdw[ka])
            wjk[fi[ja]>1] /= fi[ja,fi[ja]>1]
            tt = numpy.ones_like(wjk)
            p1 = 0
            for l in range(lmax+1):
                fac = 4*numpy.pi/(l*2+1) / r_vdw[ka]
                p0, p1 = p1, p1 + (l*2+1)
                val = numpy.einsum('n,xn,n,mn->xm', leb_weights, Ylm_sphere, wjk*tt, Ys[l])
                L[ja,:,ka,p0:p1] += -fac * val
                tt *= tjk
    return L.reshape(natm*nlm,natm*nlm)
Example #22
0
def make_A(pcmobj, r_vdw, ylm_1sph, ui):
    # Part of A matrix defined in JCP, 144, 054101, Eq (43), (44)
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    eta = pcmobj.eta
    nlm = (lmax + 1)**2

    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ngrid_1sph = weights_1sph.size
    atom_coords = mol.atom_coords()
    ylm_1sph = ylm_1sph.reshape(nlm, ngrid_1sph)
    Amat = numpy.zeros((natm, nlm, natm, nlm))

    for ja in range(natm):
        # w_u = precontract w_n U_j
        w_u = weights_1sph * ui[ja]
        p1 = 0
        for l in range(lmax + 1):
            fac = 2 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            a = numpy.einsum('xn,n,mn->xm', ylm_1sph, w_u, ylm_1sph[p0:p1])
            Amat[ja, :, ja, p0:p1] += -fac * a

        for ka in ddcosmo.atoms_with_vdw_overlap(ja, atom_coords, r_vdw):
            vjk = r_vdw[ja] * coords_1sph + atom_coords[ja] - atom_coords[ka]
            rjk = lib.norm(vjk, axis=1)
            pol = sph.multipoles(vjk, lmax)
            p1 = 0
            weights = w_u / rjk**(l * 2 + 1)
            for l in range(lmax + 1):
                fac = 4 * numpy.pi * l / (l * 2 + 1) * r_vdw[ka]**(l + 1)
                p0, p1 = p1, p1 + (l * 2 + 1)
                a = numpy.einsum('xn,n,mn->xm', ylm_1sph, weights, pol[l])
                Amat[ja, :, ka, p0:p1] += -fac * a
    return Amat
Example #23
0
def make_A(pcmobj, r_vdw, ylm_1sph, ui):
    # Part of A matrix defined in JCP, 144, 054101, Eq (43), (44)
    mol = pcmobj.mol
    natm = mol.natm
    lmax = pcmobj.lmax
    eta = pcmobj.eta
    nlm = (lmax+1)**2

    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    ngrid_1sph = weights_1sph.size
    atom_coords = mol.atom_coords()
    ylm_1sph = ylm_1sph.reshape(nlm,ngrid_1sph)
    Amat = numpy.zeros((natm,nlm,natm,nlm))

    for ja in range(natm):
        # w_u = precontract w_n U_j
        w_u = weights_1sph * ui[ja]
        p1 = 0
        for l in range(lmax+1):
            fac = 2*numpy.pi/(l*2+1)
            p0, p1 = p1, p1 + (l*2+1)
            a = numpy.einsum('xn,n,mn->xm', ylm_1sph, w_u, ylm_1sph[p0:p1])
            Amat[ja,:,ja,p0:p1] += -fac * a

        for ka in ddcosmo.atoms_with_vdw_overlap(ja, atom_coords, r_vdw):
            vjk = r_vdw[ja] * coords_1sph + atom_coords[ja] - atom_coords[ka]
            rjk = lib.norm(vjk, axis=1)
            pol = sph.multipoles(vjk, lmax)
            p1 = 0
            weights = w_u / rjk**(l*2+1)
            for l in range(lmax+1):
                fac = 4*numpy.pi*l/(l*2+1) * r_vdw[ka]**(l+1)
                p0, p1 = p1, p1 + (l*2+1)
                a = numpy.einsum('xn,n,mn->xm', ylm_1sph, weights, pol[l])
                Amat[ja,:,ka,p0:p1] += -fac * a
    return Amat
Example #24
0
def make_phi1(pcmobj, dm, r_vdw, ui):
    mol = pcmobj.mol
    natm = mol.natm
    nlm = (pcmobj.lmax+1)**2

    if not (isinstance(dm, numpy.ndarray) and dm.ndim == 2):
        dm = dm[0] + dm[1]
    tril_dm = lib.pack_tril(dm+dm.T)
    nao = dm.shape[0]
    diagidx = numpy.arange(nao)
    diagidx = diagidx*(diagidx+1)//2 + diagidx
    tril_dm[diagidx] *= .5

    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()

    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcmobj.lmax, True))
    extern_point_idx = ui > 0

    fi1 = make_fi1(pcmobj, pcmobj.get_atomic_radii())
    fi1[:,:,ui==0] = 0
    ui1 = -fi1

    ngrid_1sph = weights_1sph.size
    v_phi0 = numpy.empty((natm,ngrid_1sph))
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        d_rs = atom_coords.reshape(-1,1,3) - cav_coords
        v_phi0[ia] = numpy.einsum('z,zp->p', atom_charges, 1./lib.norm(d_rs,axis=2))
    phi1 = -numpy.einsum('n,ln,azjn,jn->azjl', weights_1sph, ylm_1sph, ui1, v_phi0)

    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        for ja in range(natm):
            rs = atom_coords[ja] - cav_coords
            d_rs = lib.norm(rs, axis=1)
            v_phi = atom_charges[ja] * numpy.einsum('px,p->px', rs, 1./d_rs**3)
            tmp = numpy.einsum('n,ln,n,nx->xl', weights_1sph, ylm_1sph, ui[ia], v_phi)
            phi1[ja,:,ia] += tmp  # response of the other atoms
            phi1[ia,:,ia] -= tmp  # response of cavity grids

    int3c2e = mol._add_suffix('int3c2e')
    int3c2e_ip1 = mol._add_suffix('int3c2e_ip1')
    aoslices = mol.aoslice_by_atom()
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        #fakemol = gto.fakemol_for_charges(cav_coords[ui[ia]>0])
        fakemol = gto.fakemol_for_charges(cav_coords)
        v_nj = df.incore.aux_e2(mol, fakemol, intor=int3c2e, aosym='s1')
        v_phi = numpy.einsum('ij,ijk->k', dm, v_nj)
        phi1[:,:,ia] += numpy.einsum('n,ln,azn,n->azl', weights_1sph, ylm_1sph, ui1[:,:,ia], v_phi)

        v_e1_nj = df.incore.aux_e2(mol, fakemol, intor=int3c2e_ip1, comp=3, aosym='s1')
        v_e2_nj = v_e1_nj + v_e1_nj.transpose(0,2,1,3)
        phi1_e2_nj = numpy.einsum('ji,xijr->xr', dm, v_e2_nj)
        phi1[ia,:,ia] += numpy.einsum('n,ln,n,xn->xl', weights_1sph, ylm_1sph, ui[ia], phi1_e2_nj)

        for ja in range(natm):
            shl0, shl1, p0, p1 = aoslices[ja]
            phi1_nj  = numpy.einsum('ij,xijr->xr', dm[p0:p1  ], v_e1_nj[:,p0:p1])
            phi1_nj += numpy.einsum('ji,xijr->xr', dm[:,p0:p1], v_e1_nj[:,p0:p1])
            phi1[ja,:,ia] -= numpy.einsum('n,ln,n,xn->xl', weights_1sph, ylm_1sph, ui[ia], phi1_nj)
    return phi1
Example #25
0
def make_B1(pcmobj, r_vdw, ui, ylm_1sph, cached_pol, L):
    '''1st order'''
    mol = pcmobj.mol
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ngrid_1sph = coords_1sph.shape[0]
    mol = pcmobj.mol
    natm = mol.natm
    nao = mol.nao
    lmax = pcmobj.lmax
    nlm = (lmax + 1)**2

    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()
    grids = pcmobj.grids

    extern_point_idx = ui > 0
    cav_coords = (atom_coords.reshape(natm, 1, 3) +
                  numpy.einsum('r,gx->rgx', r_vdw, coords_1sph))

    cav_coords = cav_coords[extern_point_idx]
    int3c2e = mol._add_suffix('int3c2e')
    cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env, int3c2e)
    fakemol = gto.fakemol_for_charges(cav_coords)
    v_nj = df.incore.aux_e2(mol,
                            fakemol,
                            intor=int3c2e,
                            aosym='s1',
                            cintopt=cintopt)
    nao_pair = v_nj.shape[0]
    v_phi = numpy.zeros((natm, ngrid_1sph, nao, nao))
    v_phi[extern_point_idx] += v_nj.transpose(2, 0, 1)
    phi0 = numpy.einsum('n,xn,jn,jnpq->jxpq', weights_1sph, ylm_1sph, ui,
                        v_phi)

    Xvec0 = numpy.linalg.solve(L.reshape(natm * nlm, -1),
                               phi0.reshape(natm * nlm, -1))
    Xvec0 = Xvec0.reshape(natm, nlm, nao, nao)

    ao = mol.eval_gto('GTOval', grids.coords)
    aow = numpy.einsum('gi,g->gi', ao, grids.weights)
    aopair = numpy.einsum('gi,gj->gij', ao, aow)

    psi0 = numpy.zeros((natm, nlm, nao, nao))
    i1 = 0
    for ia in range(natm):
        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        i0, i1 = i1, i1 + fak_pol[0].shape[1]
        p1 = 0
        for l in range(lmax + 1):
            fac = 4 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            psi0[ia, p0:p1] = -fac * numpy.einsum('mn,nij->mij', fak_pol[l],
                                                  aopair[i0:i1])

    fi0 = ddcosmo.make_fi(pcmobj, r_vdw)
    fi1 = ddcosmo_grad.make_fi1(pcmobj, pcmobj.get_atomic_radii())
    fi1[:, :, ui == 0] = 0
    ui1 = -fi1

    phi1 = numpy.zeros(ui1.shape[:3] + (nlm, nao, nao))
    int3c2e = mol._add_suffix('int3c2e')
    int3c2e_ip1 = mol._add_suffix('int3c2e_ip1')
    aoslices = mol.aoslice_by_atom()
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        #fakemol = gto.fakemol_for_charges(cav_coords[ui[ia]>0])
        fakemol = gto.fakemol_for_charges(cav_coords)
        v_nj = df.incore.aux_e2(mol, fakemol, intor=int3c2e, aosym='s1')
        phi1[:, :, ia] += lib.einsum('n,ln,azn,ijn->azlij', weights_1sph,
                                     ylm_1sph, ui1[:, :, ia], v_nj)

        v_e1_nj = df.incore.aux_e2(mol,
                                   fakemol,
                                   intor=int3c2e_ip1,
                                   comp=3,
                                   aosym='s1')
        v_e2_nj = v_e1_nj + v_e1_nj.transpose(0, 2, 1, 3)
        phi1[ia, :, ia] += lib.einsum('n,ln,n,xijn->xlij', weights_1sph,
                                      ylm_1sph, ui[ia], v_e2_nj)

        for ja in range(natm):
            shl0, shl1, p0, p1 = aoslices[ja]
            v = numpy.einsum('n,ln,n,xijn->xlij', weights_1sph, ylm_1sph,
                             ui[ia], v_e1_nj[:, p0:p1])
            phi1[ja, :, ia, :, p0:p1, :] -= v
            phi1[ja, :, ia, :, :, p0:p1] -= v.transpose(0, 1, 3, 2)

    psi1 = numpy.zeros((natm, 3, natm, nlm, nao, nao))
    i1 = 0
    for ia, (coords, weight,
             weight1) in enumerate(rks_grad.grids_response_cc(grids)):
        i0, i1 = i1, i1 + weight.size
        ao = mol.eval_gto('GTOval_sph_deriv1', coords)
        aow = numpy.einsum('gi,g->gi', ao[0], weight)
        aopair1 = lib.einsum('xgi,gj->xgij', ao[1:], aow)
        aow = numpy.einsum('gi,zxg->zxgi', ao[0], weight1)
        aopair0 = lib.einsum('zxgi,gj->zxgij', aow, ao[0])

        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        p1 = 0
        for l in range(lmax + 1):
            fac = 4 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            psi1[:, :, ia, p0:p1] -= fac * numpy.einsum(
                'mn,zxnij->zxmij', fak_pol[l], aopair0)
            vtmp = fac * numpy.einsum('mn,xnij->xmij', fak_pol[l], aopair1)
            psi1[ia, :, ia, p0:p1] -= vtmp
            psi1[ia, :, ia, p0:p1] -= vtmp.transpose(0, 1, 3, 2)

            for ja in range(natm):
                shl0, shl1, q0, q1 = aoslices[ja]
                psi1[ja, :, ia, p0:p1, q0:q1, :] += vtmp[:, :, q0:q1]
                psi1[ja, :, ia, p0:p1, :,
                     q0:q1] += vtmp[:, :, q0:q1].transpose(0, 1, 3, 2)

    L1 = ddcosmo_grad.make_L1(pcmobj, r_vdw, ylm_1sph, fi0)

    Xvec1 = numpy.linalg.solve(
        L.reshape(natm * nlm, -1),
        phi1.transpose(2, 3, 0, 1, 4, 5).reshape(natm * nlm, -1))
    Xvec1 = Xvec1.reshape(natm, nlm, natm, 3, nao,
                          nao).transpose(2, 3, 0, 1, 4, 5)
    LS0 = numpy.linalg.solve(
        L.reshape(natm * nlm, -1).T, psi0.reshape(natm * nlm, -1))
    LS0 = LS0.reshape(natm, nlm, nao, nao)

    B = lib.einsum('ixnlpq,nlrs->ixpqrs', psi1, Xvec0)
    B += lib.einsum('nlpq,ixnlrs->ixpqrs', psi0, Xvec1)
    B -= lib.einsum('ilpq,aziljm,jmrs->azpqrs', LS0, L1, Xvec0)
    B = B + B.transpose(0, 1, 4, 5, 2, 3)
    return B
Example #26
0
    def test_B1(self):
        def getB(mol):
            pcm = ddcosmo.DDCOSMO(mol)
            pcm.lmax = 2
            pcm.eps = 0
            natm = mol.natm
            nao = mol.nao
            nlm = (pcm.lmax + 1)**2
            r_vdw = ddcosmo.get_atomic_radii(pcm)
            fi = ddcosmo.make_fi(pcm, r_vdw)
            ui = 1 - fi
            ui[ui < 0] = 0
            pcm.grids = grids = dft.gen_grid.Grids(mol).run(level=0)
            coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
                pcm.lebedev_order)
            ylm_1sph = numpy.vstack(
                sph.real_sph_vec(coords_1sph, pcm.lmax, True))
            cached_pol = ddcosmo.cache_fake_multipoles(grids, r_vdw, pcm.lmax)
            L = ddcosmo.make_L(pcm, r_vdw, ylm_1sph, fi)
            return make_B(pcm, r_vdw, ui, ylm_1sph, cached_pol, L)

        pcm = ddcosmo.DDCOSMO(mol0)
        pcm.lmax = 2
        pcm.eps = 0
        natm = mol0.natm
        nao = mol0.nao
        nlm = (pcm.lmax + 1)**2
        r_vdw = ddcosmo.get_atomic_radii(pcm)
        fi = ddcosmo.make_fi(pcm, r_vdw)
        ui = 1 - fi
        ui[ui < 0] = 0
        pcm.grids = grids = dft.gen_grid.Grids(mol0).run(level=0)
        coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
            pcm.lebedev_order)
        ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcm.lmax, True))
        cached_pol = ddcosmo.cache_fake_multipoles(grids, r_vdw, pcm.lmax)
        L = ddcosmo.make_L(pcm, r_vdw, ylm_1sph, fi)
        dB = make_B1(pcm, r_vdw, ui, ylm_1sph, cached_pol, L)

        B1 = getB(mol1)
        B2 = getB(mol2)
        self.assertAlmostEqual(abs((B2 - B1) / dx - dB[0, 2]).max(), 0, 8)

        nao = mol0.nao
        numpy.random.seed(1)
        dm1 = numpy.random.random((2, nao, nao))
        dm2 = numpy.random.random((2, nao, nao))
        dm = dm1[0]
        ref = numpy.einsum('azpqrs,npq->nazrs', dB, dm1)
        v = B1_dot_x(pcm, dm, r_vdw, ui, ylm_1sph, cached_pol, L)
        self.assertAlmostEqual(abs(v - ref[0]).max(), 0, 12)

        de = _ddcosmo_tdscf_grad._grad_ee(pcm, dm1, dm2, r_vdw, ui, ylm_1sph,
                                          cached_pol, L)
        ref = numpy.einsum('nazij,nij->naz', ref, dm2)
        self.assertAlmostEqual(abs(de - ref).max(), 0, 12)

        numpy.random.seed(1)
        dm = numpy.random.random((nao, nao))
        dm = dm + dm.T
        ref = ddcosmo_grad.kernel(pcm, dm)
        dielectric = pcm.eps
        if dielectric > 0:
            f_epsilon = (dielectric - 1.) / dielectric
        else:
            f_epsilon = 1
        de = _ddcosmo_tdscf_grad._grad_nn(pcm, r_vdw, ui, ylm_1sph, cached_pol,
                                          L)
        de += _ddcosmo_tdscf_grad._grad_ne(pcm, dm, r_vdw, ui, ylm_1sph,
                                           cached_pol, L)
        de += .5 * _ddcosmo_tdscf_grad._grad_ee(pcm, dm, dm, r_vdw, ui,
                                                ylm_1sph, cached_pol, L)
        de *= .5 * f_epsilon
        self.assertAlmostEqual(abs(de - ref).max(), 0, 12)
Example #27
0
def make_B(pcmobj, r_vdw, ui, ylm_1sph, cached_pol, L):
    mol = pcmobj.mol
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ngrid_1sph = coords_1sph.shape[0]
    mol = pcmobj.mol
    natm = mol.natm
    nao = mol.nao
    lmax = pcmobj.lmax
    nlm = (lmax + 1)**2

    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()
    grids = pcmobj.grids

    extern_point_idx = ui > 0
    cav_coords = (atom_coords.reshape(natm, 1, 3) +
                  numpy.einsum('r,gx->rgx', r_vdw, coords_1sph))

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

    cav_coords = cav_coords[extern_point_idx]
    int3c2e = mol._add_suffix('int3c2e')
    cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env, int3c2e)
    fakemol = gto.fakemol_for_charges(cav_coords)
    v_nj = df.incore.aux_e2(mol,
                            fakemol,
                            intor=int3c2e,
                            aosym='s2ij',
                            cintopt=cintopt)
    nao_pair = v_nj.shape[0]
    v_phi = numpy.zeros((nao_pair, natm, ngrid_1sph))
    v_phi[:, extern_point_idx] += v_nj

    phi = numpy.einsum('n,xn,jn,ijn->ijx', weights_1sph, ylm_1sph, ui, v_phi)

    Xvec = numpy.linalg.solve(L.reshape(natm * nlm, -1),
                              phi.reshape(-1, natm * nlm).T)
    Xvec = Xvec.reshape(natm, nlm, nao_pair)

    ao = mol.eval_gto('GTOval', grids.coords)
    aow = numpy.einsum('gi,g->gi', ao, grids.weights)
    aopair = lib.pack_tril(numpy.einsum('gi,gj->gij', ao, aow))

    psi = numpy.zeros((nao_pair, natm, nlm))
    i1 = 0
    for ia in range(natm):
        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        i0, i1 = i1, i1 + fak_pol[0].shape[1]
        p1 = 0
        for l in range(lmax + 1):
            fac = 4 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            psi[:, ia, p0:p1] = -fac * numpy.einsum('mn,ni->im', fak_pol[l],
                                                    aopair[i0:i1])

    B = lib.einsum('pnl,nlq->pq', psi, Xvec)
    B = B + B.T
    B = ao2mo.restore(1, B, nao)
    return B
Example #28
0
def nuc_part(pcmobj, r_vdw, ui, ylm_1sph, cached_pol, L):
    '''0th order'''
    mol = pcmobj.mol
    natm = mol.natm
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ngrid_1sph = coords_1sph.shape[0]
    lmax = pcmobj.lmax
    nlm = (lmax + 1)**2
    nao = mol.nao
    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()
    grids = pcmobj.grids

    extern_point_idx = ui > 0
    cav_coords = (atom_coords.reshape(natm, 1, 3) +
                  numpy.einsum('r,gx->rgx', r_vdw, coords_1sph))

    v_phi = numpy.zeros((natm, ngrid_1sph))
    for ia in range(natm):
        # Note (-) sign is not applied to atom_charges, because (-) is explicitly
        # included in rhs and L matrix
        d_rs = atom_coords.reshape(-1, 1, 3) - cav_coords[ia]
        v_phi[ia] = numpy.einsum('z,zp->p', atom_charges,
                                 1. / lib.norm(d_rs, axis=2))
    phi = -numpy.einsum('n,xn,jn,jn->jx', weights_1sph, ylm_1sph, ui, v_phi)

    Xvec = numpy.linalg.solve(L.reshape(natm * nlm, -1), phi.ravel())
    Xvec = Xvec.reshape(natm, nlm)

    i1 = 0
    scaled_weights = numpy.empty((grids.weights.size))
    for ia in range(natm):
        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        i0, i1 = i1, i1 + fak_pol[0].shape[1]
        eta_nj = 0
        p1 = 0
        for l in range(lmax + 1):
            fac = 4 * numpy.pi / (l * 2 + 1)
            p0, p1 = p1, p1 + (l * 2 + 1)
            eta_nj += fac * numpy.einsum('mn,m->n', fak_pol[l], Xvec[ia,
                                                                     p0:p1])
        scaled_weights[i0:i1] = eta_nj
    scaled_weights *= grids.weights

    ao = mol.eval_gto('GTOval', grids.coords)
    vmat = -lib.einsum('g,gi,gj->ij', scaled_weights, ao, ao)

    # 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
    psi = numpy.zeros((natm, nlm))
    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.ravel())
    L_S = L_S.reshape(natm, nlm)
    xi_jn = numpy.einsum('n,jn,xn,jx->jn', weights_1sph, ui, ylm_1sph, L_S)
    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')
    fakemol = gto.fakemol_for_charges(cav_coords)
    v_nj = df.incore.aux_e2(mol,
                            fakemol,
                            intor='int3c2e',
                            aosym='s1',
                            cintopt=cintopt)
    vmat += numpy.einsum('ijn,n->ij', v_nj, xi_jn)
    return vmat
Example #29
0
def nuc_part1(pcmobj, r_vdw, ui, ylm_1sph, cached_pol, L):
    '''1st order'''
    mol = pcmobj.mol
    natm = mol.natm
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ngrid_1sph = coords_1sph.shape[0]
    lmax = pcmobj.lmax
    nlm = (lmax + 1)**2
    nao = mol.nao
    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()
    grids = pcmobj.grids
    aoslices = mol.aoslice_by_atom()

    extern_point_idx = ui > 0
    fi0 = ddcosmo.make_fi(pcmobj, r_vdw)
    fi1 = ddcosmo_grad.make_fi1(pcmobj, pcmobj.get_atomic_radii())
    fi1[:, :, ui == 0] = 0
    ui1 = -fi1

    vmat1 = numpy.zeros((natm, 3, nao, nao))

    cav_coords = (atom_coords.reshape(natm, 1, 3) +
                  numpy.einsum('r,gx->rgx', r_vdw, coords_1sph))

    v_phi = numpy.zeros((natm, ngrid_1sph))
    for ia in range(natm):
        # Note (-) sign is not applied to atom_charges, because (-) is explicitly
        # included in rhs and L matrix
        d_rs = atom_coords.reshape(-1, 1, 3) - cav_coords[ia]
        v_phi[ia] = numpy.einsum('z,zp->p', atom_charges,
                                 1. / lib.norm(d_rs, axis=2))
    phi0 = -numpy.einsum('n,xn,jn,jn->jx', weights_1sph, ylm_1sph, ui, v_phi)

    Xvec0 = numpy.linalg.solve(L.reshape(natm * nlm, -1), phi0.ravel())
    Xvec0 = Xvec0.reshape(natm, nlm)

    ngrid_1sph = weights_1sph.size
    v_phi0 = numpy.empty((natm, ngrid_1sph))
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        d_rs = atom_coords.reshape(-1, 1, 3) - cav_coords
        v_phi0[ia] = numpy.einsum('z,zp->p', atom_charges,
                                  1. / lib.norm(d_rs, axis=2))
    phi1 = -numpy.einsum('n,ln,azjn,jn->azjl', weights_1sph, ylm_1sph, ui1,
                         v_phi0)

    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        for ja in range(natm):
            rs = atom_coords[ja] - cav_coords
            d_rs = lib.norm(rs, axis=1)
            v_phi = atom_charges[ja] * numpy.einsum('px,p->px', rs,
                                                    1. / d_rs**3)
            tmp = numpy.einsum('n,ln,n,nx->xl', weights_1sph, ylm_1sph, ui[ia],
                               v_phi)
            phi1[ja, :, ia] += tmp  # response of the other atoms
            phi1[ia, :, ia] -= tmp  # response of cavity grids

    L1 = ddcosmo_grad.make_L1(pcmobj, r_vdw, ylm_1sph, fi0)

    phi1 -= lib.einsum('aziljm,jm->azil', L1, Xvec0)
    Xvec1 = numpy.linalg.solve(L.reshape(natm * nlm, -1),
                               phi1.reshape(-1, natm * nlm).T)
    Xvec1 = Xvec1.T.reshape(natm, 3, natm, nlm)

    i1 = 0
    for ia, (coords, weight,
             weight1) in enumerate(rks_grad.grids_response_cc(grids)):
        i0, i1 = i1, i1 + weight.size
        ao = mol.eval_gto('GTOval_sph_deriv1', coords)
        aow = numpy.einsum('gi,g->gi', ao[0], weight)
        aopair1 = lib.einsum('xgi,gj->xgij', ao[1:], aow)
        aow = numpy.einsum('gi,zxg->zxgi', ao[0], weight1)
        aopair0 = lib.einsum('zxgi,gj->zxgij', aow, ao[0])

        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        fac_pol = ddcosmo._vstack_factor_fak_pol(fak_pol, lmax)
        vmat1 -= numpy.einsum('m,mn,zxnij->zxij', Xvec0[ia], fac_pol, aopair0)
        vtmp = numpy.einsum('m,mn,xnij->xij', Xvec0[ia], fac_pol, aopair1)
        vmat1[ia, :] -= vtmp
        vmat1[ia, :] -= vtmp.transpose(0, 2, 1)

        for ja in range(natm):
            shl0, shl1, p0, p1 = aoslices[ja]
            vmat1[ja, :, p0:p1, :] += vtmp[:, p0:p1]
            vmat1[ja, :, :, p0:p1] += vtmp[:, p0:p1].transpose(0, 2, 1)

        scaled_weights = lib.einsum('azm,mn->azn', Xvec1[:, :, ia], fac_pol)
        scaled_weights *= weight
        aow = numpy.einsum('gi,azg->azgi', ao[0], scaled_weights)
        vmat1 -= numpy.einsum('gi,azgj->azij', ao[0], aow)

    psi0 = numpy.zeros((natm, nlm))
    for ia in range(natm):
        psi0[ia,
             0] += numpy.sqrt(4 * numpy.pi) / r_vdw[ia] * mol.atom_charge(ia)

    LS0 = numpy.linalg.solve(L.reshape(natm * nlm, -1).T, psi0.ravel())
    LS0 = LS0.reshape(natm, nlm)

    LS1 = numpy.einsum('il,aziljm->azjm', LS0, L1)
    LS1 = numpy.linalg.solve(
        L.reshape(natm * nlm, -1).T,
        LS1.reshape(-1, natm * nlm).T)
    LS1 = LS1.T.reshape(natm, 3, natm, nlm)

    int3c2e = mol._add_suffix('int3c2e')
    int3c2e_ip1 = mol._add_suffix('int3c2e_ip1')
    cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env, int3c2e)
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        #fakemol = gto.fakemol_for_charges(cav_coords[ui[ia]>0])
        fakemol = gto.fakemol_for_charges(cav_coords)
        wtmp = lib.einsum('l,n,ln->ln', LS0[ia], weights_1sph, ylm_1sph)
        v_nj = df.incore.aux_e2(mol,
                                fakemol,
                                intor=int3c2e,
                                aosym='s1',
                                cintopt=cintopt)
        vmat1 -= numpy.einsum('azl,n,ln,n,pqn->azpq', LS1[:, :, ia],
                              weights_1sph, ylm_1sph, ui[ia], v_nj)
        vmat1 += lib.einsum('ln,azn,ijn->azij', wtmp, ui1[:, :, ia], v_nj)

        v_e1_nj = df.incore.aux_e2(mol,
                                   fakemol,
                                   intor=int3c2e_ip1,
                                   comp=3,
                                   aosym='s1')
        vtmp = lib.einsum('ln,n,xijn->xij', wtmp, ui[ia], v_e1_nj)
        vmat1[ia] += vtmp
        vmat1[ia] += vtmp.transpose(0, 2, 1)

        for ja in range(natm):
            shl0, shl1, p0, p1 = aoslices[ja]
            vmat1[ja, :, p0:p1, :] -= vtmp[:, p0:p1]
            vmat1[ja, :, :, p0:p1] -= vtmp[:, p0:p1].transpose(0, 2, 1)

    return vmat1
Example #30
0
def tda_grad(td, z):
    '''ddcosmo TDA gradients'''
    mol = td.mol
    mf = td._scf
    mo_coeff = mf.mo_coeff
    mo_energy = mf.mo_energy
    mo_occ = mf.mo_occ
    nao, nmo = mo_coeff.shape
    nocc = (mo_occ > 0).sum()
    nvir = nmo - nocc
    z = z[0].reshape(nocc, nvir).T * numpy.sqrt(2)
    orbv = mo_coeff[:, nocc:]
    orbo = mo_coeff[:, :nocc]

    r_vdw = ddcosmo.get_atomic_radii(td.with_solvent)
    fi = ddcosmo.make_fi(td.with_solvent, r_vdw)
    ui = 1 - fi
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        td.with_solvent.lebedev_order)
    ylm_1sph = numpy.vstack(
        sph.real_sph_vec(coords_1sph, td.with_solvent.lmax, True))
    grids = td.with_solvent.grids
    cached_pol = ddcosmo.cache_fake_multipoles(grids, r_vdw,
                                               td.with_solvent.lmax)
    L = ddcosmo.make_L(td.with_solvent, r_vdw, ylm_1sph, fi)

    def fvind(x):
        v_mo = numpy.einsum('iabj,xai->xbj', g[:nocc, nocc:, nocc:, :nocc], x)
        v_mo += numpy.einsum('aibj,xai->xbj', g[nocc:, :nocc, nocc:, :nocc], x)
        return v_mo

    h1 = rhf_grad.get_hcore(mol)
    s1 = rhf_grad.get_ovlp(mol)

    eri1 = -mol.intor('int2e_ip1', aosym='s1', comp=3)
    eri1 = eri1.reshape(3, nao, nao, nao, nao)
    eri0 = ao2mo.kernel(mol, mo_coeff)
    eri0 = ao2mo.restore(1, eri0, nmo).reshape(nmo, nmo, nmo, nmo)
    g = eri0 * 2 - eri0.transpose(0, 3, 2, 1)
    zeta = lib.direct_sum('i+j->ij', mo_energy, mo_energy) * .5
    zeta[nocc:, :nocc] = mo_energy[:nocc]
    zeta[:nocc, nocc:] = mo_energy[nocc:]

    dielectric = td.with_solvent.eps
    if dielectric > 0:
        f_epsilon = (dielectric - 1.) / dielectric
    else:
        f_epsilon = 1
    pcm_nuc = .5 * f_epsilon * nuc_part1(td.with_solvent, r_vdw, ui, ylm_1sph,
                                         cached_pol, L)
    B0 = .5 * f_epsilon * make_B(td.with_solvent, r_vdw, ui, ylm_1sph,
                                 cached_pol, L)
    B0 = lib.einsum('pqrs,pi,qj,rk,sl->ijkl', B0, mo_coeff, mo_coeff, mo_coeff,
                    mo_coeff)
    g += B0 * 2
    B1 = .5 * f_epsilon * make_B1(td.with_solvent, r_vdw, ui, ylm_1sph,
                                  cached_pol, L)

    offsetdic = mol.offset_nr_by_atom()
    de = numpy.zeros((mol.natm, 3))
    for ia in range(mol.natm):
        shl0, shl1, p0, p1 = offsetdic[ia]

        mol.set_rinv_origin(mol.atom_coord(ia))
        h1ao = -mol.atom_charge(ia) * mol.intor('int1e_iprinv', comp=3)
        h1ao[:, p0:p1] += h1[:, p0:p1]
        h1ao = h1ao + h1ao.transpose(0, 2, 1)
        h1ao += pcm_nuc[ia]
        h1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff, h1ao, mo_coeff)
        s1mo = numpy.einsum('pi,xpq,qj->xij', mo_coeff[p0:p1], s1[:, p0:p1],
                            mo_coeff)
        s1mo = s1mo + s1mo.transpose(0, 2, 1)

        f1 = h1mo - numpy.einsum('xpq,pq->xpq', s1mo, zeta)
        f1 -= numpy.einsum('klpq,xlk->xpq', g[:nocc, :nocc],
                           s1mo[:, :nocc, :nocc])

        eri1a = eri1.copy()
        eri1a[:, :p0] = 0
        eri1a[:, p1:] = 0
        eri1a = eri1a + eri1a.transpose(0, 2, 1, 3, 4)
        eri1a = eri1a + eri1a.transpose(0, 3, 4, 1, 2)
        g1 = lib.einsum('xpqrs,pi,qj,rk,sl->xijkl', eri1a, mo_coeff, mo_coeff,
                        mo_coeff, mo_coeff)
        tmp1 = lib.einsum('xpqrs,pi,qj,rk,sl->xijkl', B1[ia], mo_coeff,
                          mo_coeff, mo_coeff, mo_coeff)
        g1 = g1 * 2 - g1.transpose(0, 1, 4, 3, 2)
        g1 += tmp1 * 2
        f1 += numpy.einsum('xkkpq->xpq', g1[:, :nocc, :nocc])
        f1ai = f1[:, nocc:, :nocc].copy()

        c1 = s1mo * -.5
        c1vo = cphf.solve(fvind, mo_energy, mo_occ, f1ai, max_cycle=50)[0]
        c1[:, nocc:, :nocc] = c1vo
        c1[:, :nocc,
           nocc:] = -(s1mo[:, nocc:, :nocc] + c1vo).transpose(0, 2, 1)
        f1 += numpy.einsum('kapq,xak->xpq', g[:nocc, nocc:], c1vo)
        f1 += numpy.einsum('akpq,xak->xpq', g[nocc:, :nocc], c1vo)

        e1 = numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:],
                          z, z)
        e1 += numpy.einsum('xab,ai,bi->x', f1[:, nocc:, nocc:], z, z)
        e1 -= numpy.einsum('xij,ai,aj->x', f1[:, :nocc, :nocc], z, z)

        g1 = numpy.einsum('pjkl,xpi->xijkl', g, c1)
        g1 += numpy.einsum('ipkl,xpj->xijkl', g, c1)
        g1 += numpy.einsum('ijpl,xpk->xijkl', g, c1)
        g1 += numpy.einsum('ijkp,xpl->xijkl', g, c1)
        e1 += numpy.einsum('xaijb,ai,bj->x', g1[:, nocc:, :nocc, :nocc, nocc:],
                           z, z)

        de[ia] = e1

    return de
Example #31
0
def make_phi1(pcmobj, dm, r_vdw, ui):
    mol = pcmobj.mol
    natm = mol.natm
    nlm = (pcmobj.lmax+1)**2

    if not (isinstance(dm, numpy.ndarray) and dm.ndim == 2):
        dm = dm[0] + dm[1]
    tril_dm = lib.pack_tril(dm+dm.T)
    nao = dm.shape[0]
    diagidx = numpy.arange(nao)
    diagidx = diagidx*(diagidx+1)//2 + diagidx
    tril_dm[diagidx] *= .5

    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()

    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(pcmobj.lebedev_order)
    ylm_1sph = numpy.vstack(sph.real_sph_vec(coords_1sph, pcmobj.lmax, True))
    extern_point_idx = ui > 0

    fi1 = make_fi1(pcmobj, pcmobj.get_atomic_radii())
    fi1[:,:,ui==0] = 0
    ui1 = -fi1

    ngrid_1sph = weights_1sph.size
    v_phi0 = numpy.empty((natm,ngrid_1sph))
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        d_rs = atom_coords.reshape(-1,1,3) - cav_coords
        v_phi0[ia] = numpy.einsum('z,zp->p', atom_charges, 1./lib.norm(d_rs,axis=2))
    phi1 = -numpy.einsum('n,ln,azjn,jn->azjl', weights_1sph, ylm_1sph, ui1, v_phi0)

    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        for ja in range(natm):
            rs = atom_coords[ja] - cav_coords
            d_rs = lib.norm(rs, axis=1)
            v_phi = atom_charges[ja] * numpy.einsum('px,p->px', rs, 1./d_rs**3)
            tmp = numpy.einsum('n,ln,n,nx->xl', weights_1sph, ylm_1sph, ui[ia], v_phi)
            phi1[ja,:,ia] += tmp  # response of the other atoms
            phi1[ia,:,ia] -= tmp  # response of cavity grids

    int3c2e = mol._add_suffix('int3c2e')
    int3c2e_ip1 = mol._add_suffix('int3c2e_ip1')
    aoslices = mol.aoslice_by_atom()
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        #fakemol = gto.fakemol_for_charges(cav_coords[ui[ia]>0])
        fakemol = gto.fakemol_for_charges(cav_coords)
        v_nj = df.incore.aux_e2(mol, fakemol, intor=int3c2e, aosym='s1')
        v_phi = numpy.einsum('ij,ijk->k', dm, v_nj)
        phi1[:,:,ia] += numpy.einsum('n,ln,azn,n->azl', weights_1sph, ylm_1sph, ui1[:,:,ia], v_phi)

        v_e1_nj = df.incore.aux_e2(mol, fakemol, intor=int3c2e_ip1, comp=3, aosym='s1')
        v_e2_nj = v_e1_nj + v_e1_nj.transpose(0,2,1,3)
        phi1_e2_nj = numpy.einsum('ji,xijr->xr', dm, v_e2_nj)
        phi1[ia,:,ia] += numpy.einsum('n,ln,n,xn->xl', weights_1sph, ylm_1sph, ui[ia], phi1_e2_nj)

        for ja in range(natm):
            shl0, shl1, p0, p1 = aoslices[ja]
            phi1_nj  = numpy.einsum('ij,xijr->xr', dm[p0:p1  ], v_e1_nj[:,p0:p1])
            phi1_nj += numpy.einsum('ji,xijr->xr', dm[:,p0:p1], v_e1_nj[:,p0:p1])
            phi1[ja,:,ia] -= numpy.einsum('n,ln,n,xn->xl', weights_1sph, ylm_1sph, ui[ia], phi1_nj)
    return phi1
Example #32
0
def B1_dot_x(pcmobj, dm, r_vdw, ui, ylm_1sph, cached_pol, L):
    mol = pcmobj.mol
    mol = pcmobj.mol
    natm = mol.natm
    nao = mol.nao
    lmax = pcmobj.lmax
    nlm = (lmax + 1)**2

    dms = numpy.asarray(dm)
    is_single_dm = dms.ndim == 2
    dms = dms.reshape(-1, nao, nao)
    n_dm = dms.shape[0]

    atom_coords = mol.atom_coords()
    atom_charges = mol.atom_charges()
    aoslices = mol.aoslice_by_atom()
    grids = pcmobj.grids
    coords_1sph, weights_1sph = ddcosmo.make_grids_one_sphere(
        pcmobj.lebedev_order)
    ngrid_1sph = coords_1sph.shape[0]

    extern_point_idx = ui > 0
    fi0 = ddcosmo.make_fi(pcmobj, r_vdw)
    fi1 = ddcosmo_grad.make_fi1(pcmobj, pcmobj.get_atomic_radii())
    fi1[:, :, ui == 0] = 0
    ui1 = -fi1

    Bx = numpy.zeros((natm, 3, nao, nao))

    ao = mol.eval_gto('GTOval', grids.coords)
    aow = numpy.einsum('gi,g->gi', ao, grids.weights)
    aopair = numpy.einsum('gi,gj->gij', ao, aow)
    den = numpy.einsum('gij,ij->g', aopair, dm)
    psi0 = numpy.zeros((natm, nlm))
    i1 = 0
    for ia in range(natm):
        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        fac_pol = ddcosmo._vstack_factor_fak_pol(fak_pol, lmax)
        i0, i1 = i1, i1 + fac_pol.shape[1]
        psi0[ia] = -numpy.einsum('mn,n->m', fac_pol, den[i0:i1])
    LS0 = numpy.linalg.solve(L.reshape(natm * nlm, -1).T, psi0.ravel())
    LS0 = LS0.reshape(natm, nlm)

    phi0 = numpy.zeros((natm, nlm))
    phi1 = numpy.zeros((natm, 3, natm, nlm))
    int3c2e = mol._add_suffix('int3c2e')
    int3c2e_ip1 = mol._add_suffix('int3c2e_ip1')
    cintopt = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env, int3c2e)
    cintopt_ip1 = gto.moleintor.make_cintopt(mol._atm, mol._bas, mol._env,
                                             int3c2e_ip1)
    for ia in range(natm):
        cav_coords = atom_coords[ia] + r_vdw[ia] * coords_1sph
        #fakemol = gto.fakemol_for_charges(cav_coords[ui[ia]>0])
        fakemol = gto.fakemol_for_charges(cav_coords)
        v_nj = df.incore.aux_e2(mol,
                                fakemol,
                                intor=int3c2e,
                                aosym='s1',
                                cintopt=cintopt)

        v_phi = numpy.einsum('pqg,pq->g', v_nj, dm)
        phi0[ia] = numpy.einsum('n,ln,n,n->l', weights_1sph, ylm_1sph, ui[ia],
                                v_phi)
        phi1[:, :, ia] += lib.einsum('n,ln,azn,n->azl', weights_1sph, ylm_1sph,
                                     ui1[:, :, ia], v_phi)
        Bx += lib.einsum('l,n,ln,azn,ijn->azij', LS0[ia], weights_1sph,
                         ylm_1sph, ui1[:, :, ia], v_nj)

        wtmp = lib.einsum('n,ln,n->ln', weights_1sph, ylm_1sph, ui[ia])

        v_e1_nj = df.incore.aux_e2(mol,
                                   fakemol,
                                   intor=int3c2e_ip1,
                                   comp=3,
                                   aosym='s1',
                                   cintopt=cintopt_ip1)
        vtmp = lib.einsum('l,ln,xijn->xij', LS0[ia], wtmp, v_e1_nj)
        Bx[ia] += vtmp
        Bx[ia] += vtmp.transpose(0, 2, 1)

        for ja in range(natm):
            shl0, shl1, p0, p1 = aoslices[ja]
            Bx[ja, :, p0:p1, :] -= vtmp[:, p0:p1]
            Bx[ja, :, :, p0:p1] -= vtmp[:, p0:p1].transpose(0, 2, 1)
            tmp = numpy.einsum('xijn,ij->xn', v_e1_nj[:, p0:p1], dm[p0:p1])
            tmp += numpy.einsum('xijn,ji->xn', v_e1_nj[:, p0:p1], dm[:, p0:p1])
            phitmp = numpy.einsum('ln,xn->xl', wtmp, tmp)
            phi1[ja, :, ia] -= phitmp
            phi1[ia, :, ia] += phitmp

    Xvec0 = numpy.linalg.solve(L.reshape(natm * nlm, -1), phi0.ravel())
    Xvec0 = Xvec0.reshape(natm, nlm)

    L1 = ddcosmo_grad.make_L1(pcmobj, r_vdw, ylm_1sph, fi0)

    phi1 -= lib.einsum('aziljm,jm->azil', L1, Xvec0)
    Xvec1 = numpy.linalg.solve(L.reshape(natm * nlm, -1),
                               phi1.reshape(-1, natm * nlm).T)
    Xvec1 = Xvec1.T.reshape(natm, 3, natm, nlm)

    psi1 = numpy.zeros((natm, 3, natm, nlm))
    i1 = 0
    for ia, (coords, weight,
             weight1) in enumerate(rks_grad.grids_response_cc(grids)):
        i0, i1 = i1, i1 + weight.size
        ao = mol.eval_gto('GTOval_sph_deriv1', coords)
        aow = numpy.einsum('gi,g->gi', ao[0], weight)
        aopair1 = lib.einsum('xgi,gj->xgij', ao[1:], aow)
        aow = numpy.einsum('gi,zxg->zxgi', ao[0], weight1)
        aopair0 = lib.einsum('zxgi,gj->zxgij', aow, ao[0])
        den0 = numpy.einsum('zxgij,ij->zxg', aopair0, dm)
        den1 = numpy.empty((natm, 3, weight.size))
        for ja in range(natm):
            shl0, shl1, p0, p1 = aoslices[ja]
            den1[ja] = numpy.einsum('xgij,ij->xg', aopair1[:, :, p0:p1],
                                    dm[p0:p1, :])
            den1[ja] += numpy.einsum('xgij,ji->xg', aopair1[:, :, p0:p1],
                                     dm[:, p0:p1])

        fak_pol, leak_idx = cached_pol[mol.atom_symbol(ia)]
        fac_pol = ddcosmo._vstack_factor_fak_pol(fak_pol, lmax)
        scaled_weights = lib.einsum('azm,mn->azn', Xvec1[:, :, ia], fac_pol)
        scaled_weights *= weight
        aow = numpy.einsum('gi,azg->azgi', ao[0], scaled_weights)
        Bx -= numpy.einsum('gi,azgj->azij', ao[0], aow)

        tmp = numpy.einsum('mn,zxn->zxm', fac_pol, den1)
        psi1[:, :, ia] -= numpy.einsum('mn,zxn->zxm', fac_pol, den0)
        psi1[ia, :, ia] -= tmp.sum(axis=0)
        for ja in range(natm):
            psi1[ja, :, ia] += tmp[ja]

        eta_nj = lib.einsum('mn,m->n', fac_pol, Xvec0[ia])
        Bx -= lib.einsum('n,zxnpq->zxpq', eta_nj, aopair0)
        vtmp = lib.einsum('n,xnpq->xpq', eta_nj, aopair1)
        Bx[ia] -= vtmp
        Bx[ia] -= vtmp.transpose(0, 2, 1)
        for ja in range(natm):
            shl0, shl1, q0, q1 = aoslices[ja]
            Bx[ja, :, q0:q1, :] += vtmp[:, q0:q1]
            Bx[ja, :, :, q0:q1] += vtmp[:, q0:q1].transpose(0, 2, 1)

    psi1 -= numpy.einsum('il,aziljm->azjm', LS0, L1)
    LS1 = numpy.linalg.solve(
        L.reshape(natm * nlm, -1).T,
        psi1.reshape(-1, natm * nlm).T)
    LS1 = LS1.T.reshape(natm, 3, natm, nlm)

    cav_coords = (atom_coords.reshape(natm, 1, 3) +
                  numpy.einsum('r,gx->rgx', r_vdw, coords_1sph))
    cav_coords = cav_coords[extern_point_idx]
    fakemol = gto.fakemol_for_charges(cav_coords)
    v_nj = df.incore.aux_e2(mol,
                            fakemol,
                            intor=int3c2e,
                            aosym='s1',
                            cintopt=cintopt)
    v_phi = numpy.zeros((natm, ngrid_1sph, nao, nao))
    v_phi[extern_point_idx] += v_nj.transpose(2, 0, 1)
    Bx += lib.einsum('azjx,n,xn,jn,jnpq->azpq', LS1, weights_1sph, ylm_1sph,
                     ui, v_phi)

    return Bx