Ejemplo n.º 1
0
    def make_h10(self, mol=None, dm0=None, gauge_orig=None):
        if mol is None:
            mol = self.mol
        if dm0 is None:
            dm0 = self._scf.make_rdm1()
        if gauge_orig is None:
            gauge_orig = self.gauge_orig

        if gauge_orig is None:
            log = logger.Logger(self.stdout, self.verbose)
            log.debug("First-order GIAO Fock matrix")

            h1 = 0.5 * mol.intor("cint1e_giao_irjxp_sph", 3)
            h1 += mol.intor_asymmetric("cint1e_ignuc_sph", 3)
            h1 += mol.intor("cint1e_igkin_sph", 3)

            x_code, c_code = pyscf.dft.vxc.parse_xc_name(self._scf.xc)
            hyb = self._scf._numint.hybrid_coeff(x_code, spin=(mol.spin > 0) + 1)

            mem_now = pyscf.lib.current_memory()[0]
            max_memory = max(2000, self._scf.max_memory * 0.9 - mem_now)
            h1 += _get_vxc_giao(
                self._scf._numint,
                mol,
                self._scf.grids,
                x_code,
                c_code,
                dm0,
                max_memory=max_memory,
                verbose=self._scf.verbose,
            )

            if abs(hyb) > 1e-10:
                vj, vk = _vhf.direct_mapdm(
                    "cint2e_ig1_sph",  # (g i,j|k,l)
                    "a4ij",
                    ("lk->s1ij", "jk->s1il"),
                    dm0,
                    3,  # xyz, 3 components
                    mol._atm,
                    mol._bas,
                    mol._env,
                )
                vk = vk - vk.transpose(0, 2, 1)
                h1 += vj - 0.5 * hyb * vk
            else:
                vj = _vhf.direct_mapdm("cint2e_ig1_sph", "a4ij", "lk->s1ij", dm0, 3, mol._atm, mol._bas, mol._env)
                h1 += vj
        else:
            mol.set_common_origin_(gauge_orig)
            h1 = 0.5 * mol.intor("cint1e_cg_irxp_sph", 3)
        pyscf.lib.chkfile.dump(self.chkfile, "nmr/h1", h1)
        return h1
Ejemplo n.º 2
0
Archivo: uks.py Proyecto: pulkin/pyscf
    def make_h10(self, mol=None, dm0=None, gauge_orig=None):
        if mol is None: mol = self.mol
        if dm0 is None: dm0 = self._scf.make_rdm1()
        if gauge_orig is None: gauge_orig = self.gauge_orig

        if gauge_orig is None:
            log = logger.Logger(self.stdout, self.verbose)
            log.debug('First-order GIAO Fock matrix')

            mf = self._scf
            ni = mf._numint
            hyb = ni.hybrid_coeff(mf.xc, spin=mol.spin)

            mem_now = lib.current_memory()[0]
            max_memory = max(2000, mf.max_memory * .9 - mem_now)
            dm0 = _attach_mo(dm0, mf.mo_coeff,
                             mf.mo_occ)  # to improve get_vxc_giao efficiency
            h1 = -get_vxc_giao(ni,
                               mol,
                               mf.grids,
                               mf.xc,
                               dm0,
                               max_memory=max_memory,
                               verbose=mf.verbose)

            intor = mol._add_suffix('int2e_ig1')
            if abs(hyb) > 1e-10:
                vj, vk = _vhf.direct_mapdm(
                    intor,  # (g i,j|k,l)
                    'a4ij',
                    ('lk->s1ij', 'jk->s1il'),
                    dm0,
                    3,  # xyz, 3 components
                    mol._atm,
                    mol._bas,
                    mol._env)
                vk = vk - vk.transpose(0, 1, 3, 2)
                h1 -= vj[0] + vj[1] - hyb * vk
            else:
                vj = _vhf.direct_mapdm(intor, 'a4ij', 'lk->s1ij', dm0, 3,
                                       mol._atm, mol._bas, mol._env)
                h1 -= vj[0] + vj[1]

            h1 -= .5 * mol.intor('int1e_giao_irjxp', 3)
            h1 -= mol.intor_asymmetric('int1e_ignuc', 3)
            h1 -= mol.intor('int1e_igkin', 3)
        else:
            mol.set_common_origin(gauge_orig)
            h1 = -.5 * mol.intor('int1e_cg_irxp', 3)
            h1 = (h1, h1)
        lib.chkfile.dump(self.chkfile, 'nmr/h1', h1)
        return h1
Ejemplo n.º 3
0
 def test_direct_mapdm(self):
     numpy.random.seed(1)
     dm = numpy.random.random((nao,nao))
     eri0 = numpy.zeros((3,nmo,nmo,nmo,nmo))
     c_atm = numpy.array(mol._atm, dtype=numpy.int32)
     c_bas = numpy.array(mol._bas, dtype=numpy.int32)
     c_env = numpy.array(mol._env)
     i0 = 0
     for i in range(mol.nbas):
         j0 = 0
         for j in range(mol.nbas):
             k0 = 0
             for k in range(mol.nbas):
                 l0 = 0
                 for l in range(mol.nbas):
                     buf = gto.getints_by_shell('cint2e_ip1_sph', (i,j,k,l),
                                                c_atm, c_bas, c_env, 3)
                     di,dj,dk,dl = buf.shape[1:]
                     eri0[:,i0:i0+di,j0:j0+dj,k0:k0+dk,l0:l0+dl] = buf
                     l0 += dl
                 k0 += dk
             j0 += dj
         i0 += di
     vj0 = numpy.einsum('nijkl,lk->nij', eri0, dm)
     vk0 = numpy.einsum('nijkl,jk->nil', eri0, dm)
     vj1, vk1 = _vhf.direct_mapdm('cint2e_ip1_sph', 's2kl',
                                  ('lk->s1ij', 'jk->s1il'),
                                  dm, 3, mol._atm, mol._bas, mol._env)
     self.assertTrue(numpy.allclose(vj0,vj1))
     self.assertTrue(numpy.allclose(vk0,vk1))
Ejemplo n.º 4
0
Archivo: rhf.py Proyecto: zzy2014/pyscf
def get_jk(mol, dm):
    '''J = ((-nabla i) j| kl) D_lk
    K = ((-nabla i) j| kl) D_jk
    '''
    vhfopt = _vhf.VHFOpt(mol, 'int2e_ip1ip2', 'CVHFgrad_jk_prescreen',
                         'CVHFgrad_jk_direct_scf')
    dm = numpy.asarray(dm, order='C')
    if dm.ndim == 3:
        n_dm = dm.shape[0]
    else:
        n_dm = 1
    ao_loc = mol.ao_loc_nr()
    fsetdm = getattr(_vhf.libcvhf, 'CVHFgrad_jk_direct_scf_dm')
    fsetdm(vhfopt._this,
           dm.ctypes.data_as(ctypes.c_void_p), ctypes.c_int(n_dm),
           ao_loc.ctypes.data_as(ctypes.c_void_p),
           mol._atm.ctypes.data_as(ctypes.c_void_p), mol.natm,
           mol._bas.ctypes.data_as(ctypes.c_void_p), mol.nbas,
           mol._env.ctypes.data_as(ctypes.c_void_p))

    # Update the vhfopt's attributes intor.  Function direct_mapdm needs
    # vhfopt._intor and vhfopt._cintopt to compute J/K.  intor was initialized
    # as int2e_ip1ip2. It should be int2e_ip1
    vhfopt._intor = intor = mol._add_suffix('int2e_ip1')
    vhfopt._cintopt = None

    vj, vk = _vhf.direct_mapdm(intor,  # (nabla i,j|k,l)
                               's2kl', # ip1_sph has k>=l,
                               ('lk->s1ij', 'jk->s1il'),
                               dm, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env, vhfopt=vhfopt)
    return -vj, -vk
Ejemplo n.º 5
0
 def test_direct_mapdm(self):
     numpy.random.seed(1)
     dm = numpy.random.random((nao, nao))
     eri0 = numpy.zeros((3, nmo, nmo, nmo, nmo))
     c_atm = numpy.array(mol._atm, dtype=numpy.int32)
     c_bas = numpy.array(mol._bas, dtype=numpy.int32)
     c_env = numpy.array(mol._env)
     i0 = 0
     for i in range(mol.nbas):
         j0 = 0
         for j in range(mol.nbas):
             k0 = 0
             for k in range(mol.nbas):
                 l0 = 0
                 for l in range(mol.nbas):
                     buf = gto.getints_by_shell('int2e_ip1_sph',
                                                (i, j, k, l), c_atm, c_bas,
                                                c_env, 3)
                     di, dj, dk, dl = buf.shape[1:]
                     eri0[:, i0:i0 + di, j0:j0 + dj, k0:k0 + dk,
                          l0:l0 + dl] = buf
                     l0 += dl
                 k0 += dk
             j0 += dj
         i0 += di
     vj0 = numpy.einsum('nijkl,lk->nij', eri0, dm)
     vk0 = numpy.einsum('nijkl,jk->nil', eri0, dm)
     vj1, vk1 = _vhf.direct_mapdm('int2e_ip1_sph', 's2kl',
                                  ('lk->s1ij', 'jk->s1il'), dm, 3, mol._atm,
                                  mol._bas, mol._env)
     self.assertTrue(numpy.allclose(vj0, vj1))
     self.assertTrue(numpy.allclose(vk0, vk1))
Ejemplo n.º 6
0
def make_h1_soc2e(hfcobj, dm0):
    mf = hfcobj._scf
    ni = mf._numint
    hyb = ni.hybrid_coeff(mf.xc, spin=mol.spin)
    mem_now = lib.current_memory()[0]
    max_memory = max(2000, mf.max_memory * .9 - mem_now)
    v1 = get_vxc_soc(ni,
                     mol,
                     mf.grids,
                     mf.xc,
                     dm0,
                     max_memory=max_memory,
                     verbose=hfcobj.verbose)
    if abs(hyb) > 1e-10:
        vj, vk = uhf_hfc.get_jk(mol, dm0)
        v1 += vj[0] + vj[1]
        v1 -= vk * hyb
    else:
        vj = _vhf.direct_mapdm(mol._add_suffix('int2e_p1vxp1'), 'a4ij',
                               'lk->s2ij', dm0, 3, mol._atm, mol._bas,
                               mol._env)
        for i in range(3):
            lib.hermi_triu(vj[0, i], hermi=2, inplace=True)
            lib.hermi_triu(vj[1, i], hermi=2, inplace=True)
        v1 += vj[0] + vj[1]
    v1[1] *= -1
    return v1
Ejemplo n.º 7
0
def get_j(mol, dm0):
    vj = _vhf.direct_mapdm(mol._add_suffix('int2e_p1vxp1'), 'a4ij', 'lk->s2ij',
                           dm0, 3, mol._atm, mol._bas, mol._env)
    for i in range(3):
        lib.hermi_triu(vj[0, i], hermi=2, inplace=True)
        lib.hermi_triu(vj[1, i], hermi=2, inplace=True)
    return vj
Ejemplo n.º 8
0
    def make_h10(self, mol=None, dm0=None, gauge_orig=None):
        if mol is None: mol = self.mol
        if dm0 is None: dm0 = self._scf.make_rdm1()
        if gauge_orig is None: gauge_orig = self.gauge_orig

        if gauge_orig is None:
            log = logger.Logger(self.stdout, self.verbose)
            log.debug('First-order GIAO Fock matrix')

            h1 = .5 * mol.intor('cint1e_giao_irjxp_sph', 3)
            h1 += mol.intor_asymmetric('cint1e_ignuc_sph', 3)
            h1 += mol.intor('cint1e_igkin_sph', 3)

            libxc = self._scf._numint.libxc
            hyb = libxc.hybrid_coeff(self._scf.xc, spin=(mol.spin > 0) + 1)

            mem_now = pyscf.lib.current_memory()[0]
            max_memory = max(2000, self._scf.max_memory * .9 - mem_now)
            h1 += get_vxc_giao(self._scf._numint,
                               mol,
                               self._scf.grids,
                               self._scf.xc,
                               dm0,
                               max_memory=max_memory,
                               verbose=self._scf.verbose)

            if abs(hyb) > 1e-10:
                vj, vk = _vhf.direct_mapdm(
                    'cint2e_ig1_sph',  # (g i,j|k,l)
                    'a4ij',
                    ('lk->s1ij', 'jk->s1il'),
                    dm0,
                    3,  # xyz, 3 components
                    mol._atm,
                    mol._bas,
                    mol._env)
                vk = vk - vk.transpose(0, 2, 1)
                h1 += vj - .5 * hyb * vk
            else:
                vj = _vhf.direct_mapdm('cint2e_ig1_sph', 'a4ij', 'lk->s1ij',
                                       dm0, 3, mol._atm, mol._bas, mol._env)
                h1 += vj
        else:
            mol.set_common_origin(gauge_orig)
            h1 = .5 * mol.intor('cint1e_cg_irxp_sph', 3)
        pyscf.lib.chkfile.dump(self.chkfile, 'nmr/h1', h1)
        return h1
Ejemplo n.º 9
0
    def test_direct_mapdm1(self):
        numpy.random.seed(1)
        nao = mol.nao_nr(cart=True)
        dm = numpy.random.random((nao,nao))
        vhfopt = _vhf.VHFOpt(mol, 'int2e_cart', 'CVHFnrs8_prescreen',
                             'CVHFsetnr_direct_scf',
                             'CVHFsetnr_direct_scf_dm')
        vj0, vk0 = _vhf.direct(dm, mol._atm, mol._bas, mol._env,
                               vhfopt=vhfopt, hermi=0, cart=True)
        vj = _vhf.direct_mapdm('int2e_cart', 's1', 'kl->s1ij', dm, 1,
                               mol._atm, mol._bas, mol._env, vhfopt)
        self.assertTrue(numpy.allclose(vj0, vj))

        vk = _vhf.direct_mapdm('int2e_cart', 's1', 'jk->s1il', [dm]*2, 1,
                               mol._atm, mol._bas, mol._env, vhfopt)
        self.assertTrue(numpy.allclose(vk0, vk[0]))
        self.assertTrue(numpy.allclose(vk0, vk[1]))
Ejemplo n.º 10
0
def get_j(mol, dm0):
    vj = _vhf.direct_mapdm(mol._add_suffix('int2e_p1vxp1'),
                           'a4ij', 'lk->s2ij',
                           dm0, 3, mol._atm, mol._bas, mol._env)
    for i in range(3):
        lib.hermi_triu(vj[0,i], hermi=2, inplace=True)
        lib.hermi_triu(vj[1,i], hermi=2, inplace=True)
    return vj
