Пример #1
0
    def _get_vind(self, dm):
        '''A single shot solvent effects for given density matrix.
        '''
        if not self._intermediates or self.grids.coords is None:
            self.build()

        mol = self.mol
        r_vdw = self._intermediates['r_vdw']
        ylm_1sph = self._intermediates['ylm_1sph']
        ui = self._intermediates['ui']
        Lmat = self._intermediates['Lmat']
        A_diele = self._intermediates['A_diele']
        A_inf = self._intermediates['A_inf']
        cached_pol = self._intermediates['cached_pol']

        if not (isinstance(dm, numpy.ndarray) and dm.ndim == 2):
            # spin-traced DM for UHF or ROHF
            dm = dm[0] + dm[1]

        phi = ddcosmo.make_phi(self, dm, r_vdw, ui, ylm_1sph)
        phi = numpy.linalg.solve(A_diele, A_inf.dot(phi.ravel()))

        Xvec = numpy.linalg.solve(Lmat, phi.ravel()).reshape(mol.natm, -1)
        psi, vmat = ddcosmo.make_psi_vmat(self, dm, r_vdw, ui, ylm_1sph,
                                          cached_pol, Xvec, Lmat)[:2]
        dielectric = self.eps
        f_epsilon = (dielectric - 1.) / dielectric
        epcm = .5 * f_epsilon * numpy.einsum('jx,jx', psi, Xvec)
        vpcm = .5 * f_epsilon * vmat
        return epcm, vpcm
Пример #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 _B_dot_x(self, dm):
        '''
        Compute the matrix-vector product B * x. The B matrix, as defined in
        the paper R. Cammi, JPCA, 104, 5631 (2000), is the second order
        derivatives of E_solvation wrt density matrices.

        Note: In ddCOSMO, strictly, B is not symmetric. To make it compatible
        with the CIS framework, it is symmetrized in current implementation.
        '''
        if not self._intermediates or self.grids.coords is None:
            self.build()

        mol = self.mol
        r_vdw      = self._intermediates['r_vdw'     ]
        ylm_1sph   = self._intermediates['ylm_1sph'  ]
        ui         = self._intermediates['ui'        ]
        Lmat       = self._intermediates['Lmat'      ]
        A_diele    = self._intermediates['A_diele'   ]
        A_inf      = self._intermediates['A_inf'     ]
        cached_pol = self._intermediates['cached_pol']
        natm = mol.natm
        nlm = (self.lmax+1)**2

        phi = ddcosmo.make_phi(self, dm, r_vdw, ui, ylm_1sph, with_nuc=False)
        phi = numpy.linalg.solve(A_diele, A_inf.dot(phi.reshape(-1,natm*nlm).T))

        Xvec = numpy.linalg.solve(Lmat, phi)
        Xvec = Xvec.reshape(natm,nlm,-1).transpose(2,0,1)
        vmat = ddcosmo.make_psi_vmat(self, dm, r_vdw, ui, ylm_1sph,
                                     cached_pol, Xvec, Lmat, with_nuc=False)[1]
        dielectric = self.eps
        f_epsilon = (dielectric-1.)/dielectric
        return .5 * f_epsilon * vmat
Пример #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 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
Пример #6
0
    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
Пример #7
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)
Пример #8
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)
Пример #9
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
Пример #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
Пример #11
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)