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
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
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))
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
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))
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
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
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
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]))
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
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)
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
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
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))
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
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
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))
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))
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
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
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
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)
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
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
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
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
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
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
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
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)
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)
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
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
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
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
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