Ejemplo n.º 11
0
def get_coulomb_hf(mol, dm):
    '''NR Hartree-Fock Coulomb repulsion'''
    #vj, vk = pyscf.scf.hf.get_vj_vk(pycint.nr_vhf_grad_o1, mol, dm)
    #return vj - vk*.5
    vj, vk = _vhf.direct_mapdm('cint2e_ip1_sph',  # (nabla i,j|k,l)
                               's2kl', # ip1_sph has k>=l,
                               ('lk->s1ij', 'jk->s1il'),
                               dm, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
    return -(vj - vk*.5)
Ejemplo n.º 12
0
def get_jk(mol, dm0):
    # K_{pq} = (pi|iq) + (iq|pi)
    vj, vk, vk1 = _vhf.direct_mapdm(mol._add_suffix('int2e_p1vxp1'),
                                    'a4ij', ('lk->s2ij', 'jk->s1il', 'li->s1kj'),
                                    dm0, 3, mol._atm, mol._bas, mol._env)
    for i in range(3):
        lib.hermi_triu(vj[0,i], hermi=2, inplace=True)
        lib.hermi_triu(vj[1,i], hermi=2, inplace=True)
    vk += vk1
    return vj, vk
Ejemplo n.º 13
0
def get_jk(mol, dm):
    '''J = ((-nabla i) j| kl) D_lk
    K = ((-nabla i) j| kl) D_jk
    '''
    vj, vk = _vhf.direct_mapdm('cint2e_ip1_sph',  # (nabla i,j|k,l)
                               's2kl', # ip1_sph has k>=l,
                               ('lk->s1ij', 'jk->s1il'),
                               dm, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
    return -vj, -vk
Ejemplo n.º 14
0
def get_jk(mol, dm0):
    # K_{pq} = (pi|iq) + (iq|pi)
    vj, vk, vk1 = _vhf.direct_mapdm(mol._add_suffix('int2e_p1vxp1'),
                                    'a4ij', ('lk->s2ij', 'jk->s1il', 'li->s1kj'),
                                    dm0, 3, mol._atm, mol._bas, mol._env)
    for i in range(3):
        lib.hermi_triu(vj[0,i], hermi=2, inplace=True)
        lib.hermi_triu(vj[1,i], hermi=2, inplace=True)
    vk += vk1
    return vj, vk
Ejemplo n.º 15
0
 def test_direct_mapdm(self):
     numpy.random.seed(1)
     dm = numpy.random.random((nao,nao))
     eri0 = mol.intor('int2e_ip1_sph', comp=3).reshape(3,nao,nao,nao,nao)
     vj0 = numpy.einsum('nijkl,lk->nij', eri0, dm)
     vk0 = numpy.einsum('nijkl,jk->nil', eri0, dm)
     vj1, vk1 = _vhf.direct_mapdm('int2e_ip1_sph', 's2kl',
                                  ('lk->s1ij', 'jk->s1il'),
                                  dm, 3, mol._atm, mol._bas, mol._env)
     self.assertTrue(numpy.allclose(vj0,vj1))
     self.assertTrue(numpy.allclose(vk0,vk1))
Ejemplo n.º 16
0
def get_jk(mol, dm0):
# J = Im[(i i|\mu g\nu) + (i gi|\mu \nu)] = -i (i i|\mu g\nu)
# K = Im[(\mu gi|i \nu) + (\mu i|i g\nu)]
#   = [-i (\mu g i|i \nu)] - h.c.   (-h.c. for anti-symm because of the factor -i)
    intor = mol._add_suffix('int2e_ig1')
    vj, vk = _vhf.direct_mapdm(intor,  # (g i,j|k,l)
                               'a4ij', ('lk->s1ij', 'jk->s1il'),
                               dm0, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
    vk = vk - numpy.swapaxes(vk, -1, -2)
    return -vj, -vk
Ejemplo n.º 17
0
def get_jk(mol, dm0):
# J = Im[(i i|\mu g\nu) + (i gi|\mu \nu)] = -i (i i|\mu g\nu)
# K = Im[(\mu gi|i \nu) + (\mu i|i g\nu)]
#   = [-i (\mu g i|i \nu)] - h.c.   (-h.c. for anti-symm because of the factor -i)
    intor = mol._add_suffix('int2e_ig1')
    vj, vk = _vhf.direct_mapdm(intor,  # (g i,j|k,l)
                               'a4ij', ('lk->s1ij', 'jk->s1il'),
                               dm0, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
    vk = vk - numpy.swapaxes(vk, -1, -2)
    return -vj, -vk
Ejemplo n.º 18
0
def get_jk(mol, dm):
    '''J = ((-nabla i) j| kl) D_lk
    K = ((-nabla i) j| kl) D_jk
    '''
    intor = mol._add_suffix('int2e_ip1')
    vj, vk = _vhf.direct_mapdm(intor,  # (nabla i,j|k,l)
                               's2kl', # ip1_sph has k>=l,
                               ('lk->s1ij', 'jk->s1il'),
                               dm, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
    return -vj, -vk
Ejemplo n.º 19
0
 def test_direct_bindm(self):
     numpy.random.seed(1)
     dm = numpy.random.random((nao,nao))
     vj0, vk0 = _vhf.direct_mapdm('cint2e_ip1_sph', 's2kl',
                                  ('lk->s1ij', 'jk->s1il'),
                                  dm, 3, mol._atm, mol._bas, mol._env)
     dms = (dm,dm)
     vj1, vk1 = _vhf.direct_bindm('cint2e_ip1_sph', 's2kl',
                                  ('lk->s1ij', 'jk->s1il'),
                                  dms, 3, mol._atm, mol._bas, mol._env)
     self.assertTrue(numpy.allclose(vj0,vj1))
     self.assertTrue(numpy.allclose(vk0,vk1))
Ejemplo n.º 20
0
 def test_direct_bindm(self):
     numpy.random.seed(1)
     dm = numpy.random.random((nao, nao))
     vj0, vk0 = _vhf.direct_mapdm('int2e_ip1_sph', 's2kl',
                                  ('lk->s1ij', 'jk->s1il'), dm, 3, mol._atm,
                                  mol._bas, mol._env)
     dms = (dm, dm)
     vj1, vk1 = _vhf.direct_bindm('int2e_ip1_sph', 's2kl',
                                  ('lk->s1ij', 'jk->s1il'), dms, 3,
                                  mol._atm, mol._bas, mol._env)
     self.assertTrue(numpy.allclose(vj0, vj1))
     self.assertTrue(numpy.allclose(vk0, vk1))
Ejemplo n.º 21
0
def make_h10giao(mol, dm0):
    vj, vk = _vhf.direct_mapdm('cint2e_ig1_sph',  # (g i,j|k,l)
                               'a4ij', ('lk->s1ij', 'jk->s1il'),
                               dm0, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
# J = i[(i i|\mu g\nu) + (i gi|\mu \nu)] = i (i i|\mu g\nu)
# K = i[(\mu gi|i \nu) + (\mu i|i g\nu)]
#   = (\mu g i|i \nu) - h.c.   anti-symm because of the factor i
    vk = vk - vk.transpose(0,2,1)
    h1 = vj - .5 * vk
    h1 += mol.intor_asymmetric('cint1e_ignuc_sph', 3)
    h1 += mol.intor('cint1e_igkin_sph', 3)
    return h1
Ejemplo n.º 22
0
def make_h10giao(mol, dm0):
    vj, vk = _vhf.direct_mapdm('cint2e_ig1_sph',  # (g i,j|k,l)
                               'a4ij', ('lk->s1ij', 'jk->s1il'),
                               dm0, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
# J = i[(i i|\mu g\nu) + (i gi|\mu \nu)] = i (i i|\mu g\nu)
# K = i[(\mu gi|i \nu) + (\mu i|i g\nu)]
#   = (\mu g i|i \nu) - h.c.   anti-symm because of the factor i
    vk = vk - vk.transpose(0,2,1)
    h1 = vj - .5 * vk
    h1 += mol.intor_asymmetric('cint1e_ignuc_sph', 3)
    h1 += mol.intor('cint1e_igkin_sph', 3)
    return h1
Ejemplo n.º 23
0
Archivo: uks.py Proyecto: MSwenne/BEP
def get_fock(nmrobj, dm0=None, gauge_orig=None):
    '''First order Fock matrix wrt external magnetic field'''
    if dm0 is None: dm0 = nmrobj._scf.make_rdm1()
    if gauge_orig is None: gauge_orig = nmrobj.gauge_orig

    mol = nmrobj.mol

    if gauge_orig is None:
        log = logger.Logger(nmrobj.stdout, nmrobj.verbose)
        log.debug('First-order GIAO Fock matrix')

        mf = nmrobj._scf
        ni = mf._numint
        omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin)

        mem_now = lib.current_memory()[0]
        max_memory = max(2000, mf.max_memory * .9 - mem_now)
        # Attach mo_coeff and mo_occ to improve get_vxc_giao efficiency
        dm0 = lib.tag_array(dm0, mo_coeff=mf.mo_coeff, mo_occ=mf.mo_occ)
        h1 = -get_vxc_giao(ni,
                           mol,
                           mf.grids,
                           mf.xc,
                           dm0,
                           max_memory=max_memory,
                           verbose=nmrobj.verbose)

        intor = mol._add_suffix('int2e_ig1')
        if abs(hyb) > 1e-10:
            vj, vk = rhf_nmr.get_jk(mol, dm0)
            h1 += vj[0] + vj[1] - hyb * vk
            if abs(omega) > 1e-10:
                with mol.with_range_coulomb(omega):
                    h1 -= (alpha - hyb) * rhf_nmr.get_jk(mol, dm0)[1]
        else:
            vj = _vhf.direct_mapdm(intor, 'a4ij', 'lk->s1ij', dm0, 3, mol._atm,
                                   mol._bas, mol._env)
            h1 -= vj[0] + vj[1]

        h1 -= .5 * mol.intor('int1e_giao_irjxp', 3)
        h1 -= mol.intor_asymmetric('int1e_ignuc', 3)
        if mol.has_ecp():
            h1 -= mol.intor_asymmetric('ECPscalar_ignuc', 3)
        h1 -= mol.intor('int1e_igkin', 3)
    else:
        with mol.with_common_origin(gauge_orig):
            h1 = -.5 * mol.intor('int1e_cg_irxp', 3)
            h1 = (h1, h1)
    if nmrobj.chkfile:
        lib.chkfile.dump(nmrobj.chkfile, 'nmr/h1', h1)
    return h1
Ejemplo n.º 24
0
    def make_h10(self, mol=None, dm0=None, gauge_orig=None):
        if mol is None: mol = self.mol
        if dm0 is None: dm0 = self._scf.make_rdm1()
        if gauge_orig is None: gauge_orig = self.gauge_orig

        if gauge_orig is None:
            log = logger.Logger(self.stdout, self.verbose)
            log.debug('First-order GIAO Fock matrix')

            h1 = .5 * mol.intor('cint1e_giao_irjxp_sph', 3)
            h1 += mol.intor_asymmetric('cint1e_ignuc_sph', 3)
            h1 += mol.intor('cint1e_igkin_sph', 3)

            libxc = self._scf._numint.libxc
            hyb = libxc.hybrid_coeff(self._scf.xc, spin=(mol.spin>0)+1)

            mem_now = pyscf.lib.current_memory()[0]
            max_memory = max(2000, self._scf.max_memory*.9-mem_now)
            h1 += get_vxc_giao(self._scf._numint, mol, self._scf.grids,
                               self._scf.xc, dm0, max_memory=max_memory,
                               verbose=self._scf.verbose)

            if abs(hyb) > 1e-10:
                vj, vk = _vhf.direct_mapdm('cint2e_ig1_sph',  # (g i,j|k,l)
                                           'a4ij', ('lk->s1ij', 'jk->s1il'),
                                           dm0, 3, # xyz, 3 components
                                           mol._atm, mol._bas, mol._env)
                vk = vk - vk.transpose(0,2,1)
                h1 += vj - .5 * hyb * vk
            else:
                vj = _vhf.direct_mapdm('cint2e_ig1_sph', 'a4ij', 'lk->s1ij',
                                       dm0, 3, mol._atm, mol._bas, mol._env)
                h1 += vj
        else:
            mol.set_common_origin_(gauge_orig)
            h1 = .5 * mol.intor('cint1e_cg_irxp_sph', 3)
        pyscf.lib.chkfile.dump(self.chkfile, 'nmr/h1', h1)
        return h1
Ejemplo n.º 25
0
def get_veff_(ks, mol, dm):
    '''Coulomb + XC functional
    '''
    t0 = (time.clock(), time.time())
    assert(dm.ndim == 2)
    nao = dm.shape[0]

    if ks.grids.coords is None:
        ks.grids.build_()
    grids = ks.grids
    if ks._numint.non0tab is None:
        ks._numint.non0tab = ks._numint.make_mask(mol, ks.grids.coords)
    x_code, c_code = pyscf.dft.vxc.parse_xc_name(ks.xc)
    hyb = pyscf.dft.vxc.hybrid_coeff(x_code, spin=(mol.spin>0)+1)

    mem_now = pyscf.lib.current_memory()[0]
    max_memory = max(2000, ks.max_memory*.9-mem_now)
    vxc = _get_vxc(ks._numint, mol, ks.grids, x_code, c_code, dm,
                   max_memory=max_memory, verbose=ks.verbose)
    t0 = logger.timer(ks, 'vxc', *t0)

    if abs(hyb) < 1e-10:
        vj = _vhf.direct_mapdm('cint2e_ip1_sph',  # (nabla i,j|k,l)
                               's2kl', # ip1_sph has k>=l,
                               ('lk->s1ij',),
                               dm, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
        vhf = vj
    else:
        vj, vk = _vhf.direct_mapdm('cint2e_ip1_sph',  # (nabla i,j|k,l)
                                   's2kl', # ip1_sph has k>=l,
                                   ('lk->s1ij', 'jk->s1il'),
                                   dm, 3, # xyz, 3 components
                                   mol._atm, mol._bas, mol._env)
        vhf = vj - vk * (hyb * .5)

    return -(vhf + vxc)
Ejemplo n.º 26
0
Archivo: rhf.py Proyecto: pulkin/pyscf
def make_h10giao(mol, dm0):
# J = Im[(i i|\mu g\nu) + (i gi|\mu \nu)] = -i (i i|\mu g\nu)
# K = Im[(\mu gi|i \nu) + (\mu i|i g\nu)]
#   = [-i (\mu g i|i \nu)] - h.c.   (-h.c. for anti-symm because of the factor -i)
    intor = mol._add_suffix('int2e_ig1')
    vj, vk = _vhf.direct_mapdm(intor,  # (g i,j|k,l)
                               'a4ij', ('lk->s1ij', 'jk->s1il'),
                               -dm0, 3, # xyz, 3 components
                               mol._atm, mol._bas, mol._env)
    vk = vk - vk.transpose(0,2,1)
    h1 = vj - .5 * vk
# Im[<g\mu|H|g\nu>] = -i * (gnuc + gkin)
    h1 -= mol.intor_asymmetric('int1e_ignuc', 3)
    h1 -= mol.intor('int1e_igkin', 3)
    return h1
Ejemplo n.º 27
0
def make_h10giao(mol, dm0):
    intor = mol._add_suffix('int2e_ig1')
    vj, vk = _vhf.direct_mapdm(
        intor,  # (g i,j|k,l)
        'a4ij',
        ('lk->s1ij', 'jk->s1il'),
        -dm0,
        3,  # xyz, 3 components
        mol._atm,
        mol._bas,
        mol._env)
    vk = vk - vk.transpose(0, 1, 3, 2)
    h1 = vj[0] + vj[1] - vk
    h1 -= mol.intor_asymmetric('int1e_ignuc', 3)
    h1 -= mol.intor('int1e_igkin', 3)
    return h1
Ejemplo n.º 28
0
def get_fock(nmrobj, dm0=None, gauge_orig=None):
    '''First order Fock matrix wrt external magnetic field'''
    if dm0 is None: dm0 = nmrobj._scf.make_rdm1()
    if gauge_orig is None: gauge_orig = nmrobj.gauge_orig

    mol = nmrobj.mol

    if gauge_orig is None:
        log = logger.Logger(nmrobj.stdout, nmrobj.verbose)
        log.debug('First-order GIAO Fock matrix')

        mf = nmrobj._scf
        ni = mf._numint
        omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=mol.spin)

        mem_now = lib.current_memory()[0]
        max_memory = max(2000, mf.max_memory*.9-mem_now)
        # Attach mo_coeff and mo_occ to improve get_vxc_giao efficiency
        dm0 = lib.tag_array(dm0, mo_coeff=mf.mo_coeff, mo_occ=mf.mo_occ)
        h1 = -get_vxc_giao(ni, mol, mf.grids, mf.xc, dm0,
                           max_memory=max_memory, verbose=nmrobj.verbose)

        intor = mol._add_suffix('int2e_ig1')
        if abs(hyb) > 1e-10:
            vj, vk = rhf_nmr.get_jk(mol, dm0)
            h1 += vj[0] + vj[1] - hyb * vk
            if abs(omega) > 1e-10:
                with mol.with_range_coulomb(omega):
                    h1 -= (alpha-hyb) * rhf_nmr.get_jk(mol, dm0)[1]
        else:
            vj = _vhf.direct_mapdm(intor, 'a4ij', 'lk->s1ij',
                                   dm0, 3, mol._atm, mol._bas, mol._env)
            h1 -= vj[0] + vj[1]

        h1 -= .5 * mol.intor('int1e_giao_irjxp', 3)
        h1 -= mol.intor_asymmetric('int1e_ignuc', 3)
        if mol.has_ecp():
            h1 -= mol.intor_asymmetric('ECPscalar_ignuc', 3)
        h1 -= mol.intor('int1e_igkin', 3)
    else:
        with mol.with_common_origin(gauge_orig):
            h1 = -.5 * mol.intor('int1e_cg_irxp', 3)
            h1 = (h1, h1)
    if nmrobj.chkfile:
        lib.chkfile.dump(nmrobj.chkfile, 'nmr/h1', h1)
    return h1
Ejemplo n.º 29
0
    def make_h10(self, mol=None, dm0=None, gauge_orig=None):
        if mol is None: mol = self.mol
        if dm0 is None: dm0 = self._scf.make_rdm1()
        if gauge_orig is None: gauge_orig = self.gauge_orig

        if gauge_orig is None:
            log = logger.Logger(self.stdout, self.verbose)
            log.debug('First-order GIAO Fock matrix')

            h1 = -.5 * mol.intor('int1e_giao_irjxp', 3)
            h1 -= mol.intor_asymmetric('int1e_ignuc', 3)
            h1 -= mol.intor('int1e_igkin', 3)

            mf = self._scf
            ni = mf._numint
            hyb = ni.hybrid_coeff(mf.xc, spin=mol.spin)

            mem_now = lib.current_memory()[0]
            max_memory = max(2000, mf.max_memory * .9 - mem_now)
            # Attach mo_coeff and mo_occ to improve get_vxc_giao efficiency
            dm0 = lib.tag_array(dm0, mo_coeff=mf.mo_coeff, mo_occ=mf.mo_occ)
            h1 -= get_vxc_giao(ni,
                               mol,
                               mf.grids,
                               mf.xc,
                               dm0,
                               max_memory=max_memory,
                               verbose=self.verbose)

            intor = mol._add_suffix('int2e_ig1')
            if abs(hyb) > 1e-10:
                vj, vk = rhf_nmr.get_jk(mol, dm0)
                h1 += vj - .5 * hyb * vk
            else:
                vj = _vhf.direct_mapdm(intor, 'a4ij', 'lk->s1ij', dm0, 3,
                                       mol._atm, mol._bas, mol._env)
                h1 -= vj
        else:
            mol.set_common_origin(gauge_orig)
            h1 = -.5 * mol.intor('int1e_cg_irxp', 3)
        lib.chkfile.dump(self.chkfile, 'nmr/h1', h1)
        return h1
Ejemplo n.º 30
0
def make_dia_gc2e(gobj, dm0, gauge_orig, sso_qed_fac=1):
    '''Note the side effects of set_common_origin'''

    if (isinstance(gobj.dia_soc2e, str) and
        ('SOMF' in gobj.dia_soc2e.upper() or 'AMFI' in gobj.dia_soc2e.upper())):
        raise NotImplementedError(gobj.dia_soc2e)
    if isinstance(gobj.dia_soc2e, str):
        with_sso = 'SSO' in gobj.dia_soc2e.upper()
        with_soo = 'SOO' in gobj.dia_soc2e.upper()
    else:
        with_sso = with_soo = True

    mol = gobj.mol
    dma, dmb = dm0
    effspin = mol.spin * .5
    muB = .5  # Bohr magneton
    alpha2 = nist.ALPHA ** 2
    #sso_qed_fac = (nist.G_ELECTRON - 1)

    # int2e_ip1v_r1 = (ij|\frac{\vec{r}_{12}}{r_{12}^3} \vec{r}_1|kl)
    if gauge_orig is None:
        intor = mol._add_suffix('int2e_ip1v_r1')
    else:
        mol.set_common_origin(gauge_orig)
        intor = mol._add_suffix('int2e_ip1v_rc1')
    vj, vk = _vhf.direct_mapdm(intor,
                               's2kl', ('lk->s1ij', 'jk->s1il'),
                               (dma, dmb), 9,
                               mol._atm, mol._bas, mol._env)
    ek = numpy.einsum('xil,li->x', vk[0], dma)
    ek-= numpy.einsum('xil,li->x', vk[1], dmb)
    ek = ek.reshape(3,3)
    gc2e = 0
    if with_sso:
        # spin-density should be contracted to electron 1 (associated to operator r1)
        ej = numpy.einsum('xij,ji->x', vj[0]+vj[1], dma-dmb).reshape(3,3)
        gc2e += sso_qed_fac * (ej - ek)
    if with_soo:
        # spin-density should be contracted to electron 2
        ej = numpy.einsum('xij,ji->x', vj[0]-vj[1], dma+dmb).reshape(3,3)
        gc2e += 2 * (ej - ek)
    gc2e -= numpy.eye(3) * gc2e.trace()
    gc2e *= (alpha2/8) / effspin / muB

    #   ([GIAO-i j] + [i GIAO-j]|\frac{\vec{r}_{12}}{r_{12}^3} x p1|kl)
    # + (ij|\frac{\vec{r}_{12}}{r_{12}^3} x p1|[GIAO-k l] + [k GIAO-l])
    if gauge_orig is None:
        nao = dma.shape[0]
        vj, vk = _vhf.direct_mapdm(mol._add_suffix('int2e_ipvg1_xp1'),
                                   's2kl', ('lk->s1ij', 'jk->s1il'),
                                   (dma, dmb), 9,
                                   mol._atm, mol._bas, mol._env)
        vk1 = _vhf.direct_mapdm(mol._add_suffix('int2e_ipvg2_xp1'),
                                   'aa4', 'jk->s1il',
                                   (dma, dmb), 9,
                                   mol._atm, mol._bas, mol._env)
        vj = vj.reshape(2,3,3,nao,nao)
        vk = vk.reshape(2,3,3,nao,nao)
        vk += vk1.reshape(2,3,3,nao,nao).transpose(0,2,1,3,4)
        ek = numpy.einsum('xyij,ji->xy', vk[0], dma)
        ek-= numpy.einsum('xyij,ji->xy', vk[1], dmb)
        dia_giao = 0
        if with_sso:
            ej = numpy.einsum('xyij,ji->xy', vj[0]+vj[1], dma-dmb)
            dia_giao += sso_qed_fac * (ej - ek)
        if with_soo:
            ej = numpy.einsum('xyij,ji->xy', vj[0]-vj[1], dma+dmb)
            dia_giao += 2 * (ej - ek)
        gc2e -= dia_giao * (alpha2/4) / effspin / muB

    if gobj.mb:  # correction of order c^{-2} from MB basis
        vj, vk = gobj._scf.get_jk(mol, dm0)
        vhf = vj[0] + vj[1] - vk
        gc_mb = numpy.einsum('ij,ji', vhf[0], dma)
        gc_mb-= numpy.einsum('ij,ji', vhf[1], dmb)
        gc2e += gc_mb * (alpha2/4) / effspin / muB * numpy.eye(3)

    return gc2e
Ejemplo n.º 31
0
Archivo: rhf.py Proyecto: eronca/pyscf
def hess_elec(hess_mf, mo_energy=None, mo_coeff=None, mo_occ=None,
              atmlst=None, max_memory=4000, verbose=None):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(hess_mf.stdout, hess_mf.verbose)

    time0 = (time.clock(), time.time())

    mf = hess_mf._scf
    mol = hess_mf.mol
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_occ is None:    mo_occ = mf.mo_occ
    if mo_coeff is None:  mo_coeff = mf.mo_coeff
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    mocc = mo_coeff[:,mo_occ>0]
    nocc = mocc.shape[1]
    dm0 = numpy.dot(mocc, mocc.T) * 2

    h1aos = hess_mf.make_h1(mo_coeff, mo_occ, hess_mf.chkfile, atmlst, log)
    t1 = log.timer('making H1', *time0)
    mo1s, e1s = hess_mf.solve_mo1(mo_energy, mo_coeff, mo_occ, h1aos,
                                  None, atmlst, max_memory, log)
    t1 = log.timer('solving MO1', *t1)

    tmpf = tempfile.NamedTemporaryFile(dir=lib.param.TMPDIR)
    with h5py.File(tmpf.name, 'w') as f:
        for i0, ia in enumerate(atmlst):
            mol.set_rinv_origin(mol.atom_coord(ia))
            f['rinv2aa/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_ipiprinv_sph', comp=9))
            f['rinv2ab/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_iprinvip_sph', comp=9))

    h1aa =(mol.intor('cint1e_ipipkin_sph', comp=9) +
           mol.intor('cint1e_ipipnuc_sph', comp=9))
    h1ab =(mol.intor('cint1e_ipkinip_sph', comp=9) +
           mol.intor('cint1e_ipnucip_sph', comp=9))
    s1aa = mol.intor('cint1e_ipipovlp_sph', comp=9)
    s1ab = mol.intor('cint1e_ipovlpip_sph', comp=9)
    s1a =-mol.intor('cint1e_ipovlp_sph', comp=3)

    # Energy weighted density matrix
    dme0 = numpy.einsum('pi,qi,i->pq', mocc, mocc, mo_energy[:nocc]) * 2

    vj1, vk1 = _vhf.direct_mapdm('cint2e_ipip1_sph', 's2kl',
                                 ('lk->s1ij', 'jk->s1il'), dm0, 9,
                                 mol._atm, mol._bas, mol._env)
    vhf1ii = vj1 - vk1*.5
    vj1 = vk1 = None
    t1 = log.timer('contracting cint2e_ipip1_sph', *t1)

    offsetdic = mol.offset_nr_by_atom()
    frinv = h5py.File(tmpf.name, 'r')
    rinv2aa = frinv['rinv2aa']
    rinv2ab = frinv['rinv2ab']

    de2 = numpy.zeros((mol.natm,mol.natm,3,3))
    for i0, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        h_2 = rinv2ab[str(ia)] + rinv2aa[str(ia)].value.transpose(0,2,1)
        h_2[:,p0:p1] += h1ab[:,p0:p1]
        s1ao = numpy.zeros((3,nao,nao))
        s1ao[:,p0:p1] += s1a[:,p0:p1]
        s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
        s1oo = numpy.einsum('xpq,pi,qj->xij', s1ao, mocc, mocc)

        shls_slice = (shl0, shl1) + (0, mol.nbas)*3
        vj1, vk1, vk2 = _vhf.direct_bindm('cint2e_ip1ip2_sph', 's1',
                                          ('ji->s1kl', 'li->s1kj', 'lj->s1ki'),
                                          (dm0[:,p0:p1], dm0[:,p0:p1], dm0), 9,
                                          mol._atm, mol._bas, mol._env,
                                          shls_slice=shls_slice)
        vhf2 = vj1 * 2 - vk1 * .5
        vhf2[:,:,p0:p1] -= vk2 * .5
        t1 = log.timer('contracting cint2e_ip1ip2_sph for atom %d'%ia, *t1)

        vj1, vk1 = _vhf.direct_bindm('cint2e_ipvip1_sph', 's2kl',
                                     ('lk->s1ij', 'li->s1kj'),
                                     (dm0, dm0[:,p0:p1]), 9,
                                     mol._atm, mol._bas, mol._env,
                                     shls_slice=shls_slice)
        vhf2[:,:,p0:p1] += vj1.transpose(0,2,1)
        vhf2 -= vk1.transpose(0,2,1) * .5
        vj1 = vk1 = vk2 = None
        t1 = log.timer('contracting cint2e_ipvip1_sph for atom %d'%ia, *t1)

        for j0, ja in enumerate(atmlst):
            q0, q1 = offsetdic[ja][2:]
# *2 for double occupancy, *2 for +c.c.
            mo1  = lib.chkfile.load(hess_mf.chkfile, 'scf_mo1/%d'%ja)
            h1ao = lib.chkfile.load(hess_mf.chkfile, 'scf_h1ao/%d'%ia)
            dm1 = numpy.einsum('ypi,qi->ypq', mo1, mocc)
            de  = numpy.einsum('xpq,ypq->xy', h1ao, dm1) * 4
            dm1 = numpy.einsum('ypi,qi,i->ypq', mo1, mocc, mo_energy[:nocc])
            de -= numpy.einsum('xpq,ypq->xy', s1ao, dm1) * 4
            de -= numpy.einsum('xpq,ypq->xy', s1oo, e1s[j0]) * 2

            de = de.reshape(-1)
            v2aa = rinv2aa[str(ja)].value
            v2ab = rinv2ab[str(ja)].value
            de += numpy.einsum('xpq,pq->x', v2aa[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', v2ab[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', h_2[:,:,q0:q1], dm0[:,q0:q1])*2
            de += numpy.einsum('xpq,pq->x', vhf2[:,q0:q1], dm0[q0:q1])*2
            de -= numpy.einsum('xpq,pq->x', s1ab[:,p0:p1,q0:q1], dme0[p0:p1,q0:q1])*2

            if ia == ja:
                de += numpy.einsum('xpq,pq->x', h1aa[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', v2aa, dm0)*2
                de -= numpy.einsum('xpq,pq->x', v2ab, dm0)*2
                de += numpy.einsum('xpq,pq->x', vhf1ii[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', s1aa[:,p0:p1], dme0[p0:p1])*2

            de2[i0,j0] = de.reshape(3,3)

    frinv.close()
    log.timer('RHF hessian', *time0)
    return de2
Ejemplo n.º 32
0
Archivo: rks.py Proyecto: v1j4y/pyscf
def hess_elec(hess_mf, mo_energy=None, mo_coeff=None, mo_occ=None,
              atmlst=None, max_memory=4000, verbose=None):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(hess_mf.stdout, hess_mf.verbose)

    time0 = (time.clock(), time.time())

    mf = hess_mf._scf
    mol = hess_mf.mol
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_occ is None:    mo_occ = mf.mo_occ
    if mo_coeff is None:  mo_coeff = mf.mo_coeff
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    nocc = int(mo_occ.sum()) // 2
    mocc = mo_coeff[:,:nocc]
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    ni = copy.copy(mf._numint)
    if USE_XCFUN:
        try:
            ni.libxc = dft.xcfun
            xctype = ni._xc_type(mf.xc)
        except (ImportError, KeyError, NotImplementedError):
            ni.libxc = dft.libxc
            xctype = ni._xc_type(mf.xc)
    else:
        xctype = ni._xc_type(mf.xc)
    grids = mf.grids
    hyb = ni.libxc.hybrid_coeff(mf.xc)
    max_memory = 4000

    h1aos = hess_mf.make_h1(mo_coeff, mo_occ, hess_mf.chkfile, atmlst, log)
    t1 = log.timer('making H1', *time0)
    def fx(mo1):
        # *2 for alpha + beta
        dm1 = numpy.einsum('xai,pa,qi->xpq', mo1, mo_coeff, mocc*2)
        dm1 = dm1 + dm1.transpose(0,2,1)
        vindxc = _contract_xc_kernel(mf, mf.xc, dm1, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, dm1)
            veff = vj - hyb * .5 * vk + vindxc
        else:
            vj = mf.get_j(mol, dm1)
            veff = vj + vindxc
        v1 = numpy.einsum('xpq,pa,qi->xai', veff, mo_coeff, mocc)
        return v1.reshape(v1.shape[0],-1)
    mo1s, e1s = hess_mf.solve_mo1(mo_energy, mo_coeff, mo_occ, h1aos,
                                  fx, atmlst, max_memory, log)
    t1 = log.timer('solving MO1', *t1)

    tmpf = tempfile.NamedTemporaryFile()
    with h5py.File(tmpf.name, 'w') as f:
        for i0, ia in enumerate(atmlst):
            mol.set_rinv_origin_(mol.atom_coord(ia))
            f['rinv2aa/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_ipiprinv_sph', comp=9))
            f['rinv2ab/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_iprinvip_sph', comp=9))

    h1aa =(mol.intor('cint1e_ipipkin_sph', comp=9) +
           mol.intor('cint1e_ipipnuc_sph', comp=9))
    h1ab =(mol.intor('cint1e_ipkinip_sph', comp=9) +
           mol.intor('cint1e_ipnucip_sph', comp=9))
    s1aa = mol.intor('cint1e_ipipovlp_sph', comp=9)
    s1ab = mol.intor('cint1e_ipovlpip_sph', comp=9)
    s1a =-mol.intor('cint1e_ipovlp_sph', comp=3)

    # Energy weighted density matrix
    dme0 = numpy.einsum('pi,qi,i->pq', mocc, mocc, mo_energy[:nocc]) * 2

    if abs(hyb) > 1e-10:
        vj1, vk1 = _vhf.direct_mapdm('cint2e_ipip1_sph', 's2kl',
                                     ('lk->s1ij', 'jk->s1il'), dm0, 9,
                                     mol._atm, mol._bas, mol._env)
        veff1ii = vj1 - hyb * .5 * vk1
    else:
        vj1 = _vhf.direct_mapdm('cint2e_ipip1_sph', 's2kl', 'lk->s1ij', dm0, 9,
                                mol._atm, mol._bas, mol._env)
        veff1ii = vj1.copy()
    vj1[:] = 0
    if xctype == 'LDA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
            for i in range(6):
                vj1[i] += pyscf.lib.dot(ao[i+4].T, aow)
            aow = aow1 = None
    elif xctype == 'GGA':
        ao_deriv = 3
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]
            vrho, vgamma = vxc[:2]
            wv = numpy.empty_like(rho)
            wv[0]  = weight * vrho
            wv[1:] = rho[1:] * (weight * vgamma * 2)
            aow = numpy.einsum('npi,np->pi', ao[:4], wv)
            for i in range(6):
                vj1[i] += pyscf.lib.dot(ao[i+4].T, aow)
            aow = numpy.einsum('npi,np->pi', ao[[XXX,XXY,XXZ]], wv[1:4])
            vj1[0] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XXY,XYY,XYZ]], wv[1:4])
            vj1[1] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XXZ,XYZ,XZZ]], wv[1:4])
            vj1[2] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XYY,YYY,YYZ]], wv[1:4])
            vj1[3] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XYZ,YYZ,YZZ]], wv[1:4])
            vj1[4] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XZZ,YZZ,ZZZ]], wv[1:4])
            vj1[5] += pyscf.lib.dot(aow.T, ao[0])
            rho = vxc = vrho = vgamma = wv = aow = None
    else:
        raise NotImplementedError('meta-GGA')
    veff1ii += vj1[[0,1,2,1,3,4,2,4,5]]
    vj1 = vk1 = None

    t1 = log.timer('contracting cint2e_ipip1_sph', *t1)

    offsetdic = mol.offset_nr_by_atom()
    frinv = h5py.File(tmpf.name, 'r')
    rinv2aa = frinv['rinv2aa']
    rinv2ab = frinv['rinv2ab']

    de2 = numpy.zeros((mol.natm,mol.natm,3,3))
    for i0, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        h_2 = rinv2ab[str(ia)] + rinv2aa[str(ia)].value.transpose(0,2,1)
        h_2[:,p0:p1] += h1ab[:,p0:p1]
        s1ao = numpy.zeros((3,nao,nao))
        s1ao[:,p0:p1] += s1a[:,p0:p1]
        s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
        s1oo = numpy.einsum('xpq,pi,qj->xij', s1ao, mocc, mocc)

        shls_offset = (shl0, shl1) + (0, mol.nbas)*3
        if abs(hyb) > 1e-10:
            vj1, vk1, vk2 = _vhf.direct_bindm('cint2e_ip1ip2_sph', 's1',
                                              ('ji->s1kl', 'li->s1kj', 'lj->s1ki'),
                                              (dm0[:,p0:p1], dm0[:,p0:p1], dm0), 9,
                                              mol._atm, mol._bas, mol._env,
                                              shls_offset=shls_offset)
            veff2 = vj1 * 2 - hyb * .5 * vk1
            veff2[:,:,p0:p1] -= hyb * .5 * vk2
            t1 = log.timer('contracting cint2e_ip1ip2_sph for atom %d'%ia, *t1)

            vj1, vk1 = _vhf.direct_bindm('cint2e_ipvip1_sph', 's2kl',
                                         ('lk->s1ij', 'li->s1kj'),
                                         (dm0, dm0[:,p0:p1]), 9,
                                         mol._atm, mol._bas, mol._env,
                                         shls_offset=shls_offset)
            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)
            veff2 -= hyb * .5 * vk1.transpose(0,2,1)
            vj1 = vk1 = vk2 = None
            t1 = log.timer('contracting cint2e_ipvip1_sph for atom %d'%ia, *t1)
        else:
            vj1 = _vhf.direct_bindm('cint2e_ip1ip2_sph', 's1',
                                    'ji->s1kl', dm0[:,p0:p1], 9,
                                    mol._atm, mol._bas, mol._env,
                                    shls_offset=shls_offset)
            veff2 = vj1 * 2
            t1 = log.timer('contracting cint2e_ip1ip2_sph for atom %d'%ia, *t1)

            vj1 = _vhf.direct_bindm('cint2e_ipvip1_sph', 's2kl',
                                    'lk->s1ij', dm0, 9,
                                    mol._atm, mol._bas, mol._env,
                                    shls_offset=shls_offset)
            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)
            t1 = log.timer('contracting cint2e_ipvip1_sph for atom %d'%ia, *t1)

        if xctype == 'LDA':
            ao_deriv = 1
            vj1[:] = 0
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
                rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
                vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
                vrho = vxc[0]
                frr = fxc[0]
                half = pyscf.lib.dot(ao[0], dm0[:,p0:p1].copy())
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:,:,p0:p1], half)
                aow = numpy.einsum('pi,xp->xpi', ao[0], weight*frr*rho1)
                veff2[0] += pyscf.lib.dot(ao[1].T, aow[0]) * 2
                veff2[1] += pyscf.lib.dot(ao[1].T, aow[1]) * 2
                veff2[2] += pyscf.lib.dot(ao[1].T, aow[2]) * 2
                veff2[3] += pyscf.lib.dot(ao[2].T, aow[0]) * 2
                veff2[4] += pyscf.lib.dot(ao[2].T, aow[1]) * 2
                veff2[5] += pyscf.lib.dot(ao[2].T, aow[2]) * 2
                veff2[6] += pyscf.lib.dot(ao[3].T, aow[0]) * 2
                veff2[7] += pyscf.lib.dot(ao[3].T, aow[1]) * 2
                veff2[8] += pyscf.lib.dot(ao[3].T, aow[2]) * 2
                aow = numpy.einsum('xpi,p->xpi', ao[1:,:,p0:p1], weight*vrho)
                vj1[0] += pyscf.lib.dot(aow[0].T, ao[1])
                vj1[1] += pyscf.lib.dot(aow[0].T, ao[2])
                vj1[2] += pyscf.lib.dot(aow[0].T, ao[3])
                vj1[3] += pyscf.lib.dot(aow[1].T, ao[1])
                vj1[4] += pyscf.lib.dot(aow[1].T, ao[2])
                vj1[5] += pyscf.lib.dot(aow[1].T, ao[3])
                vj1[6] += pyscf.lib.dot(aow[2].T, ao[1])
                vj1[7] += pyscf.lib.dot(aow[2].T, ao[2])
                vj1[8] += pyscf.lib.dot(aow[2].T, ao[3])
                half = aow = None

            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)

        elif xctype == 'GGA':
            def get_wv(rho, rho1, weight, vxc, fxc):
                vgamma = vxc[1]
                frr, frg, fgg = fxc[:3]
                ngrid = weight.size
                sigma1 = numpy.einsum('xi,xi->i', rho[1:], rho1[1:])
                wv = numpy.empty((4,ngrid))
                wv[0]  = frr * rho1[0]
                wv[0] += frg * sigma1 * 2
                wv[1:]  = (fgg * sigma1 * 4 + frg * rho1[0] * 2) * rho[1:]
                wv[1:] += vgamma * rho1[1:] * 2
                wv *= weight
                return wv
            ao_deriv = 2
            vj1[:] = 0
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
                rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
                vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
                vrho, vgamma = vxc[:2]
                # (d_X \nabla_x mu) nu DM_{mu,nu}
                half = pyscf.lib.dot(ao[0], dm0[:,p0:p1].copy())
                rho1X = numpy.einsum('xpi,pi->xp', ao[[1,XX,XY,XZ],:,p0:p1], half)
                rho1Y = numpy.einsum('xpi,pi->xp', ao[[2,YX,YY,YZ],:,p0:p1], half)
                rho1Z = numpy.einsum('xpi,pi->xp', ao[[3,ZX,ZY,ZZ],:,p0:p1], half)
                # (d_X mu) (\nabla_x nu) DM_{mu,nu}
                half = pyscf.lib.dot(ao[1], dm0[:,p0:p1].copy())
                rho1X[1] += numpy.einsum('pi,pi->p', ao[1,:,p0:p1], half)
                rho1Y[1] += numpy.einsum('pi,pi->p', ao[2,:,p0:p1], half)
                rho1Z[1] += numpy.einsum('pi,pi->p', ao[3,:,p0:p1], half)
                half = pyscf.lib.dot(ao[2], dm0[:,p0:p1].copy())
                rho1X[2] += numpy.einsum('pi,pi->p', ao[1,:,p0:p1], half)
                rho1Y[2] += numpy.einsum('pi,pi->p', ao[2,:,p0:p1], half)
                rho1Z[2] += numpy.einsum('pi,pi->p', ao[3,:,p0:p1], half)
                half = pyscf.lib.dot(ao[3], dm0[:,p0:p1].copy())
                rho1X[3] += numpy.einsum('pi,pi->p', ao[1,:,p0:p1], half)
                rho1Y[3] += numpy.einsum('pi,pi->p', ao[2,:,p0:p1], half)
                rho1Z[3] += numpy.einsum('pi,pi->p', ao[3,:,p0:p1], half)

                wv = get_wv(rho, rho1X, weight, vxc, fxc) * 2  # ~ vj1*2
                aow = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)  # dX
                veff2[0] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)  # dY
                veff2[3] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)  # dZ
                veff2[6] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[1:4], wv[1:4])
                veff2[0] += pyscf.lib.dot(ao[1].T, aow)
                veff2[3] += pyscf.lib.dot(ao[2].T, aow)
                veff2[6] += pyscf.lib.dot(ao[3].T, aow)
                wv = get_wv(rho, rho1Y, weight, vxc, fxc) * 2
                aow = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)
                veff2[1] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)
                veff2[4] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)
                veff2[7] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[1:4], wv[1:4])
                veff2[1] += pyscf.lib.dot(ao[1].T, aow)
                veff2[4] += pyscf.lib.dot(ao[2].T, aow)
                veff2[7] += pyscf.lib.dot(ao[3].T, aow)
                wv = get_wv(rho, rho1Z, weight, vxc, fxc) * 2
                aow = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)
                veff2[2] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)
                veff2[5] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)
                veff2[8] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[1:4], wv[1:4])
                veff2[2] += pyscf.lib.dot(ao[1].T, aow)
                veff2[5] += pyscf.lib.dot(ao[2].T, aow)
                veff2[8] += pyscf.lib.dot(ao[3].T, aow)

                wv = numpy.empty_like(rho)
                wv[0]  = weight * vrho * .5
                wv[1:] = rho[1:] * (weight * vgamma * 2)
                aowx = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)
                aowy = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)
                aowz = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)
                ao1 = aowx[:,p0:p1].T.copy()
                ao2 = aowy[:,p0:p1].T.copy()
                ao3 = aowz[:,p0:p1].T.copy()
                vj1[0] += pyscf.lib.dot(ao1, ao[1])
                vj1[1] += pyscf.lib.dot(ao1, ao[2])
                vj1[2] += pyscf.lib.dot(ao1, ao[3])
                vj1[3] += pyscf.lib.dot(ao2, ao[1])
                vj1[4] += pyscf.lib.dot(ao2, ao[2])
                vj1[5] += pyscf.lib.dot(ao2, ao[3])
                vj1[6] += pyscf.lib.dot(ao3, ao[1])
                vj1[7] += pyscf.lib.dot(ao3, ao[2])
                vj1[8] += pyscf.lib.dot(ao3, ao[3])
                ao1 = ao[1,:,p0:p1].T.copy()
                ao2 = ao[2,:,p0:p1].T.copy()
                ao3 = ao[3,:,p0:p1].T.copy()
                vj1[0] += pyscf.lib.dot(ao1, aowx)
                vj1[1] += pyscf.lib.dot(ao1, aowy)
                vj1[2] += pyscf.lib.dot(ao1, aowz)
                vj1[3] += pyscf.lib.dot(ao2, aowx)
                vj1[4] += pyscf.lib.dot(ao2, aowy)
                vj1[5] += pyscf.lib.dot(ao2, aowz)
                vj1[6] += pyscf.lib.dot(ao3, aowx)
                vj1[7] += pyscf.lib.dot(ao3, aowy)
                vj1[8] += pyscf.lib.dot(ao3, aowz)

            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)

        else:
            raise NotImplementedError('meta-GGA')

        for j0, ja in enumerate(atmlst):
            q0, q1 = offsetdic[ja][2:]
