예제 #1
0
    def test_ddcosmo_scf(self):
        mol = gto.M(atom=''' H 0 0 0 ''',
                    charge=1,
                    basis='sto3g',
                    verbose=7,
                    output='/dev/null')
        pcm = ddcosmo.DDCOSMO(mol)
        pcm.lmax = 10
        pcm.lebedev_order = 29
        mf = ddcosmo.ddcosmo_for_scf(scf.RHF(mol), pcm)
        mf.init_guess = '1e'
        mf.run()
        self.assertAlmostEqual(mf.e_tot, -0.1645636146393864, 9)

        mol = gto.M(atom='''
               6        0.000000    0.000000   -0.542500
               8        0.000000    0.000000    0.677500
               1        0.000000    0.935307   -1.082500
               1        0.000000   -0.935307   -1.082500
                    ''',
                    basis='sto3g',
                    verbose=7,
                    output='/dev/null')
        pcm = ddcosmo.DDCOSMO(mol)
        pcm.lmax = 6
        pcm.lebedev_order = 17
        mf = ddcosmo.ddcosmo_for_scf(scf.RHF(mol), pcm).run()
        self.assertAlmostEqual(mf.e_tot, -112.35450855007909, 9)
예제 #2
0
 def test_e_cosmo_grad(self):
     pcmobj = ddcosmo.DDCOSMO(mol0)
     de = ddcosmo_grad.kernel(pcmobj, dm)
     pcmobj = ddcosmo.DDCOSMO(mol1)
     e1 = pcmobj.energy(dm)
     pcmobj = ddcosmo.DDCOSMO(mol2)
     e2 = pcmobj.energy(dm)
     self.assertAlmostEqual(abs((e2 - e1) / dx - de[0, 2]).max(), 0, 7)
예제 #3
0
def ddCOSMO(method_or_mol, solvent_obj=None, dm=None):
    '''Initialize ddCOSMO model.

    Examples:

    >>> mf = ddCOSMO(scf.RHF(mol))
    >>> mf.kernel()
    >>> sol = ddCOSMO(mol)
    >>> mc = ddCOSMO(CASCI(mf, 6, 6), sol)
    >>> mc.kernel()
    '''
    from pyscf import gto
    from pyscf import scf, mcscf
    from pyscf import tdscf

    if isinstance(method_or_mol, gto.mole.Mole):
        return ddcosmo.DDCOSMO(method_or_mol)

    elif isinstance(method_or_mol, scf.hf.SCF):
        return ddcosmo.ddcosmo_for_scf(method_or_mol, solvent_obj, dm)
    elif isinstance(method_or_mol, mcscf.mc1step.CASSCF):
        return ddcosmo.ddcosmo_for_casscf(method_or_mol, solvent_obj, dm)
    elif isinstance(method_or_mol, mcscf.casci.CASCI):
        return ddcosmo.ddcosmo_for_casci(method_or_mol, solvent_obj, dm)
    elif isinstance(method_or_mol, (tdscf.rhf.TDA, tdscf.rhf.TDHF)):
        return ddcosmo.ddcosmo_for_tdscf(method_or_mol, solvent_obj, dm)
    else:
        return ddcosmo.ddcosmo_for_post_scf(method_or_mol, solvent_obj, dm)
