def test_gen_rhf_response(self): numpy.random.seed(9) dm1 = numpy.random.random(dm_he.shape) dm1 = dm1 + dm1.transpose(0,2,1) dm1[1] = dm1[0] mydf = df.FFTDF(cell_he) ni = dft.numint.KNumInt() mf = dft.KRKS(cell_he) mf.with_df = multigrid.MultiGridFFTDF(cell_he) mf.kpts = kpts mf.xc = 'lda,' ref = dft.numint.nr_rks_fxc(ni, cell_he, mydf.grids, mf.xc, dm_he, dm1, kpts=kpts) vj = mydf.get_jk(dm1, with_k=False, kpts=kpts)[0] ref += vj v = multigrid._gen_rhf_response(mf, dm_he)(dm1) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v-ref).max(), 0, 9) mf.xc = 'b88,' ref = dft.numint.nr_rks_fxc(ni, cell_he, mydf.grids, mf.xc, dm_he, dm1, kpts=kpts) ref += vj v = multigrid._gen_rhf_response(mf, dm_he, hermi=1)(dm1) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v-ref).max(), 0, 6)
def test_gen_rhf_response(self): numpy.random.seed(9) dm1 = numpy.random.random(dm_he.shape) dm1 = dm1 + dm1.transpose(0, 2, 1) dm1[1] = dm1[0] mydf = df.FFTDF(cell_he) ni = dft.numint.KNumInt() mf = dft.KRKS(cell_he) mf.with_df = multigrid.MultiGridFFTDF(cell_he) mf.kpts = kpts mf.xc = 'lda,' ref = dft.numint.nr_rks_fxc(ni, cell_he, mydf.grids, mf.xc, dm_he, dm1, hermi=1, kpts=kpts) vj = mydf.get_jk(dm1, with_k=False, kpts=kpts)[0] ref += vj v = multigrid._gen_rhf_response(mf, dm_he, hermi=1)(dm1) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v - ref).max(), 0, 9) mf.xc = 'b88,' ref = dft.numint.nr_rks_fxc(ni, cell_he, mydf.grids, mf.xc, dm_he, dm1, hermi=1, kpts=kpts) ref += vj v = multigrid._gen_rhf_response(mf, dm_he, hermi=1)(dm1) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v - ref).max(), 0, 6)
def _gen_rhf_response(mf, mo_coeff=None, mo_occ=None, singlet=None, hermi=0, max_memory=None): assert (not isinstance(mf, (uhf.UHF, rohf.ROHF))) if mo_coeff is None: mo_coeff = mf.mo_coeff if mo_occ is None: mo_occ = mf.mo_occ mol = mf.mol if _is_dft_object(mf): from pyscf.dft import rks from pyscf.dft import numint ni = mf._numint ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True) if getattr(mf, 'nlc', '') != '': logger.warn( mf, 'NLC functional found in DFT object. Its second ' 'deriviative is not available. Its contribution is ' 'not included in the response function.') omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin) hybrid = abs(hyb) > 1e-10 # mf can be pbc.dft.RKS object with multigrid if (not hybrid and 'MultiGridFFTDF' == getattr( mf, 'with_df', None).__class__.__name__): from pyscf.pbc.dft import multigrid dm0 = mf.make_rdm1(mo_coeff, mo_occ) return multigrid._gen_rhf_response(mf, dm0, singlet, hermi) if singlet is None: # for newton solver rho0, vxc, fxc = ni.cache_xc_kernel(mol, mf.grids, mf.xc, mo_coeff, mo_occ, 0) else: rho0, vxc, fxc = ni.cache_xc_kernel(mol, mf.grids, mf.xc, [mo_coeff] * 2, [mo_occ * .5] * 2, spin=1) dm0 = None #mf.make_rdm1(mo_coeff, mo_occ) if max_memory is None: mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) if singlet is None: # Without specify singlet, general case def vind(dm1): # The singlet hessian if hermi == 2: v1 = numpy.zeros_like(dm1) else: v1 = ni.nr_rks_fxc(mol, mf.grids, mf.xc, dm0, dm1, 0, hermi, rho0, vxc, fxc, max_memory=max_memory) if hybrid: if hermi != 2: vj, vk = mf.get_jk(mol, dm1, hermi=hermi) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb vk += mf.get_k(mol, dm1, hermi, omega) * (alpha - hyb) v1 += vj - .5 * vk else: v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi) elif hermi != 2: v1 += mf.get_j(mol, dm1, hermi=hermi) return v1 elif singlet: def vind(dm1): if hermi == 2: v1 = numpy.zeros_like(dm1) else: # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled v1 = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm1, 0, True, rho0, vxc, fxc, max_memory=max_memory) v1 *= .5 if hybrid: if hermi != 2: vj, vk = mf.get_jk(mol, dm1, hermi=hermi) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb vk += mf.get_k(mol, dm1, hermi, omega) * (alpha - hyb) v1 += vj - .5 * vk else: v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi) elif hermi != 2: v1 += mf.get_j(mol, dm1, hermi=hermi) return v1 else: # triplet def vind(dm1): if hermi == 2: v1 = numpy.zeros_like(dm1) else: # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled v1 = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm1, 0, False, rho0, vxc, fxc, max_memory=max_memory) v1 *= .5 if hybrid: vk = mf.get_k(mol, dm1, hermi=hermi) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb vk += mf.get_k(mol, dm1, hermi, omega) * (alpha - hyb) v1 += -.5 * vk return v1 else: # HF if (singlet is None or singlet) and hermi != 2: def vind(dm1): vj, vk = mf.get_jk(mol, dm1, hermi=hermi) return vj - .5 * vk else: def vind(dm1): return -.5 * mf.get_k(mol, dm1, hermi=hermi) return vind
def test_nr_rks_fxc_st(self): numpy.random.seed(9) dm1 = numpy.random.random( dm_he.shape) + numpy.random.random(dm_he.shape) * 1j dm1[1] = dm1[0] mydf = df.FFTDF(cell_he) ni = dft.numint.KNumInt() mg_df = multigrid.MultiGridFFTDF(cell_he) mf = dft.KRKS(cell_he) mf.with_df = mg_df mf.kpts = kpts xc = 'lda,' ref = dft.numint.nr_rks_fxc_st(ni, cell_he, mydf.grids, xc, dm_he, dm1, singlet=True, kpts=kpts) v = multigrid.nr_rks_fxc_st(mg_df, xc, dm_he, dm1, singlet=True, kpts=kpts) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v - ref).max(), 0, 4) mf.xc = 'b88,' ref = dft.numint.nr_rks_fxc_st(ni, cell_he, mydf.grids, mf.xc, dm_he, dm1, singlet=True, kpts=kpts) v = multigrid._gen_rhf_response(mf, dm_he, singlet=True)(dm1) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v - ref).max(), 0, 5) mf.xc = 'lda,' ref = dft.numint.nr_rks_fxc_st(ni, cell_he, mydf.grids, mf.xc, dm_he, dm1, singlet=False, kpts=kpts) v = multigrid._gen_rhf_response(mf, dm_he, singlet=False)(dm1) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v - ref).max(), 0, 4) xc = 'b88,' ref = dft.numint.nr_rks_fxc_st(ni, cell_he, mydf.grids, xc, dm_he, dm1, singlet=False, kpts=kpts) v = multigrid.nr_rks_fxc_st(mg_df, xc, dm_he, dm1, singlet=False, kpts=kpts) self.assertEqual(ref.dtype, v.dtype) self.assertEqual(ref.shape, v.shape) self.assertAlmostEqual(abs(v - ref).max(), 0, 5)
def _gen_rhf_response(mf, mo_coeff=None, mo_occ=None, singlet=None, hermi=0, max_memory=None): from pyscf.pbc.dft import numint, multigrid assert (isinstance(mf, khf.KRHF)) if mo_coeff is None: mo_coeff = mf.mo_coeff if mo_occ is None: mo_occ = mf.mo_occ cell = mf.cell kpts = mf.kpts if getattr(mf, 'xc', None) and getattr(mf, '_numint', None): ni = mf._numint ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True) omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, spin=cell.spin) hybrid = abs(hyb) > 1e-10 if abs(omega) > 1e-10: # For range separated Coulomb raise NotImplementedError if not hybrid and isinstance(mf.with_df, multigrid.MultiGridFFTDF): dm0 = mf.make_rdm1(mo_coeff, mo_occ) return multigrid._gen_rhf_response(mf, dm0, singlet, hermi) if singlet is None: # for newton solver rho0, vxc, fxc = ni.cache_xc_kernel(cell, mf.grids, mf.xc, mo_coeff, mo_occ, 0, kpts) else: if isinstance(mo_occ, numpy.ndarray): mo_occ = mo_occ * .5 else: mo_occ = [x * .5 for x in mo_occ] rho0, vxc, fxc = ni.cache_xc_kernel(cell, mf.grids, mf.xc, [mo_coeff] * 2, [mo_occ] * 2, spin=1, kpts=kpts) dm0 = None #mf.make_rdm1(mo_coeff, mo_occ) if max_memory is None: mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory * .8 - mem_now) if singlet is None: # Without specify singlet, general case def vind(dm1): # The singlet hessian if hermi == 2: v1 = numpy.zeros_like(dm1) else: v1 = ni.nr_rks_fxc(cell, mf.grids, mf.xc, dm0, dm1, 0, hermi, rho0, vxc, fxc, kpts, max_memory=max_memory) if hybrid: if hermi != 2: vj, vk = mf.get_jk(cell, dm1, hermi=hermi, kpts=kpts) v1 += vj - .5 * hyb * vk else: v1 -= .5 * hyb * mf.get_k( cell, dm1, hermi=hermi, kpts=kpts) elif hermi != 2: v1 += mf.get_j(cell, dm1, hermi=hermi, kpts=kpts) return v1 elif singlet: def vind(dm1): if hermi == 2: v1 = numpy.zeros_like(dm1) else: # nr_rks_fxc_st requires alpha of dm1 v1 = numint.nr_rks_fxc_st(ni, cell, mf.grids, mf.xc, dm0, dm1, 0, True, rho0, vxc, fxc, kpts, max_memory=max_memory) v1 *= .5 if hybrid: if hermi != 2: vj, vk = mf.get_jk(cell, dm1, hermi=hermi, kpts=kpts) v1 += vj - .5 * hyb * vk else: v1 -= .5 * hyb * mf.get_k( cell, dm1, hermi=hermi, kpts=kpts) elif hermi != 2: v1 += mf.get_j(cell, dm1, hermi=hermi, kpts=kpts) return v1 else: # triplet def vind(dm1): if hermi == 2: v1 = numpy.zeros_like(dm1) else: # nr_rks_fxc_st requires alpha of dm1 v1 = numint.nr_rks_fxc_st(ni, cell, mf.grids, mf.xc, dm0, dm1, 0, False, rho0, vxc, fxc, kpts, max_memory=max_memory) v1 *= .5 if hybrid: v1 += -.5 * hyb * mf.get_k( cell, dm1, hermi=hermi, kpts=kpts) return v1 else: # HF if (singlet is None or singlet) and hermi != 2: def vind(dm1): vj, vk = mf.get_jk(cell, dm1, hermi=hermi, kpts=kpts) return vj - .5 * vk else: def vind(dm1): return -.5 * mf.get_k(cell, dm1, hermi=hermi, kpts=kpts) return vind
def _gen_rhf_response(mf, mo_coeff=None, mo_occ=None, singlet=None, hermi=0, max_memory=None): assert(not isinstance(mf, (uhf.UHF, rohf.ROHF))) if mo_coeff is None: mo_coeff = mf.mo_coeff if mo_occ is None: mo_occ = mf.mo_occ mol = mf.mol if getattr(mf, 'xc', None) and getattr(mf, '_numint', None): from pyscf.dft import rks from pyscf.dft import numint ni = mf._numint ni.libxc.test_deriv_order(mf.xc, 2, raise_error=True) if getattr(mf, 'nlc', '') != '': logger.warn(mf, 'NLC functional found in DFT object. Its second ' 'deriviative is not available. Its contribution is ' 'not included in the response function.') omega, alpha, hyb = ni.rsh_and_hybrid_coeff(mf.xc, mol.spin) hybrid = abs(hyb) > 1e-10 # mf can be pbc.dft.RKS object with multigrid if (not hybrid and 'MultiGridFFTDF' == getattr(mf, 'with_df', None).__class__.__name__): from pyscf.pbc.dft import multigrid dm0 = mf.make_rdm1(mo_coeff, mo_occ) return multigrid._gen_rhf_response(mf, dm0, singlet, hermi) if singlet is None: # for newton solver rho0, vxc, fxc = ni.cache_xc_kernel(mol, mf.grids, mf.xc, mo_coeff, mo_occ, 0) else: rho0, vxc, fxc = ni.cache_xc_kernel(mol, mf.grids, mf.xc, [mo_coeff]*2, [mo_occ*.5]*2, spin=1) dm0 = None #mf.make_rdm1(mo_coeff, mo_occ) if max_memory is None: mem_now = lib.current_memory()[0] max_memory = max(2000, mf.max_memory*.8-mem_now) if singlet is None: # Without specify singlet, general case def vind(dm1): # The singlet hessian if hermi == 2: v1 = numpy.zeros_like(dm1) else: v1 = ni.nr_rks_fxc(mol, mf.grids, mf.xc, dm0, dm1, 0, hermi, rho0, vxc, fxc, max_memory=max_memory) if hybrid: if hermi != 2: vj, vk = mf.get_jk(mol, dm1, hermi=hermi) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb vk += rks._get_k_lr(mol, dm1, omega, hermi) * (alpha-hyb) v1 += vj - .5 * vk else: v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi) elif hermi != 2: v1 += mf.get_j(mol, dm1, hermi=hermi) return v1 elif singlet: def vind(dm1): if hermi == 2: v1 = numpy.zeros_like(dm1) else: # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled v1 = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm1, 0, True, rho0, vxc, fxc, max_memory=max_memory) v1 *= .5 if hybrid: if hermi != 2: vj, vk = mf.get_jk(mol, dm1, hermi=hermi) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb vk += rks._get_k_lr(mol, dm1, omega, hermi) * (alpha-hyb) v1 += vj - .5 * vk else: v1 -= .5 * hyb * mf.get_k(mol, dm1, hermi=hermi) elif hermi != 2: v1 += mf.get_j(mol, dm1, hermi=hermi) return v1 else: # triplet def vind(dm1): if hermi == 2: v1 = numpy.zeros_like(dm1) else: # nr_rks_fxc_st requires alpha of dm1, dm1*.5 should be scaled v1 = numint.nr_rks_fxc_st(ni, mol, mf.grids, mf.xc, dm0, dm1, 0, False, rho0, vxc, fxc, max_memory=max_memory) v1 *= .5 if hybrid: vk = mf.get_k(mol, dm1, hermi=hermi) vk *= hyb if abs(omega) > 1e-10: # For range separated Coulomb vk += rks._get_k_lr(mol, dm1, omega, hermi) * (alpha-hyb) v1 += -.5 * vk return v1 else: # HF if (singlet is None or singlet) and hermi != 2: def vind(dm1): vj, vk = mf.get_jk(mol, dm1, hermi=hermi) return vj - .5 * vk else: def vind(dm1): return -.5 * mf.get_k(mol, dm1, hermi=hermi) return vind