# *2 for double occupancy, *2 for +c.c.
            mo1  = pyscf.lib.chkfile.load(hess_mf.chkfile, 'scf_mo1/%d'%ja)
            h1ao = pyscf.lib.chkfile.load(hess_mf.chkfile, 'scf_h1ao/%d'%ia)
            dm1 = numpy.einsum('ypi,qi->ypq', mo1, mocc)
            de  = numpy.einsum('xpq,ypq->xy', h1ao, dm1) * 4
            dm1 = numpy.einsum('ypi,qi,i->ypq', mo1, mocc, mo_energy[:nocc])
            de -= numpy.einsum('xpq,ypq->xy', s1ao, dm1) * 4
            de -= numpy.einsum('xpq,ypq->xy', s1oo, e1s[j0]) * 2

            de = de.reshape(-1)
            v2aa = rinv2aa[str(ja)].value
            v2ab = rinv2ab[str(ja)].value
            de += numpy.einsum('xpq,pq->x', v2aa[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', v2ab[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', h_2[:,:,q0:q1], dm0[:,q0:q1])*2
            de += numpy.einsum('xpq,pq->x', veff2[:,q0:q1], dm0[q0:q1])*2
            de -= numpy.einsum('xpq,pq->x', s1ab[:,p0:p1,q0:q1], dme0[p0:p1,q0:q1])*2

            if ia == ja:
                de += numpy.einsum('xpq,pq->x', h1aa[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', v2aa, dm0)*2
                de -= numpy.einsum('xpq,pq->x', v2ab, dm0)*2
                de += numpy.einsum('xpq,pq->x', veff1ii[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', s1aa[:,p0:p1], dme0[p0:p1])*2

            de2[i0,j0] = de.reshape(3,3)

    frinv.close()
    log.timer('RHF hessian', *time0)
    return de2
Ejemplo n.º 33
0
 def get_k(self, mol=None, dm=None, hermi=0):
     if mol is None: mol = self.mol
     if dm is None: dm = self.base.make_rdm1()
     intor = mol._add_suffix('int2e_ip1')
     return -_vhf.direct_mapdm(intor, 's2kl', 'jk->s1il', dm, 3, mol._atm,
                               mol._bas, mol._env)
Ejemplo n.º 34
0
 def get_k(self, mol=None, dm=None, hermi=0):
     if mol is None: mol = self.mol
     if dm is None: dm = self._scf.make_rdm1()
     return -_vhf.direct_mapdm('cint2e_ip1_sph', 's2kl', 'jk->s1il', dm, 3,
                               mol._atm, mol._bas, mol._env)
Ejemplo n.º 35
0
def hess_elec(hess_mf, mo_energy=None, mo_coeff=None, mo_occ=None,
              atmlst=None, max_memory=4000, verbose=None):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(hess_mf.stdout, hess_mf.verbose)

    time0 = (time.clock(), time.time())

    mf = hess_mf._scf
    mol = hess_mf.mol
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_occ is None:    mo_occ = mf.mo_occ
    if mo_coeff is None:  mo_coeff = mf.mo_coeff
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    nocc = int(mo_occ.sum()) // 2
    mocc = mo_coeff[:,:nocc]
    dm0 = mf.make_rdm1(mo_coeff, mo_occ)

    ni = copy.copy(mf._numint)
    if USE_XCFUN:
        try:
            ni.libxc = dft.xcfun
            xctype = ni._xc_type(mf.xc)
        except (ImportError, KeyError, NotImplementedError):
            ni.libxc = dft.libxc
            xctype = ni._xc_type(mf.xc)
    else:
        xctype = ni._xc_type(mf.xc)
    grids = mf.grids
    hyb = ni.libxc.hybrid_coeff(mf.xc)
    max_memory = 4000

    h1aos = hess_mf.make_h1(mo_coeff, mo_occ, hess_mf.chkfile, atmlst, log)
    t1 = log.timer('making H1', *time0)
    def fx(mo1):
        # *2 for alpha + beta
        dm1 = numpy.einsum('xai,pa,qi->xpq', mo1, mo_coeff, mocc*2)
        dm1 = dm1 + dm1.transpose(0,2,1)
        vindxc = _contract_xc_kernel(mf, mf.xc, dm1, max_memory)
        if abs(hyb) > 1e-10:
            vj, vk = mf.get_jk(mol, dm1)
            veff = vj - hyb * .5 * vk + vindxc
        else:
            vj = mf.get_j(mol, dm1)
            veff = vj + vindxc
        v1 = numpy.einsum('xpq,pa,qi->xai', veff, mo_coeff, mocc)
        return v1.reshape(v1.shape[0],-1)
    mo1s, e1s = hess_mf.solve_mo1(mo_energy, mo_coeff, mo_occ, h1aos,
                                  fx, atmlst, max_memory, log)
    t1 = log.timer('solving MO1', *t1)

    tmpf = tempfile.NamedTemporaryFile()
    with h5py.File(tmpf.name, 'w') as f:
        for i0, ia in enumerate(atmlst):
            mol.set_rinv_origin(mol.atom_coord(ia))
            f['rinv2aa/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_ipiprinv_sph', comp=9))
            f['rinv2ab/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_iprinvip_sph', comp=9))

    h1aa =(mol.intor('cint1e_ipipkin_sph', comp=9) +
           mol.intor('cint1e_ipipnuc_sph', comp=9))
    h1ab =(mol.intor('cint1e_ipkinip_sph', comp=9) +
           mol.intor('cint1e_ipnucip_sph', comp=9))
    s1aa = mol.intor('cint1e_ipipovlp_sph', comp=9)
    s1ab = mol.intor('cint1e_ipovlpip_sph', comp=9)
    s1a =-mol.intor('cint1e_ipovlp_sph', comp=3)

    # Energy weighted density matrix
    dme0 = numpy.einsum('pi,qi,i->pq', mocc, mocc, mo_energy[:nocc]) * 2

    if abs(hyb) > 1e-10:
        vj1, vk1 = _vhf.direct_mapdm('cint2e_ipip1_sph', 's2kl',
                                     ('lk->s1ij', 'jk->s1il'), dm0, 9,
                                     mol._atm, mol._bas, mol._env)
        veff1ii = vj1 - hyb * .5 * vk1
    else:
        vj1 = _vhf.direct_mapdm('cint2e_ipip1_sph', 's2kl', 'lk->s1ij', dm0, 9,
                                mol._atm, mol._bas, mol._env)
        veff1ii = vj1.copy()
    vj1[:] = 0
    if xctype == 'LDA':
        ao_deriv = 2
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
            rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]
            vrho = vxc[0]
            aow = numpy.einsum('pi,p->pi', ao[0], weight*vrho)
            for i in range(6):
                vj1[i] += pyscf.lib.dot(ao[i+4].T, aow)
            aow = aow1 = None
    elif xctype == 'GGA':
        ao_deriv = 3
        for ao, mask, weight, coords \
                in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
            rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
            vxc = ni.eval_xc(mf.xc, rho, 0, deriv=1)[1]
            vrho, vgamma = vxc[:2]
            wv = numpy.empty_like(rho)
            wv[0]  = weight * vrho
            wv[1:] = rho[1:] * (weight * vgamma * 2)
            aow = numpy.einsum('npi,np->pi', ao[:4], wv)
            for i in range(6):
                vj1[i] += pyscf.lib.dot(ao[i+4].T, aow)
            aow = numpy.einsum('npi,np->pi', ao[[XXX,XXY,XXZ]], wv[1:4])
            vj1[0] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XXY,XYY,XYZ]], wv[1:4])
            vj1[1] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XXZ,XYZ,XZZ]], wv[1:4])
            vj1[2] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XYY,YYY,YYZ]], wv[1:4])
            vj1[3] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XYZ,YYZ,YZZ]], wv[1:4])
            vj1[4] += pyscf.lib.dot(aow.T, ao[0])
            aow = numpy.einsum('npi,np->pi', ao[[XZZ,YZZ,ZZZ]], wv[1:4])
            vj1[5] += pyscf.lib.dot(aow.T, ao[0])
            rho = vxc = vrho = vgamma = wv = aow = None
    else:
        raise NotImplementedError('meta-GGA')
    veff1ii += vj1[[0,1,2,1,3,4,2,4,5]]
    vj1 = vk1 = None

    t1 = log.timer('contracting cint2e_ipip1_sph', *t1)

    offsetdic = mol.offset_nr_by_atom()
    frinv = h5py.File(tmpf.name, 'r')
    rinv2aa = frinv['rinv2aa']
    rinv2ab = frinv['rinv2ab']

    de2 = numpy.zeros((mol.natm,mol.natm,3,3))
    for i0, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        h_2 = rinv2ab[str(ia)] + rinv2aa[str(ia)].value.transpose(0,2,1)
        h_2[:,p0:p1] += h1ab[:,p0:p1]
        s1ao = numpy.zeros((3,nao,nao))
        s1ao[:,p0:p1] += s1a[:,p0:p1]
        s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
        s1oo = numpy.einsum('xpq,pi,qj->xij', s1ao, mocc, mocc)

        shls_slice = (shl0, shl1) + (0, mol.nbas)*3
        if abs(hyb) > 1e-10:
            vj1, vk1, vk2 = _vhf.direct_bindm('cint2e_ip1ip2_sph', 's1',
                                              ('ji->s1kl', 'li->s1kj', 'lj->s1ki'),
                                              (dm0[:,p0:p1], dm0[:,p0:p1], dm0), 9,
                                              mol._atm, mol._bas, mol._env,
                                              shls_slice=shls_slice)
            veff2 = vj1 * 2 - hyb * .5 * vk1
            veff2[:,:,p0:p1] -= hyb * .5 * vk2
            t1 = log.timer('contracting cint2e_ip1ip2_sph for atom %d'%ia, *t1)

            vj1, vk1 = _vhf.direct_bindm('cint2e_ipvip1_sph', 's2kl',
                                         ('lk->s1ij', 'li->s1kj'),
                                         (dm0, dm0[:,p0:p1]), 9,
                                         mol._atm, mol._bas, mol._env,
                                         shls_slice=shls_slice)
            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)
            veff2 -= hyb * .5 * vk1.transpose(0,2,1)
            vj1 = vk1 = vk2 = None
            t1 = log.timer('contracting cint2e_ipvip1_sph for atom %d'%ia, *t1)
        else:
            vj1 = _vhf.direct_bindm('cint2e_ip1ip2_sph', 's1',
                                    'ji->s1kl', dm0[:,p0:p1], 9,
                                    mol._atm, mol._bas, mol._env,
                                    shls_slice=shls_slice)
            veff2 = vj1 * 2
            t1 = log.timer('contracting cint2e_ip1ip2_sph for atom %d'%ia, *t1)

            vj1 = _vhf.direct_bindm('cint2e_ipvip1_sph', 's2kl',
                                    'lk->s1ij', dm0, 9,
                                    mol._atm, mol._bas, mol._env,
                                    shls_slice=shls_slice)
            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)
            t1 = log.timer('contracting cint2e_ipvip1_sph for atom %d'%ia, *t1)

        if xctype == 'LDA':
            ao_deriv = 1
            vj1[:] = 0
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
                rho = ni.eval_rho2(mol, ao[0], mo_coeff, mo_occ, mask, 'LDA')
                vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
                vrho = vxc[0]
                frr = fxc[0]
                half = pyscf.lib.dot(ao[0], dm0[:,p0:p1].copy())
                rho1 = numpy.einsum('xpi,pi->xp', ao[1:,:,p0:p1], half)
                aow = numpy.einsum('pi,xp->xpi', ao[0], weight*frr*rho1)
                veff2[0] += pyscf.lib.dot(ao[1].T, aow[0]) * 2
                veff2[1] += pyscf.lib.dot(ao[1].T, aow[1]) * 2
                veff2[2] += pyscf.lib.dot(ao[1].T, aow[2]) * 2
                veff2[3] += pyscf.lib.dot(ao[2].T, aow[0]) * 2
                veff2[4] += pyscf.lib.dot(ao[2].T, aow[1]) * 2
                veff2[5] += pyscf.lib.dot(ao[2].T, aow[2]) * 2
                veff2[6] += pyscf.lib.dot(ao[3].T, aow[0]) * 2
                veff2[7] += pyscf.lib.dot(ao[3].T, aow[1]) * 2
                veff2[8] += pyscf.lib.dot(ao[3].T, aow[2]) * 2
                aow = numpy.einsum('xpi,p->xpi', ao[1:,:,p0:p1], weight*vrho)
                vj1[0] += pyscf.lib.dot(aow[0].T, ao[1])
                vj1[1] += pyscf.lib.dot(aow[0].T, ao[2])
                vj1[2] += pyscf.lib.dot(aow[0].T, ao[3])
                vj1[3] += pyscf.lib.dot(aow[1].T, ao[1])
                vj1[4] += pyscf.lib.dot(aow[1].T, ao[2])
                vj1[5] += pyscf.lib.dot(aow[1].T, ao[3])
                vj1[6] += pyscf.lib.dot(aow[2].T, ao[1])
                vj1[7] += pyscf.lib.dot(aow[2].T, ao[2])
                vj1[8] += pyscf.lib.dot(aow[2].T, ao[3])
                half = aow = None

            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)

        elif xctype == 'GGA':
            def get_wv(rho, rho1, weight, vxc, fxc):
                vgamma = vxc[1]
                frr, frg, fgg = fxc[:3]
                ngrid = weight.size
                sigma1 = numpy.einsum('xi,xi->i', rho[1:], rho1[1:])
                wv = numpy.empty((4,ngrid))
                wv[0]  = frr * rho1[0]
                wv[0] += frg * sigma1 * 2
                wv[1:]  = (fgg * sigma1 * 4 + frg * rho1[0] * 2) * rho[1:]
                wv[1:] += vgamma * rho1[1:] * 2
                wv *= weight
                return wv
            ao_deriv = 2
            vj1[:] = 0
            for ao, mask, weight, coords \
                    in ni.block_loop(mol, grids, nao, ao_deriv, max_memory, ni.non0tab):
                rho = ni.eval_rho2(mol, ao[:4], mo_coeff, mo_occ, mask, 'GGA')
                vxc, fxc = ni.eval_xc(mf.xc, rho, 0, deriv=2)[1:3]
                vrho, vgamma = vxc[:2]
                # (d_X \nabla_x mu) nu DM_{mu,nu}
                half = pyscf.lib.dot(ao[0], dm0[:,p0:p1].copy())
                rho1X = numpy.einsum('xpi,pi->xp', ao[[1,XX,XY,XZ],:,p0:p1], half)
                rho1Y = numpy.einsum('xpi,pi->xp', ao[[2,YX,YY,YZ],:,p0:p1], half)
                rho1Z = numpy.einsum('xpi,pi->xp', ao[[3,ZX,ZY,ZZ],:,p0:p1], half)
                # (d_X mu) (\nabla_x nu) DM_{mu,nu}
                half = pyscf.lib.dot(ao[1], dm0[:,p0:p1].copy())
                rho1X[1] += numpy.einsum('pi,pi->p', ao[1,:,p0:p1], half)
                rho1Y[1] += numpy.einsum('pi,pi->p', ao[2,:,p0:p1], half)
                rho1Z[1] += numpy.einsum('pi,pi->p', ao[3,:,p0:p1], half)
                half = pyscf.lib.dot(ao[2], dm0[:,p0:p1].copy())
                rho1X[2] += numpy.einsum('pi,pi->p', ao[1,:,p0:p1], half)
                rho1Y[2] += numpy.einsum('pi,pi->p', ao[2,:,p0:p1], half)
                rho1Z[2] += numpy.einsum('pi,pi->p', ao[3,:,p0:p1], half)
                half = pyscf.lib.dot(ao[3], dm0[:,p0:p1].copy())
                rho1X[3] += numpy.einsum('pi,pi->p', ao[1,:,p0:p1], half)
                rho1Y[3] += numpy.einsum('pi,pi->p', ao[2,:,p0:p1], half)
                rho1Z[3] += numpy.einsum('pi,pi->p', ao[3,:,p0:p1], half)

                wv = get_wv(rho, rho1X, weight, vxc, fxc) * 2  # ~ vj1*2
                aow = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)  # dX
                veff2[0] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)  # dY
                veff2[3] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)  # dZ
                veff2[6] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[1:4], wv[1:4])
                veff2[0] += pyscf.lib.dot(ao[1].T, aow)
                veff2[3] += pyscf.lib.dot(ao[2].T, aow)
                veff2[6] += pyscf.lib.dot(ao[3].T, aow)
                wv = get_wv(rho, rho1Y, weight, vxc, fxc) * 2
                aow = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)
                veff2[1] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)
                veff2[4] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)
                veff2[7] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[1:4], wv[1:4])
                veff2[1] += pyscf.lib.dot(ao[1].T, aow)
                veff2[4] += pyscf.lib.dot(ao[2].T, aow)
                veff2[7] += pyscf.lib.dot(ao[3].T, aow)
                wv = get_wv(rho, rho1Z, weight, vxc, fxc) * 2
                aow = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)
                veff2[2] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)
                veff2[5] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)
                veff2[8] += pyscf.lib.dot(aow.T, ao[0])
                aow = numpy.einsum('npi,np->pi', ao[1:4], wv[1:4])
                veff2[2] += pyscf.lib.dot(ao[1].T, aow)
                veff2[5] += pyscf.lib.dot(ao[2].T, aow)
                veff2[8] += pyscf.lib.dot(ao[3].T, aow)

                wv = numpy.empty_like(rho)
                wv[0]  = weight * vrho * .5
                wv[1:] = rho[1:] * (weight * vgamma * 2)
                aowx = numpy.einsum('npi,np->pi', ao[[1,XX,XY,XZ]], wv)
                aowy = numpy.einsum('npi,np->pi', ao[[2,YX,YY,YZ]], wv)
                aowz = numpy.einsum('npi,np->pi', ao[[3,ZX,ZY,ZZ]], wv)
                ao1 = aowx[:,p0:p1].T.copy()
                ao2 = aowy[:,p0:p1].T.copy()
                ao3 = aowz[:,p0:p1].T.copy()
                vj1[0] += pyscf.lib.dot(ao1, ao[1])
                vj1[1] += pyscf.lib.dot(ao1, ao[2])
                vj1[2] += pyscf.lib.dot(ao1, ao[3])
                vj1[3] += pyscf.lib.dot(ao2, ao[1])
                vj1[4] += pyscf.lib.dot(ao2, ao[2])
                vj1[5] += pyscf.lib.dot(ao2, ao[3])
                vj1[6] += pyscf.lib.dot(ao3, ao[1])
                vj1[7] += pyscf.lib.dot(ao3, ao[2])
                vj1[8] += pyscf.lib.dot(ao3, ao[3])
                ao1 = ao[1,:,p0:p1].T.copy()
                ao2 = ao[2,:,p0:p1].T.copy()
                ao3 = ao[3,:,p0:p1].T.copy()
                vj1[0] += pyscf.lib.dot(ao1, aowx)
                vj1[1] += pyscf.lib.dot(ao1, aowy)
                vj1[2] += pyscf.lib.dot(ao1, aowz)
                vj1[3] += pyscf.lib.dot(ao2, aowx)
                vj1[4] += pyscf.lib.dot(ao2, aowy)
                vj1[5] += pyscf.lib.dot(ao2, aowz)
                vj1[6] += pyscf.lib.dot(ao3, aowx)
                vj1[7] += pyscf.lib.dot(ao3, aowy)
                vj1[8] += pyscf.lib.dot(ao3, aowz)

            veff2[:,:,p0:p1] += vj1.transpose(0,2,1)

        else:
            raise NotImplementedError('meta-GGA')

        for j0, ja in enumerate(atmlst):
            q0, q1 = offsetdic[ja][2:]