예제 #4
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)
예제 #5
0
    def test_e_psi1(self):
        def get_e_psi1(pcmobj):
            pcmobj.grids.build()
            mol = pcmobj.mol
            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

            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)
            psi1 = ddcosmo_grad.make_e_psi1(pcmobj, dm, r_vdw, ui,
                                            pcmobj.grids, ylm_1sph, cached_pol,
                                            L_X, Lmat)
            return L_X, psi, psi1

        pcmobj = ddcosmo.DDCOSMO(mol0)
        L_X, psi0, psi1 = get_e_psi1(pcmobj)

        pcmobj = ddcosmo.DDCOSMO(mol1)
        L_X1, psi = get_e_psi1(pcmobj)[:2]
        e1 = numpy.einsum('jx,jx', psi, L_X)

        pcmobj = ddcosmo.DDCOSMO(mol2)
        L_X2, psi = get_e_psi1(pcmobj)[:2]
        e2 = numpy.einsum('jx,jx', psi, L_X)
        self.assertAlmostEqual(abs((e2 - e1) / dx - psi1[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_fi(self):
        pcmobj = ddcosmo.DDCOSMO(mol0)
        fi1 = ddcosmo_grad.make_fi1(pcmobj, pcmobj.get_atomic_radii())
        ui1 = -fi1
        fi = ddcosmo.make_fi(pcmobj, pcmobj.get_atomic_radii())
        ui = 1 - fi
        ui1[:, :, ui < 0] = 0

        pcmobj = ddcosmo.DDCOSMO(mol1)
        fi_1 = ddcosmo.make_fi(pcmobj, pcmobj.get_atomic_radii())
        ui_1 = 1 - fi_1
        ui_1[ui_1 < 0] = 0

        pcmobj = ddcosmo.DDCOSMO(mol2)
        fi_2 = ddcosmo.make_fi(pcmobj, pcmobj.get_atomic_radii())
        ui_2 = 1 - fi_2
        ui_2[ui_2 < 0] = 0
        self.assertAlmostEqual(abs((fi_2 - fi_1) / dx - fi1[0, 2]).max(), 0, 6)
        self.assertAlmostEqual(abs((ui_2 - ui_1) / dx - ui1[0, 2]).max(), 0, 6)
예제 #9
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)
예제 #10
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)
예제 #11
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)
예제 #12
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)
예제 #13
0
def ddcosmo_grad(grad_method, pcmobj=None):
    grad_method_class = grad_method.__class__

    class WithSolventGrad(grad_method.__class__):
        def __init__(self, pcmobj):
            self.__dict__.update(grad_method.__dict__)
            self.with_solvent = pcmobj
            self.de_solvent = None
            self.de_solute = None
            self._keys = self._keys.union(
                ['with_solvent', 'de_solvent', 'de_solute'])

        def kernel(self, dm=None, atmlst=None):
            if dm is None:
                dm = grad_method.base.make_rdm1(ao_repr=True)

            # de_solvent needs to be called first because _finalize method
            # is called in the grad_method.kernel function.  de_solvent is
            # required by the _finalize method.
            self.de_solvent = kernel(self.with_solvent, dm)
            self.de_solute = grad_method_class.kernel(self, atmlst=atmlst)
            self.de = self.de_solute + self.de_solvent

            if self.verbose >= logger.NOTE:
                logger.note(
                    self, '--------------- %s (%s) gradients ---------------',
                    grad_method.base.__class__.__name__,
                    self.with_solvent.__class__.__name__)
                rhf_grad._write(self, self.mol, self.de, self.atmlst)
                logger.note(self,
                            '----------------------------------------------')
            return self.de

        def _finalize(self):
            # disable _finalize. It is called in grad_method.kernel method
            # where self.de was not yet initialized.
            pass

    if pcmobj is None:
        pcmobj = ddcosmo.DDCOSMO(mf.mol)
    return WithSolventGrad(pcmobj)
예제 #14
0
 def test_vmat(self):
     mol = gto.M(atom='H 0 0 0; H 0 1 1.2; H 1. .1 0; H .5 .5 1', verbose=0)
     pcmobj = ddcosmo.DDCOSMO(mol)
     f = pcmobj.as_solver()
     nao = mol.nao_nr()
     numpy.random.seed(1)
     dm1 = numpy.random.random((nao, nao))
     dm1 = dm1 + dm1.T
     e0, vmat0 = f(dm1)
     dx = 0.0001
     vmat1 = numpy.zeros_like(dm1)
     for i in range(nao):
         for j in range(i):
             dm1[i, j] += dx
             dm1[j, i] += dx
             e1 = f(dm1)[0]
             vmat1[i, j] = vmat1[j, i] = (e1 - e0) / (dx * 2)
             dm1[i, j] -= dx
             dm1[j, i] -= dx
         dm1[i, i] += dx
         e1 = f(dm1)[0]
         vmat1[i, i] = (e1 - e0) / dx
         dm1[i, i] -= dx
     self.assertAlmostEqual(abs(vmat0 - vmat1).max(), 0, 4)
예제 #15
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)