示例#1
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)
示例#2
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, ylm_1sph)
            L_X = numpy.linalg.solve(Lmat, phi.ravel()).reshape(natm, -1)
            psi, vmat, L_S = \
                    ddcosmo.make_psi_vmat(pcmobj, dm, r_vdw, ui, ylm_1sph,
                                          cached_pol, L_X, Lmat)
            phi1 = ddcosmo_grad.make_phi1(pcmobj, dm, r_vdw, ui, ylm_1sph)
            phi1 = numpy.einsum('izjx,jx->iz', phi1, L_S)
            return L_S, phi, phi1
示例#3
0
    def test_psi_vmat(self):
        pcm = ddcosmo.DDCOSMO(mol)
        pcm.lmax = 2
        pcm.eps = 0
        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()
        pcm.grids = grids
        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, 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.reshape(natm * nlm, -1).T,
                                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)
示例#4
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
示例#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)
示例#6
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)
示例#7
0
    def test_solvent_nuc(self):
        def get_nuc(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 nuc_part(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)
        dvmat = nuc_part1(pcm, r_vdw, ui, ylm_1sph, cached_pol, L)

        vmat1 = get_nuc(mol1)
        vmat2 = get_nuc(mol2)
        self.assertAlmostEqual(
            abs((vmat2 - vmat1) / dx - dvmat[0, 2]).max(), 0, 8)

        nao = mol0.nao
        numpy.random.seed(19)
        dm = numpy.random.random((nao, nao))
        vref = pcm._get_vind(dm)[1]
        vmat = 0.5 * get_nuc(mol0)
        vmat += pcm._B_dot_x(dm)
        self.assertAlmostEqual(abs(vmat - vref).max(), 0, 14)

        dm1 = numpy.random.random((2, nao, nao))
        de = _ddcosmo_tdscf_grad._grad_ne(pcm, dm1, r_vdw, ui, ylm_1sph,
                                          cached_pol, L)
        ref = numpy.einsum('azij,nij->naz', dvmat, dm1)
        self.assertAlmostEqual(abs(de - ref).max(), 0, 12)
示例#8
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)
示例#9
0
文件: ddpcm.py 项目: wmizukami/pyscf
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()))

        Xvec = 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, Xvec, Lmat)[:2]
        dielectric = pcmobj.eps
        f_epsilon = (dielectric - 1.) / dielectric
        epcm = .5 * f_epsilon * numpy.einsum('jx,jx', psi, Xvec)
        vpcm = .5 * f_epsilon * vmat
        return epcm, vpcm

    return gen_vind
示例#10
0
    def test_B_dot_x(self):
        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
        grids = dft.gen_grid.Grids(mol).run(level=0)
        pcm.grids = grids
        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)
        B = make_B(pcm, r_vdw, ui, ylm_1sph, cached_pol, L)

        numpy.random.seed(19)
        dm = numpy.random.random((2, nao, nao))
        Bx = numpy.einsum('ijkl,xkl->xij', B, dm)

        phi = ddcosmo.make_phi(pcm, dm, r_vdw, ui, ylm_1sph, with_nuc=False)
        Xvec = numpy.linalg.solve(L.reshape(natm * nlm, -1),
                                  phi.reshape(-1, natm * nlm).T)
        Xvec = Xvec.reshape(natm, nlm, -1).transpose(2, 0, 1)
        psi, vref, LS = ddcosmo.make_psi_vmat(pcm,
                                              dm,
                                              r_vdw,
                                              ui,
                                              ylm_1sph,
                                              cached_pol,
                                              Xvec,
                                              L,
                                              with_nuc=False)
        self.assertAlmostEqual(abs(Bx - vref).max(), 0, 12)
        e1 = numpy.einsum('nij,nij->n', psi, Xvec)
        e2 = numpy.einsum('nij,nij->n', phi, LS)
        e3 = numpy.einsum('nij,nij->n', dm, vref) * .5
        self.assertAlmostEqual(abs(e1 - e2).max(), 0, 12)
        self.assertAlmostEqual(abs(e1 - e3).max(), 0, 12)

        vmat = pcm._B_dot_x(dm)
        self.assertEqual(vmat.shape, (2, nao, nao))
        self.assertAlmostEqual(abs(vmat - vref * .5).max(), 0, 12)
        self.assertAlmostEqual(lib.fp(vmat), -17.383712106418606, 12)
示例#11
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)
示例#12
0
文件: ddpcm.py 项目: chrinide/pyscf
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
示例#13
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
示例#14
0
文件: ddpcm.py 项目: wmizukami/pyscf
    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,
        }
示例#15
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)
示例#16
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
示例#17
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
示例#18
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)