# *2 for double occupancy, *2 for +c.c.
            mo1  = pyscf.lib.chkfile.load(hess_mf.chkfile, 'scf_mo1/%d'%ja)
            h1ao = pyscf.lib.chkfile.load(hess_mf.chkfile, 'scf_h1ao/%d'%ia)
            dm1 = numpy.einsum('ypi,qi->ypq', mo1, mocc)
            de  = numpy.einsum('xpq,ypq->xy', h1ao, dm1) * 4
            dm1 = numpy.einsum('ypi,qi,i->ypq', mo1, mocc, mo_energy[:nocc])
            de -= numpy.einsum('xpq,ypq->xy', s1ao, dm1) * 4
            de -= numpy.einsum('xpq,ypq->xy', s1oo, e1s[j0]) * 2

            de = de.reshape(-1)
            v2aa = rinv2aa[str(ja)].value
            v2ab = rinv2ab[str(ja)].value
            de += numpy.einsum('xpq,pq->x', v2aa[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', v2ab[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', h_2[:,:,q0:q1], dm0[:,q0:q1])*2
            de += numpy.einsum('xpq,pq->x', veff2[:,q0:q1], dm0[q0:q1])*2
            de -= numpy.einsum('xpq,pq->x', s1ab[:,p0:p1,q0:q1], dme0[p0:p1,q0:q1])*2

            if ia == ja:
                de += numpy.einsum('xpq,pq->x', h1aa[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', v2aa, dm0)*2
                de -= numpy.einsum('xpq,pq->x', v2ab, dm0)*2
                de += numpy.einsum('xpq,pq->x', veff1ii[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', s1aa[:,p0:p1], dme0[p0:p1])*2

            de2[i0,j0] = de.reshape(3,3)

    frinv.close()
    log.timer('RHF hessian', *time0)
    return de2
Ejemplo n.º 36
0
        def fx(X_):
            if not isinstance(X_, np.ndarray):
                return 0
            X = X_.copy()  # type: np.ndarray
            shape1 = list(X.shape)
            X.shape = (-1, shape1[-2], shape1[-1])
            if skl_none:
                dmX = X
                if dmX.shape[-2] != nao or dmX.shape[-1] != nao:
                    raise ValueError(
                        "if `sk`, `sl` is None, we assume that mo1 passed in is an AO-based matrix!"
                    )
            else:
                dmX = C[:, sk] @ X @ C[:, sl].T
            dmX += dmX.transpose((0, 2, 1))

            ax_ao = np.empty((natm, 3, dmX.shape[0], nao, nao))

            # Actual calculation
            # (ut v | k l), (ut k | v l)
            j_1, k_1 = _vhf.direct_mapdm(mol._add_suffix('int2e_ip1'), "s2kl",
                                         ("lk->s1ij", "jk->s1il"), dmX, 3,
                                         mol._atm, mol._bas, mol._env)
            if dmX.shape[
                    0] == 1:  # dm shape is 1 * nao * nao, then j_1, k_1 do not retain dimension of dm.shape[0]
                j_1, k_1 = j_1[None, :], k_1[None, :]
            j_1, k_1 = j_1.swapaxes(0, 1), k_1.swapaxes(0, 1)

            # HF Part
            for A in range(natm):
                ax = np.zeros((3, dmX.shape[0], nao, nao))
                shl0, shl1, p0, p1 = mol.aoslice_by_atom()[A]
                sA = slice(p0, p1)  # equivalent to mol_slice(A)
                ax[:, :, sA, :] -= 2 * j_1[:, :, sA, :]
                ax[:, :, :, sA] -= 2 * j_1[:, :, sA, :].swapaxes(-1, -2)
                ax[:, :, sA, :] += cx * k_1[:, :, sA, :]
                ax[:, :, :, sA] += cx * k_1[:, :, sA, :].swapaxes(-1, -2)
                # (kt l | u v), (kt u | l v)
                j_1A, k_1A = _vhf.direct_mapdm(
                    mol._add_suffix('int2e_ip1'),
                    "s2kl", ("ji->s1kl", "li->s1kj"),
                    dmX[:, :, p0:p1],
                    3,
                    mol._atm,
                    mol._bas,
                    mol._env,
                    shls_slice=((shl0, shl1) + (0, mol.nbas) * 3))
                if dmX.shape[
                        0] == 1:  # dm shape is 1 * nao * nao, then j_1A, k_1A do not retain dimension of dm.shape[0]
                    j_1A, k_1A = j_1A[None, :], k_1A[None, :]
                j_1A, k_1A = j_1A.swapaxes(0, 1), k_1A.swapaxes(0, 1)
                ax -= 4 * j_1A
                ax += cx * (k_1A + k_1A.swapaxes(-1, -2))

                ax_ao[A] = ax

            # GGA Part
            if self.xc_type == "GGA":
                grdit = GridIterator(self.mol,
                                     self.grids,
                                     self.D,
                                     deriv=3,
                                     memory=self.grdit_memory)
                for grdh in grdit:
                    kerh = KernelHelper(grdh, self.xc, deriv=3)
                    # Define some kernel and density derivative alias
                    pd_frr = kerh.frrr * grdh.A_rho_1 + kerh.frrg * grdh.A_gamma_1
                    pd_frg = kerh.frrg * grdh.A_rho_1 + kerh.frgg * grdh.A_gamma_1
                    pd_fgg = kerh.frgg * grdh.A_rho_1 + kerh.fggg * grdh.A_gamma_1
                    pd_fg = kerh.frg * grdh.A_rho_1 + kerh.fgg * grdh.A_gamma_1
                    pd_rho_1 = grdh.A_rho_2

                    # Form dmX density grid
                    rho_X_0 = np.array([grdh.get_rho_0(dm) for dm in dmX])
                    rho_X_1 = np.array([grdh.get_rho_1(dm) for dm in dmX])
                    pd_rho_X_0 = np.array([grdh.get_A_rho_1(dm)
                                           for dm in dmX]).transpose(
                                               (1, 2, 0, 3))
                    pd_rho_X_1 = np.array([grdh.get_A_rho_2(dm)
                                           for dm in dmX]).transpose(
                                               (1, 2, 0, 3, 4))

                    # Define temporary intermediates
                    tmp_M_0 = (+np.einsum("g, Bg -> Bg", kerh.frr, rho_X_0) +
                               2 * np.einsum("g, wg, Bwg -> Bg", kerh.frg,
                                             grdh.rho_1, rho_X_1))
                    tmp_M_1 = (
                        +4 * np.einsum("g, Bg, rg -> Brg", kerh.frg, rho_X_0,
                                       grdh.rho_1) +
                        8 * np.einsum("g, wg, Bwg, rg -> Brg", kerh.fgg,
                                      grdh.rho_1, rho_X_1, grdh.rho_1) +
                        4 * np.einsum("g, Brg -> Brg", kerh.fg, rho_X_1))
                    pd_tmp_M_0 = (
                        +np.einsum("Atg, Bg -> AtBg", pd_frr, rho_X_0) +
                        np.einsum("g, AtBg -> AtBg", kerh.frr, pd_rho_X_0) +
                        2 * np.einsum("Atg, wg, Bwg -> AtBg", pd_frg,
                                      grdh.rho_1, rho_X_1) +
                        2 * np.einsum("g, Atwg, Bwg -> AtBg", kerh.frg,
                                      pd_rho_1, rho_X_1) +
                        2 * np.einsum("g, wg, AtBwg -> AtBg", kerh.frg,
                                      grdh.rho_1, pd_rho_X_1))
                    pd_tmp_M_1 = (
                        +4 * np.einsum("Atg, Bg, rg -> AtBrg", pd_frg, rho_X_0,
                                       grdh.rho_1) +
                        4 * np.einsum("g, Bg, Atrg -> AtBrg", kerh.frg,
                                      rho_X_0, pd_rho_1) +
                        4 * np.einsum("g, AtBg, rg -> AtBrg", kerh.frg,
                                      pd_rho_X_0, grdh.rho_1) +
                        8 * np.einsum("Atg, wg, Bwg, rg -> AtBrg", pd_fgg,
                                      grdh.rho_1, rho_X_1, grdh.rho_1) +
                        8 * np.einsum("g, Atwg, Bwg, rg -> AtBrg", kerh.fgg,
                                      pd_rho_1, rho_X_1, grdh.rho_1) +
                        8 * np.einsum("g, wg, Bwg, Atrg -> AtBrg", kerh.fgg,
                                      grdh.rho_1, rho_X_1, pd_rho_1) +
                        8 * np.einsum("g, wg, AtBwg, rg -> AtBrg", kerh.fgg,
                                      grdh.rho_1, pd_rho_X_1, grdh.rho_1) +
                        4 * np.einsum("Atg, Brg -> AtBrg", pd_fg, rho_X_1) +
                        4 *
                        np.einsum("g, AtBrg -> AtBrg", kerh.fg, pd_rho_X_1))

                    contrib1 = np.zeros((natm, 3, dmX.shape[0], nao, nao))
                    contrib1 += np.einsum("AtBg, gu, gv -> AtBuv", pd_tmp_M_0,
                                          grdh.ao_0, grdh.ao_0)
                    contrib1 += np.einsum("AtBrg, rgu, gv -> AtBuv",
                                          pd_tmp_M_1, grdh.ao_1, grdh.ao_0)
                    contrib1 += contrib1.swapaxes(-1, -2)

                    tmp_contrib = (-2 * np.einsum(
                        "Bg, tgu, gv -> tBuv", tmp_M_0, grdh.ao_1, grdh.ao_0) -
                                   np.einsum("Brg, trgu, gv -> tBuv", tmp_M_1,
                                             grdh.ao_2, grdh.ao_0) -
                                   np.einsum("Brg, tgu, rgv -> tBuv", tmp_M_1,
                                             grdh.ao_1, grdh.ao_1))

                    contrib2 = np.zeros((natm, 3, dmX.shape[0], nao, nao))
                    for A in range(natm):
                        sA = self.mol_slice(A)
                        contrib2[A, :, :, sA] += tmp_contrib[:, :, sA]

                    contrib2 += contrib2.swapaxes(-1, -2)

                    # U contribution to \partial_{A_t} A
                    rho_U_0 = np.einsum("Atuv, gu, gv -> Atg", dmU, grdh.ao_0,
                                        grdh.ao_0)
                    rho_U_1 = 2 * np.einsum("Atuv, rgu, gv -> Atrg", dmU,
                                            grdh.ao_1, grdh.ao_0)
                    gamma_U_0 = 2 * np.einsum("rg, Atrg -> Atg", grdh.rho_1,
                                              rho_U_1)
                    pdU_frr = kerh.frrr * rho_U_0 + kerh.frrg * gamma_U_0
                    pdU_frg = kerh.frrg * rho_U_0 + kerh.frgg * gamma_U_0
                    pdU_fgg = kerh.frgg * rho_U_0 + kerh.fggg * gamma_U_0
                    pdU_fg = kerh.frg * rho_U_0 + kerh.fgg * gamma_U_0
                    pdU_rho_1 = rho_U_1
                    pdU_tmp_M_0 = (
                        +np.einsum("Atg, Bg -> AtBg", pdU_frr, rho_X_0) +
                        2 * np.einsum("Atg, wg, Bwg -> AtBg", pdU_frg,
                                      grdh.rho_1, rho_X_1) +
                        2 * np.einsum("g, Atwg, Bwg -> AtBg", kerh.frg,
                                      pdU_rho_1, rho_X_1))
                    pdU_tmp_M_1 = (
                        +4 * np.einsum("Atg, Bg, rg -> AtBrg", pdU_frg,
                                       rho_X_0, grdh.rho_1) +
                        4 * np.einsum("g, Bg, Atrg -> AtBrg", kerh.frg,
                                      rho_X_0, pdU_rho_1) +
                        8 * np.einsum("Atg, wg, Bwg, rg -> AtBrg", pdU_fgg,
                                      grdh.rho_1, rho_X_1, grdh.rho_1) +
                        8 * np.einsum("g, Atwg, Bwg, rg -> AtBrg", kerh.fgg,
                                      pdU_rho_1, rho_X_1, grdh.rho_1) +
                        8 * np.einsum("g, wg, Bwg, Atrg -> AtBrg", kerh.fgg,
                                      grdh.rho_1, rho_X_1, pdU_rho_1) +
                        4 * np.einsum("Atg, Brg -> AtBrg", pdU_fg, rho_X_1))

                    contrib3 = np.zeros((natm, 3, dmX.shape[0], nao, nao))
                    contrib3 += np.einsum("AtBg, gu, gv -> AtBuv", pdU_tmp_M_0,
                                          grdh.ao_0, grdh.ao_0)
                    contrib3 += np.einsum("AtBrg, rgu, gv -> AtBuv",
                                          pdU_tmp_M_1, grdh.ao_1, grdh.ao_0)
                    contrib3 += contrib3.swapaxes(-1, -2)

                    ax_ao += contrib1 + contrib2 + contrib3

            ax_ao.shape = (natm * 3, dmX.shape[0], nao, nao)

            if not sij_none:
                ax_ao = np.einsum("ABuv, ui, vj -> ABij", ax_ao, C[:, si],
                                  C[:, sj])
            if reshape:
                shape1.pop()
                shape1.pop()
                shape1.insert(0, ax_ao.shape[0])
                shape1.append(ax_ao.shape[-2])
                shape1.append(ax_ao.shape[-1])
                ax_ao.shape = shape1

            return ax_ao
Ejemplo n.º 37
0
 def get_k(self, mol=None, dm=None, hermi=0):
     if mol is None: mol = self.mol
     if dm is None: dm = self._scf.make_rdm1()
     return -_vhf.direct_mapdm('cint2e_ip1_sph', 's2kl', 'jk->s1il', dm, 3,
                               mol._atm, mol._bas, mol._env)
Ejemplo n.º 38
0
 def get_k(self, mol=None, dm=None, hermi=0):
     if mol is None: mol = self.mol
     if dm is None: dm = self.base.make_rdm1()
     intor = mol._add_suffix('int2e_ip1')
     return -_vhf.direct_mapdm(intor, 's2kl', 'jk->s1il', dm, 3,
                               mol._atm, mol._bas, mol._env)
Ejemplo n.º 39
0
def make_dia_gc2e(gobj, dm0, gauge_orig, sso_qed_fac=1):
    '''Note the side effects of set_common_origin'''

    if (isinstance(gobj.dia_soc2e, str) and
        ('SOMF' in gobj.dia_soc2e.upper() or 'AMFI' in gobj.dia_soc2e.upper())):
        raise NotImplementedError(gobj.dia_soc2e)
    if isinstance(gobj.dia_soc2e, str):
        with_sso = 'SSO' in gobj.dia_soc2e.upper()
        with_soo = 'SOO' in gobj.dia_soc2e.upper()
    else:
        with_sso = with_soo = True

    mol = gobj.mol
    dma, dmb = dm0
    effspin = mol.spin * .5
    muB = .5  # Bohr magneton
    alpha2 = nist.ALPHA ** 2
    #sso_qed_fac = (nist.G_ELECTRON - 1)

    # int2e_ip1v_r1 = (ij|\frac{\vec{r}_{12}}{r_{12}^3} \vec{r}_1|kl)
    if gauge_orig is None:
        intor = mol._add_suffix('int2e_ip1v_r1')
    else:
        mol.set_common_origin(gauge_orig)
        intor = mol._add_suffix('int2e_ip1v_rc1')
    vj, vk = _vhf.direct_mapdm(intor,
                               's2kl', ('lk->s1ij', 'jk->s1il'),
                               (dma, dmb), 9,
                               mol._atm, mol._bas, mol._env)
    ek = numpy.einsum('xil,li->x', vk[0], dma)
    ek-= numpy.einsum('xil,li->x', vk[1], dmb)
    ek = ek.reshape(3,3)
    gc2e = 0
    if with_sso:
        # spin-density should be contracted to electron 1 (associated to operator r1)
        ej = numpy.einsum('xij,ji->x', vj[0]+vj[1], dma-dmb).reshape(3,3)
        gc2e += sso_qed_fac * (ej - ek)
    if with_soo:
        # spin-density should be contracted to electron 2
        ej = numpy.einsum('xij,ji->x', vj[0]-vj[1], dma+dmb).reshape(3,3)
        gc2e += 2 * (ej - ek)
    gc2e -= numpy.eye(3) * gc2e.trace()
    gc2e *= (alpha2/8) / effspin / muB

    #   ([GIAO-i j] + [i GIAO-j]|\frac{\vec{r}_{12}}{r_{12}^3} x p1|kl)
    # + (ij|\frac{\vec{r}_{12}}{r_{12}^3} x p1|[GIAO-k l] + [k GIAO-l])
    if gauge_orig is None:
        nao = dma.shape[0]
        vj, vk = _vhf.direct_mapdm(mol._add_suffix('int2e_ipvg1_xp1'),
                                   's2kl', ('lk->s1ij', 'jk->s1il'),
                                   (dma, dmb), 9,
                                   mol._atm, mol._bas, mol._env)
        vk1 = _vhf.direct_mapdm(mol._add_suffix('int2e_ipvg2_xp1'),
                                   'aa4', 'jk->s1il',
                                   (dma, dmb), 9,
                                   mol._atm, mol._bas, mol._env)
        vj = vj.reshape(2,3,3,nao,nao)
        vk = vk.reshape(2,3,3,nao,nao)
        vk += vk1.reshape(2,3,3,nao,nao).transpose(0,2,1,3,4)
        ek = numpy.einsum('xyij,ji->xy', vk[0], dma)
        ek-= numpy.einsum('xyij,ji->xy', vk[1], dmb)
        dia_giao = 0
        if with_sso:
            ej = numpy.einsum('xyij,ji->xy', vj[0]+vj[1], dma-dmb)
            dia_giao += sso_qed_fac * (ej - ek)
        if with_soo:
            ej = numpy.einsum('xyij,ji->xy', vj[0]-vj[1], dma+dmb)
            dia_giao += 2 * (ej - ek)
        gc2e -= dia_giao * (alpha2/4) / effspin / muB

    if gobj.mb:  # correction of order c^{-2} from MB basis
        vj, vk = gobj._scf.get_jk(mol, dm0)
        vhf = vj[0] + vj[1] - vk
        gc_mb = numpy.einsum('ij,ji', vhf[0], dma)
        gc_mb-= numpy.einsum('ij,ji', vhf[1], dmb)
        gc2e += gc_mb * (alpha2/4) / effspin / muB * numpy.eye(3)

    return gc2e
Ejemplo n.º 40
0
    def _get_F_2_ao_JKcontrib(self):

        mol = self.mol
        natm = self.natm
        D = self.D
        nao = self.nao

        def reshape_only_first_dimension(mats_, d1=3, d2=3):
            rmats = []
            if isinstance(mats_, np.ndarray):
                mats = [mats_]
            else:
                mats = mats_
            for mat in mats:
                s = list(mat.shape)
                s[0] = d2
                s.insert(0, d1)
                mat.shape = tuple(s)

        Jcontrib = np.zeros((natm, natm, 3, 3, nao, nao))
        Kcontrib = np.zeros((natm, natm, 3, 3, nao, nao))
        hbas = (0, mol.nbas)

        # Atom insensitive contractions
        j_1 = _vhf.direct_mapdm(mol._add_suffix('int2e_ipip1'), "s2kl",
                                ("lk->s1ij"), D, 9, mol._atm, mol._bas,
                                mol._env)
        j_2 = _vhf.direct_mapdm(mol._add_suffix('int2e_ipvip1'), "s2kl",
                                ("lk->s1ij"), D, 9, mol._atm, mol._bas,
                                mol._env)
        k_1 = _vhf.direct_mapdm(mol._add_suffix('int2e_ipip1'), "s2kl",
                                ("jk->s1il"), D, 9, mol._atm, mol._bas,
                                mol._env)
        k_3 = _vhf.direct_mapdm(mol._add_suffix('int2e_ip1ip2'), "s1",
                                ("lj->s1ki"), D, 9, mol._atm, mol._bas,
                                mol._env)

        reshape_only_first_dimension((j_1, j_2, k_1, k_3))

        # One atom sensitive contractions, multiple usage
        j_3A, k_1A, k_2A, k_3A = [], [], [], []
        for A in range(natm):
            shl0A, shl1A, p0A, p1A = mol.aoslice_by_atom()[A]
            sA, hA = slice(p0A, p1A), (shl0A, shl1A)

            j_3A.append(
                _vhf.direct_mapdm(mol._add_suffix('int2e_ip1ip2'),
                                  "s1", ("lk->s1ij"),
                                  D[:, sA],
                                  9,
                                  mol._atm,
                                  mol._bas,
                                  mol._env,
                                  shls_slice=(hbas + hbas + hA + hbas)))
            k_1A.append(
                _vhf.direct_mapdm(mol._add_suffix('int2e_ipip1'),
                                  "s2kl", ("li->s1kj"),
                                  D[:, sA],
                                  9,
                                  mol._atm,
                                  mol._bas,
                                  mol._env,
                                  shls_slice=(hA + hbas * 3)))
            k_2A.append(
                _vhf.direct_mapdm(mol._add_suffix('int2e_ipvip1'),
                                  "s2kl", ("jk->s1il"),
                                  D[sA],
                                  9,
                                  mol._atm,
                                  mol._bas,
                                  mol._env,
                                  shls_slice=(hbas + hA + hbas + hbas)))
            k_3A.append(
                _vhf.direct_mapdm(mol._add_suffix('int2e_ip1ip2'),
                                  "s1", ("jk->s1il"),
                                  D[:, sA],
                                  9,
                                  mol._atm,
                                  mol._bas,
                                  mol._env,
                                  shls_slice=(hbas + hbas + hA + hbas)))
        for jkA in j_3A, k_1A, k_2A, k_3A:
            reshape_only_first_dimension(jkA)

        for A in range(natm):
            shl0A, shl1A, p0A, p1A = mol.aoslice_by_atom()[A]
            sA, hA = slice(p0A, p1A), (shl0A, shl1A)

            # One atom sensitive contractions, One usage only
            j_1A = _vhf.direct_mapdm(mol._add_suffix('int2e_ipip1'),
                                     "s2kl", ("ji->s1kl"),
                                     D[:, sA],
                                     9,
                                     mol._atm,
                                     mol._bas,
                                     mol._env,
                                     shls_slice=(hA + (0, mol.nbas) * 3))
            reshape_only_first_dimension((j_1A, ))

            # A-A manipulation
            Jcontrib[A, A, :, :, sA, :] += j_1[:, :, sA, :]
            Jcontrib[A, A] += j_1A
            Kcontrib[A, A, :, :, sA] += k_1[:, :, sA]
            Kcontrib[A, A] += k_1A[A]

            for B in range(A + 1):
                shl0B, shl1B, p0B, p1B = mol.aoslice_by_atom()[B]
                sB, hB = slice(p0B, p1B), (shl0B, shl1B)

                # Two atom sensitive contractions
                j_2AB = _vhf.direct_mapdm(mol._add_suffix('int2e_ipvip1'),
                                          "s2kl", ("ji->s1kl"),
                                          D[sB, sA],
                                          9,
                                          mol._atm,
                                          mol._bas,
                                          mol._env,
                                          shls_slice=(hA + hB +
                                                      (0, mol.nbas) * 2))
                k_3AB = _vhf.direct_mapdm(mol._add_suffix('int2e_ip1ip2'),
                                          "s1", ("ki->s1jl"),
                                          D[sB, sA],
                                          9,
                                          mol._atm,
                                          mol._bas,
                                          mol._env,
                                          shls_slice=(hA + (0, mol.nbas) + hB +
                                                      (0, mol.nbas)))
                reshape_only_first_dimension((j_2AB, k_3AB))

                # A-B manipulation
                Jcontrib[A, B, :, :, sA, sB] += j_2[:, :, sA, sB]
                Jcontrib[A, B] += j_2AB
                Jcontrib[A, B, :, :, sA] += 2 * j_3A[B][:, :, sA]
                Jcontrib[B, A, :, :, sB] += 2 * j_3A[A][:, :, sB]
                Kcontrib[A, B, :, :, sA] += k_2A[B][:, :, sA]
                Kcontrib[B, A, :, :, sB] += k_2A[A][:, :, sB]
                Kcontrib[A, B, :, :, sA] += k_3A[B][:, :, sA]
                Kcontrib[B, A, :, :, sB] += k_3A[A][:, :, sB]
                Kcontrib[A, B, :, :, sA, sB] += k_3[:, :, sB,
                                                    sA].swapaxes(-1, -2)
                Kcontrib[A, B] += k_3AB

            # A == B finalize

            Jcontrib[A, A] /= 2
            Kcontrib[A, A] /= 2
            gc.collect()

        # Symmetry Finalize
        Jcontrib += Jcontrib.transpose((0, 1, 2, 3, 5, 4))
        Jcontrib += Jcontrib.transpose((1, 0, 3, 2, 4, 5))
        Kcontrib += Kcontrib.transpose((0, 1, 2, 3, 5, 4))
        Kcontrib += Kcontrib.transpose((1, 0, 3, 2, 4, 5))

        return Jcontrib, Kcontrib
Ejemplo n.º 41
0
def hess_elec(hess_mf, mo_energy=None, mo_coeff=None, mo_occ=None,
              atmlst=None, max_memory=4000, verbose=None):
    if isinstance(verbose, logger.Logger):
        log = verbose
    else:
        log = logger.Logger(hess_mf.stdout, hess_mf.verbose)

    time0 = (time.clock(), time.time())

    mf = hess_mf._scf
    mol = hess_mf.mol
    if mo_energy is None: mo_energy = mf.mo_energy
    if mo_occ is None:    mo_occ = mf.mo_occ
    if mo_coeff is None:  mo_coeff = mf.mo_coeff
    if atmlst is None: atmlst = range(mol.natm)

    nao, nmo = mo_coeff.shape
    mocc = mo_coeff[:,mo_occ>0]
    nocc = mocc.shape[1]
    dm0 = numpy.dot(mocc, mocc.T) * 2

    h1aos = hess_mf.make_h1(mo_coeff, mo_occ, hess_mf.chkfile, atmlst, log)
    t1 = log.timer('making H1', *time0)
    mo1s, e1s = hess_mf.solve_mo1(mo_energy, mo_coeff, mo_occ, h1aos,
                                  None, atmlst, max_memory, log)
    t1 = log.timer('solving MO1', *t1)

    tmpf = tempfile.NamedTemporaryFile()
    with h5py.File(tmpf.name, 'w') as f:
        for i0, ia in enumerate(atmlst):
            mol.set_rinv_origin(mol.atom_coord(ia))
            f['rinv2aa/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_ipiprinv_sph', comp=9))
            f['rinv2ab/%d'%ia] = (mol.atom_charge(ia) *
                                  mol.intor('cint1e_iprinvip_sph', comp=9))

    h1aa =(mol.intor('cint1e_ipipkin_sph', comp=9) +
           mol.intor('cint1e_ipipnuc_sph', comp=9))
    h1ab =(mol.intor('cint1e_ipkinip_sph', comp=9) +
           mol.intor('cint1e_ipnucip_sph', comp=9))
    s1aa = mol.intor('cint1e_ipipovlp_sph', comp=9)
    s1ab = mol.intor('cint1e_ipovlpip_sph', comp=9)
    s1a =-mol.intor('cint1e_ipovlp_sph', comp=3)

    # Energy weighted density matrix
    dme0 = numpy.einsum('pi,qi,i->pq', mocc, mocc, mo_energy[:nocc]) * 2

    vj1, vk1 = _vhf.direct_mapdm('cint2e_ipip1_sph', 's2kl',
                                 ('lk->s1ij', 'jk->s1il'), dm0, 9,
                                 mol._atm, mol._bas, mol._env)
    vhf1ii = vj1 - vk1*.5
    vj1 = vk1 = None
    t1 = log.timer('contracting cint2e_ipip1_sph', *t1)

    offsetdic = mol.offset_nr_by_atom()
    frinv = h5py.File(tmpf.name, 'r')
    rinv2aa = frinv['rinv2aa']
    rinv2ab = frinv['rinv2ab']

    de2 = numpy.zeros((mol.natm,mol.natm,3,3))
    for i0, ia in enumerate(atmlst):
        shl0, shl1, p0, p1 = offsetdic[ia]

        h_2 = rinv2ab[str(ia)] + rinv2aa[str(ia)].value.transpose(0,2,1)
        h_2[:,p0:p1] += h1ab[:,p0:p1]
        s1ao = numpy.zeros((3,nao,nao))
        s1ao[:,p0:p1] += s1a[:,p0:p1]
        s1ao[:,:,p0:p1] += s1a[:,p0:p1].transpose(0,2,1)
        s1oo = numpy.einsum('xpq,pi,qj->xij', s1ao, mocc, mocc)

        shls_slice = (shl0, shl1) + (0, mol.nbas)*3
        vj1, vk1, vk2 = _vhf.direct_bindm('cint2e_ip1ip2_sph', 's1',
                                          ('ji->s1kl', 'li->s1kj', 'lj->s1ki'),
                                          (dm0[:,p0:p1], dm0[:,p0:p1], dm0), 9,
                                          mol._atm, mol._bas, mol._env,
                                          shls_slice=shls_slice)
        vhf2 = vj1 * 2 - vk1 * .5
        vhf2[:,:,p0:p1] -= vk2 * .5
        t1 = log.timer('contracting cint2e_ip1ip2_sph for atom %d'%ia, *t1)

        vj1, vk1 = _vhf.direct_bindm('cint2e_ipvip1_sph', 's2kl',
                                     ('lk->s1ij', 'li->s1kj'),
                                     (dm0, dm0[:,p0:p1]), 9,
                                     mol._atm, mol._bas, mol._env,
                                     shls_slice=shls_slice)
        vhf2[:,:,p0:p1] += vj1.transpose(0,2,1)
        vhf2 -= vk1.transpose(0,2,1) * .5
        vj1 = vk1 = vk2 = None
        t1 = log.timer('contracting cint2e_ipvip1_sph for atom %d'%ia, *t1)

        for j0, ja in enumerate(atmlst):
            q0, q1 = offsetdic[ja][2:]
# *2 for double occupancy, *2 for +c.c.
            mo1  = pyscf.lib.chkfile.load(hess_mf.chkfile, 'scf_mo1/%d'%ja)
            h1ao = pyscf.lib.chkfile.load(hess_mf.chkfile, 'scf_h1ao/%d'%ia)
            dm1 = numpy.einsum('ypi,qi->ypq', mo1, mocc)
            de  = numpy.einsum('xpq,ypq->xy', h1ao, dm1) * 4
            dm1 = numpy.einsum('ypi,qi,i->ypq', mo1, mocc, mo_energy[:nocc])
            de -= numpy.einsum('xpq,ypq->xy', s1ao, dm1) * 4
            de -= numpy.einsum('xpq,ypq->xy', s1oo, e1s[j0]) * 2

            de = de.reshape(-1)
            v2aa = rinv2aa[str(ja)].value
            v2ab = rinv2ab[str(ja)].value
            de += numpy.einsum('xpq,pq->x', v2aa[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', v2ab[:,p0:p1], dm0[p0:p1])*2
            de += numpy.einsum('xpq,pq->x', h_2[:,:,q0:q1], dm0[:,q0:q1])*2
            de += numpy.einsum('xpq,pq->x', vhf2[:,q0:q1], dm0[q0:q1])*2
            de -= numpy.einsum('xpq,pq->x', s1ab[:,p0:p1,q0:q1], dme0[p0:p1,q0:q1])*2

            if ia == ja:
                de += numpy.einsum('xpq,pq->x', h1aa[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', v2aa, dm0)*2
                de -= numpy.einsum('xpq,pq->x', v2ab, dm0)*2
                de += numpy.einsum('xpq,pq->x', vhf1ii[:,p0:p1], dm0[p0:p1])*2
                de -= numpy.einsum('xpq,pq->x', s1aa[:,p0:p1], dme0[p0:p1])*2

            de2[i0,j0] = de.reshape(3,3)

    frinv.close()
    log.timer('RHF hessian', *time0)
    return de2
Ejemplo n.º 42
0
        def fx(mo1):
            # It is assumed that mo1 is Bs** like
            if len(mo1.shape) != 4:
                raise ValueError(
                    "Passed in mo1 should be Bs** like, so length of mo1.shape should be 4."
                )
            if skl_none:
                dm1 = mo1
                if dm1.shape[-2] != self.nao or dm1.shape[-1] != self.nao:
                    raise ValueError(
                        "if `sk`, `sl` is None, we assume that mo1 passed in is an AO-based matrix!"
                    )
            else:
                dm1 = C[:, sk] @ mo1 @ C[:, sl].T
            dm1 += dm1.swapaxes(-1, -2)

            # create a return tensor
            if sij_none:
                ax_final = np.zeros(
                    (natm, dm1.shape[0], 3, dm1.shape[1], nao, nao))
            else:
                ax_final = np.zeros((natm, dm1.shape[0], 3, dm1.shape[1],
                                     si.stop - si.start, sj.stop - sj.start))

            # Actual calculation
            for B in range(dm1.shape[0]):
                for s in range(dm1.shape[1]):
                    dm1Bs = dm1[B, s]
                    # (ut v | k l), (ut k | v l)
                    j_1, k_1 = _vhf.direct_mapdm(mol._add_suffix('int2e_ip1'),
                                                 "s2kl",
                                                 ("lk->s1ij", "jk->s1il"),
                                                 dm1Bs, 3, mol._atm, mol._bas,
                                                 mol._env)
                    for A in range(natm):
                        ax = np.zeros((3, nao, nao))
                        shl0, shl1, p0, p1 = mol.aoslice_by_atom()[A]
                        sA = slice(p0, p1)  # equivalent to mol_slice(A)
                        ax[:, sA, :] -= 2 * j_1[:, sA, :]
                        ax[:, :, sA] -= 2 * j_1[:, sA, :].swapaxes(-1, -2)
                        ax[:, sA, :] += cx * k_1[:, sA, :]
                        ax[:, :, sA] += cx * k_1[:, sA, :].swapaxes(-1, -2)
                        # (kt l | u v), (kt u | l v)
                        j_1A, k_1A = _vhf.direct_mapdm(
                            mol._add_suffix('int2e_ip1'),
                            "s2kl", ("ji->s1kl", "li->s1kj"),
                            dm1Bs[:, p0:p1],
                            3,
                            mol._atm,
                            mol._bas,
                            mol._env,
                            shls_slice=((shl0, shl1) + (0, mol.nbas) * 3))
                        ax -= 4 * j_1A
                        ax += cx * (k_1A + k_1A.swapaxes(-1, -2))

                        if sij_none:
                            ax_final[A, B, :, s] = ax
                        else:
                            ax_final[A, B, :, s] = C[:, si].T @ ax @ C[:, sj]

            return ax_final