def test_mn_scf_0085(self): from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations """ Spin-resolved case redoing SCF procedure. """ #print(__name__, dir(gto_mf_uhf)) #print(set(dir(gto_mf_uhf))-set(dir(gto_mf_rhf))) scf = nao_scf(mf=gto_mf_uhf, gto=mol, verbosity=0) self.assertEqual(scf.nspin, 2) jn,kn = scf.get_jk() for d,dr in zip(jg.shape, jn.shape): self.assertEqual(d, dr) for d,dr in zip(kg.shape, kn.shape): self.assertEqual(d, dr) #print(__name__, jn.shape, kn.shape) dm_nao = scf.make_rdm1() Ehartree = (jn*dm_nao.reshape(scf.nspin,scf.norbs,scf.norbs)).sum()/2.0 Ex = (kn*dm_nao.reshape(scf.nspin,scf.norbs,scf.norbs)).sum()/2.0 self.assertAlmostEqual(Ehartree, 248.461304275) self.assertAlmostEqual(Ex, 50.9912877484) ne_occ = fermi_dirac_occupations(scf.telec, scf.mo_energy, scf.fermi_energy).sum() self.assertAlmostEqual(ne_occ, 25.0) ## Do unrestricted Hartree-Fock SCF with numerical atomic orbitals e_tot = scf.kernel_scf() self.assertEqual(scf.nspin, 2) self.assertAlmostEqual(e_tot, -1149.86757123) ne_occ = fermi_dirac_occupations(scf.telec, scf.mo_energy, scf.fermi_energy).sum() self.assertAlmostEqual(ne_occ, 25.0) o,dm = scf.overlap_coo().toarray(), scf.make_rdm1() for nes, dms in zip(scf.nelec, dm[0,:,:,:,0]): #print(__name__, (dms*o).sum(), nes) self.assertAlmostEqual((dms*o).sum(), nes, 4)
def __init__(self, **kw): from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations tddft_iter.__init__(self, **kw) self.x_zip = kw['x_zip'] if 'x_zip' in kw else False self.x_zip_eps = kw['x_zip_eps'] if 'x_zip_eps' in kw else 0.05 self.x_zip_emax = kw['x_zip_emax'] if 'x_zip_emax' in kw else 0.25 if self.x_zip: # redefine the eigenvectors sm2e,sma2x = self.build_x_zip() if self.verbosity>0: print(__name__, 'self.mo_energy.shape =', self.mo_energy.shape) print(__name__, 'sm2e.shape =', sm2e.shape) self.ksn2e = array([sm2e]) ksn2fd = fermi_dirac_occupations(self.telec, self.ksn2e, self.fermi_energy) for s,n2fd in enumerate(ksn2fd[0]): if not all(n2fd>self.nfermi_tol): continue print(self.telec, s, nfermi_tol, n2fd) raise RuntimeError(__name__, 'telec is too high?') self.ksn2f = (3-self.nspin)*ksn2fd self.nfermi = array([argmax(ksn2fd[0,s,:]<self.nfermi_tol) for s in range(self.nspin)], dtype=int) self.vstart = array([argmax(1.0-ksn2fd[0,s,:]>=self.nfermi_tol) for s in range(self.nspin)], dtype=int) self.xocc = [ma2x[:nfermi,:] for ma2x,nfermi in zip(sma2x,self.nfermi)] self.xvrt = [ma2x[vstart:,:] for ma2x,vstart in zip(sma2x,self.vstart)]
def read_wfsx(self, fname, **kw): """ An occasional reading of the SIESTA's .WFSX file """ from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c from pyscf.nao.m_siesta2blanko_denvec import _siesta2blanko_denvec from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations self.wfsx = siesta_wfsx_c(fname=fname, **kw) assert self.nkpoints == self.wfsx.nkpoints assert self.norbs == self.wfsx.norbs assert self.nspin == self.wfsx.nspin orb2m = self.get_orb2m() for k in range(self.nkpoints): for s in range(self.nspin): for n in range(self.norbs): _siesta2blanko_denvec(orb2m, self.wfsx.x[k,s,n,:,:]) self.mo_coeff = np.require(self.wfsx.x, dtype=self.dtype, requirements='CW') self.mo_energy = np.require(self.wfsx.ksn2e, dtype=self.dtype, requirements='CW') self.telec = kw['telec'] if 'telec' in kw else self.hsx.telec self.nelec = kw['nelec'] if 'nelec' in kw else self.hsx.nelec self.fermi_energy = kw['fermi_energy'] if 'fermi_energy' in kw else self.fermi_energy ksn2fd = fermi_dirac_occupations(self.telec, self.mo_energy, self.fermi_energy) self.mo_occ = (3-self.nspin)*ksn2fd return self
def test_fermi_dirac(self): """ This is to test the Fermi-Dirac occupations """ ksn2e = np.zeros([1,1,100], dtype=np.float32) ksn2e[0,0,:] = np.linspace(-1000.0, 100.0, 100) fermi_energy = -100.0 telec = 0.1 ksn2f = fermi_dirac_occupations(telec, ksn2e, fermi_energy) self.assertAlmostEqual(ksn2f.sum(), 81.5)
def get_occupations(self, telec=None, ksn2e=None, fermi_energy=None): """ Compute occupations of electron levels according to Fermi-Dirac distribution """ from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations Telec = self.hsx.telec if telec is None else telec ksn2E = self.wfsx.ksn2e if ksn2e is None else ksn2e Fermi = self.fermi_energy if fermi_energy is None else fermi_energy ksn2fd = fermi_dirac_occupations(Telec, ksn2E, Fermi) ksn2fd = (3.0-self.nspin)*ksn2fd return ksn2fd
def test_fermi_energy_spin_saturated(self): """ This is to test the determination of Fermi level""" ee = np.arange(-10.13, 100.0, 0.1) #print('0: ', ee.shape) nelec = 5.0 telec = 0.01 fermi_energy = get_fermi_energy(ee, nelec, telec) occ = 2.0*fermi_dirac_occupations(telec, ee, fermi_energy) self.assertAlmostEqual(occ.sum(), 5.0) self.assertAlmostEqual(fermi_energy, -9.93)
def test_fermi_energy_spin_resolved_spin1(self): """ This is to test the determination of Fermi level""" ee = np.linspace(-10.13, 99.97, 1102).reshape((1,1102)) #print('1: ', ee.shape) nelec = 5.0 telec = 0.01 fermi_energy = get_fermi_energy(ee, nelec, telec) occ = 2.0*fermi_dirac_occupations(telec, ee, fermi_energy) self.assertAlmostEqual(occ.sum(), 5.0) self.assertAlmostEqual(fermi_energy, -9.93)
def test_fermi_energy_spin_resolved_even(self): """ This is to test the determination of Fermi level in spin-resolved case""" ee = np.row_stack((np.linspace(-10.3, 100.0, 1003), np.linspace(-10.0, 100.0, 1003))) nelec = 20.0 telec = 0.02 #print(ee) fermi_energy = get_fermi_energy(ee, nelec, telec) occ = fermi_dirac_occupations(telec, ee, fermi_energy) self.assertAlmostEqual(occ.sum(), 20.0) self.assertAlmostEqual(fermi_energy, -9.10544404859)
def test_dft_sv(self): """ Try to run DFT with system_vars_c """ from pyscf.nao import system_vars_c from pyscf.nao.m_comp_dm import comp_dm from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations sv = system_vars_c().init_siesta_xml(label='water', cd=os.path.dirname( os.path.abspath(__file__))) ksn2fd = fermi_dirac_occupations(sv.hsx.telec, sv.wfsx.ksn2e, sv.fermi_energy) ksn2f = (3 - sv.nspin) * ksn2fd dm = comp_dm(sv.wfsx.x, ksn2f) vxc = sv.vxc_lil(dm, 'LDA,PZ')
def init_mo_coeff_fireball(self, **kw): """ Constructor a mean-field class from the preceeding FIREBALL calculation """ from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations from pyscf.nao.m_fireball_get_eigen_dat import fireball_get_eigen_dat from pyscf.nao.m_fireball_hsx import fireball_hsx self.telec = kw['telec'] if 'telec' in kw else self.telec self.fermi_energy = kw['fermi_energy'] if 'fermi_energy' in kw else self.fermi_energy self.mo_energy = np.require(fireball_get_eigen_dat(self.cd), dtype=self.dtype, requirements='CW') ksn2fd = fermi_dirac_occupations(self.telec, self.mo_energy, self.fermi_energy) self.mo_occ = (3-self.nspin)*ksn2fd if abs(self.nelectron-self.mo_occ.sum())>1e-6: raise RuntimeError("mo_occ wrong?" ) print(__name__, ' self.nspecies ', self.nspecies) print(self.sp_mu2j) self.hsx = fireball_hsx(self, **kw)
def init_mo_coeff_label(self, **kw): """ Constructor a mean-field class from the preceeding SIESTA calculation """ from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations self.mo_coeff = np.require(self.wfsx.x, dtype=self.dtype, requirements='CW') self.mo_energy = np.require(self.wfsx.ksn2e, dtype=self.dtype, requirements='CW') self.telec = kw['telec'] if 'telec' in kw else self.hsx.telec if self.nspin==1: self.nelec = kw['nelec'] if 'nelec' in kw else np.array([self.hsx.nelec]) elif self.nspin==2: self.nelec = kw['nelec'] if 'nelec' in kw else np.array([int(self.hsx.nelec/2), int(self.hsx.nelec/2)]) print(__name__, 'not sure here: self.nelec', self.nelec) else: raise RuntimeError('0>nspin>2?') self.fermi_energy = kw['fermi_energy'] if 'fermi_energy' in kw else self.fermi_energy ksn2fd = fermi_dirac_occupations(self.telec, self.mo_energy, self.fermi_energy) self.mo_occ = (3-self.nspin)*ksn2fd
def init_mo_coeff_fireball(self, **kw): """ Constructor a mean-field class from the preceeding FIREBALL calculation """ from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations from pyscf.nao.m_fireball_get_eigen_dat import fireball_get_eigen_dat from pyscf.nao.m_fireball_hsx import fireball_hsx self.telec = kw['telec'] if 'telec' in kw else self.telec self.fermi_energy = kw[ 'fermi_energy'] if 'fermi_energy' in kw else self.fermi_energy self.mo_energy = require(fireball_get_eigen_dat(self.cd), dtype=self.dtype, requirements='CW') ksn2fd = fermi_dirac_occupations(self.telec, self.mo_energy, self.fermi_energy) self.mo_occ = (3 - self.nspin) * ksn2fd if abs(self.nelectron - self.mo_occ.sum()) > 1e-6: raise RuntimeError("mo_occ wrong?") #print(__name__, ' self.nspecies ', self.nspecies) #print(self.sp_mu2j) self.hsx = fireball_hsx(self, **kw)
def test_fermi_energy_spin_resolved_even_kpoints_spin2(self): """ This is to test the determination of Fermi level in spin-resolved case""" ee = np.row_stack((np.linspace(-10.1, 100.0, 1003), np.linspace(-10.2, 100.0, 1003), np.linspace(-10.3, 100.0, 1003), np.linspace(-10.4, 100.0, 1003))).reshape((2,2,1003)) nelec = 20.0 telec = 0.02 nkpts = ee.shape[0] nspin = ee.shape[-2] #print(ee) fermi_energy = get_fermi_energy(ee, nelec, telec) occ = (3.0-nspin)*fermi_dirac_occupations(telec, ee, fermi_energy) #print(occ) #print(occ.sum()/nkpts) #print(fermi_energy) self.assertAlmostEqual(occ.sum()/nkpts, 20.0) self.assertAlmostEqual(fermi_energy, -9.2045998319213016)
def init_mo_coeff_label(self, **kw): """ Constructor a mean-field class from the preceeding SIESTA calculation """ from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations from pyscf.nao.m_fermi_energy import fermi_energy self.mo_coeff = require(self.wfsx.x, dtype=self.dtype, requirements='CW') self.mo_energy = require(self.wfsx.ksn2e, dtype=self.dtype, requirements='CW') self.telec = kw['telec'] if 'telec' in kw else self.hsx.telec self.magnetization = kw[ 'magnetization'] if 'magnetization' in kw else None #using this key for number of unpaired if self.nspin == 1: self.nelec = kw['nelec'] if 'nelec' in kw else np.array( [self.hsx.nelec]) elif (self.nspin == 2 and self.magnetization == None): self.nelec = kw['nelec'] if 'nelec' in kw else np.array( [int(self.hsx.nelec / 2), int(self.hsx.nelec / 2)]) elif (self.nspin == 2 and self.magnetization != None): if 'nelec' in kw: self.nelec = kw['nelec'] else: ne = self.hsx.nelec nalpha = (ne + self.magnetization) // 2 nbeta = nalpha - self.magnetization if nalpha + nbeta != ne: raise RuntimeError( 'Electron number %d and spin %d are not consistent\n' 'Note mol.spin = 2S = Nalpha - Nbeta, not 2S+1' % (ne, self.magnetization)) self.nelec = np.array([nalpha, nbeta]) if self.verbosity > 0: print(__name__, 'not sure here: self.nelec', self.nelec) else: raise RuntimeError('0>nspin>2?') if 'fermi_energy' in kw: self.fermi_energy = kw[ 'fermi_energy'] # possibility to redefine Fermi energy ksn2fd = fermi_dirac_occupations(self.telec, self.mo_energy, self.fermi_energy) self.mo_occ = (3 - self.nspin) * ksn2fd nelec_occ = np.einsum('ksn->s', self.mo_occ) / self.nkpoints if not np.allclose(self.nelec, nelec_occ, atol=1e-4): fermi_guess = fermi_energy(self.wfsx.ksn2e, self.hsx.nelec, self.hsx.telec) np.set_printoptions(precision=2, linewidth=1000) raise RuntimeWarning( '''occupations?\n mo_occ: \n{}\n telec: {}\n nelec expected: {} nelec(occ): {}\n Fermi guess: {}\n Fermi: {}\n E_n:\n{}'''.format( self.mo_occ, self.telec, self.nelec, nelec_occ, fermi_guess, self.fermi_energy, self.mo_energy)) if 'fermi_energy' in kw and self.verbosity > 0: po = np.get_printoptions() np.set_printoptions(precision=2, linewidth=1000) print(__name__, "mo_occ:\n{}".format(self.mo_occ)) np.set_printoptions(**po)
def __init__(self, sv, pb, tddft_iter_tol=1e-2, tddft_iter_broadening=0.00367493, nfermi_tol=1e-5, telec=None, nelec=None, fermi_energy=None, xc_code='LDA,PZ', GPU=False, precision="single", **kvargs): """ Iterative TDDFT a la PK, DF, OC JCTC """ from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations from pyscf.nao.m_comp_dm import comp_dm import sys assert tddft_iter_tol > 1e-6 assert type(tddft_iter_broadening) == float assert sv.wfsx.x.shape[-1] == 1 # i.e. real eigenvectors we accept here if precision == "single": self.dtype = np.float32 self.dtypeComplex = np.complex64 elif precision == "double": self.dtype = np.float64 self.dtypeComplex = np.complex128 else: raise ValueError("precision can be only single or double") self.rf0_ncalls = 0 self.l0_ncalls = 0 self.matvec_ncalls = 0 self.tddft_iter_tol = tddft_iter_tol self.eps = tddft_iter_broadening self.sv, self.pb, self.norbs, self.nspin = sv, pb, sv.norbs, sv.nspin self.v_dab = pb.get_dp_vertex_coo(dtype=self.dtype).tocsr() self.cc_da = pb.get_da2cc_coo(dtype=self.dtype).tocsr() self.moms0, self.moms1 = pb.comp_moments(dtype=self.dtype) self.nprod = self.moms0.size self.kernel, self.kernel_dim = pb.comp_coulomb_pack(dtype=self.dtype) if xc_code.upper() != 'RPA': dm = comp_dm(sv.wfsx.x, sv.get_occupations()) pb.comp_fxc_pack(dm, xc_code, kernel=self.kernel, dtype=self.dtype, **kvargs) self.telec = sv.hsx.telec if telec is None else telec self.nelec = sv.hsx.nelec if nelec is None else nelec self.fermi_energy = sv.fermi_energy if fermi_energy is None else fermi_energy self.x = np.require(sv.wfsx.x, dtype=self.dtype, requirements='CW') self.ksn2e = np.require(sv.wfsx.ksn2e, dtype=self.dtype, requirements='CW') ksn2fd = fermi_dirac_occupations(self.telec, self.ksn2e, self.fermi_energy) self.ksn2f = (3 - self.nspin) * ksn2fd self.nfermi = np.argmax(ksn2fd[0, 0, :] < nfermi_tol) self.vstart = np.argmax(1.0 - ksn2fd[0, 0, :] > nfermi_tol) self.xocc = self.x[0, 0, 0:self.nfermi, :, 0] # does python creates a copy at this point ? self.xvrt = self.x[0, 0, self.vstart:, :, 0] # does python creates a copy at this point ? self.tddft_iter_gpu = tddft_iter_gpu_c(GPU, self.v_dab, self.ksn2f, self.ksn2e, self.norbs, self.nfermi, self.vstart)
def __init__(self, **kw): from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations from scipy.linalg import blas self.dtype = kw['dtype'] if 'dtype' in kw else np.float32 for x in ['dtype']: kw.pop(x, None) mf.__init__(self, dtype=self.dtype, **kw) self.dealloc_hsx = kw['dealloc_hsx'] if 'dealloc_hsx' in kw else True self.eps = kw[ 'iter_broadening'] if 'iter_broadening' in kw else 0.00367493 self.GPU = GPU = kw['GPU'] if 'GPU' in kw else None self.nfermi_tol = nfermi_tol = kw[ 'nfermi_tol'] if 'nfermi_tol' in kw else 1e-5 self.telec = kw['telec'] if 'telec' in kw else self.telec self.fermi_energy = kw[ 'fermi_energy'] if 'fermi_energy' in kw else self.fermi_energy assert type(self.eps) == float self.spmv = spmv_wrapper if self.dtype == np.float32: self.dtypeComplex = np.complex64 self.gemm = blas.sgemm if self.scipy_ver > 0: self.spmv = blas.sspmv elif self.dtype == np.float64: self.dtypeComplex = np.complex128 self.gemm = blas.dgemm if self.scipy_ver > 0: self.spmv = blas.dspmv else: raise ValueError("dtype can be only float32 or float64") self.div_eigenenergy_numba = None if self.use_numba: from pyscf.nao.m_div_eigenenergy_numba import div_eigenenergy_numba self.div_eigenenergy_numba = div_eigenenergy_numba if hasattr(self, 'hsx') and self.dealloc_hsx: self.hsx.deallocate() # deallocate hsx self.ksn2e = self.mo_energy ksn2fd = fermi_dirac_occupations(self.telec, self.ksn2e, self.fermi_energy) for s, n2fd in enumerate(ksn2fd[0]): if not all(n2fd > self.nfermi_tol): continue print(self.telec, s, self.nfermi_tol, n2fd) raise RuntimeError(__name__, 'telec is too high?') self.ksn2f = (3 - self.nspin) * ksn2fd self.nfermi = array([ argmax(ksn2fd[0, s, :] < self.nfermi_tol) for s in range(self.nspin) ], dtype=int) self.vstart = array([ argmax(1.0 - ksn2fd[0, s, :] >= self.nfermi_tol) for s in range(self.nspin) ], dtype=int) self.xocc = [ self.mo_coeff[0, s, :nfermi, :, 0] for s, nfermi in enumerate(self.nfermi) ] self.xvrt = [ self.mo_coeff[0, s, vstart:, :, 0] for s, vstart in enumerate(self.vstart) ] if self.verbosity > 1: print(__name__, ' self.dtype ', self.dtype) print(__name__, ' self.xocc[0].dtype ', self.xocc[0].dtype) print(__name__, ' self.xvrt[0].dtype ', self.xvrt[0].dtype) print(__name__, ' self.ksn2e.dtype ', self.ksn2e.dtype) print(__name__, ' self.ksn2f.dtype ', self.ksn2f.dtype) self.rf0_ncalls = 0 if not hasattr(self, 'pb'): print('no pb?') return pb = self.pb self.v_dab = pb.get_dp_vertex_sparse(dtype=self.dtype, sparseformat=coo_matrix).tocsr() self.cc_da = pb.get_da2cc_sparse(dtype=self.dtype, sparseformat=coo_matrix).tocsr() self.moms0, self.moms1 = pb.comp_moments(dtype=self.dtype) self.nprod = self.moms0.size if self.verbosity > 0: print(__name__, ' nprod ', self.nprod, ' cc_da.shape ', self.cc_da.shape) self.td_GPU = tddft_iter_gpu_c(GPU, self.mo_coeff[0, 0, :, :, 0], self.ksn2f, self.ksn2e, self.norbs, self.nfermi, self.nprod, self.vstart)
def __init__(self, **kw): from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations self.dtype = kw['dtype'] if 'dtype' in kw else np.float32 for x in ['dtype']: kw.pop(x, None) mf.__init__(self, dtype=self.dtype, **kw) if self.dtype == np.float32: self.gemm = blas.sgemm elif self.dtype == np.float64: self.gemm = blas.dgemm else: raise ValueError("dtype can be only float32 or float64") self.dealloc_hsx = kw['dealloc_hsx'] if 'dealloc_hsx' in kw else True self.eps = kw[ 'iter_broadening'] if 'iter_broadening' in kw else 0.00367493 self.GPU = GPU = kw['GPU'] if 'GPU' in kw else None self.nfermi_tol = nfermi_tol = kw[ 'nfermi_tol'] if 'nfermi_tol' in kw else 1e-5 self.telec = kw['telec'] if 'telec' in kw else self.telec self.fermi_energy = kw[ 'fermi_energy'] if 'fermi_energy' in kw else self.fermi_energy assert type(self.eps) == float self.div_numba = None if self.use_numba: from pyscf.nao.m_div_eigenenergy_numba import div_eigenenergy_numba self.div_numba = div_eigenenergy_numba if hasattr(self, 'hsx') and self.dealloc_hsx: self.hsx.deallocate() # deallocate hsx self.ksn2e = self.mo_energy # Just a pointer here. Is it ok? if 'fermi_energy' in kw: if self.verbosity > 0: print(__name__, 'Fermi energy is specified => recompute occupations') ksn2fd = fermi_dirac_occupations(self.telec, self.ksn2e, self.fermi_energy) for s, n2fd in enumerate(ksn2fd[0]): if not all(n2fd > self.nfermi_tol): continue print(self.telec, s, self.nfermi_tol, n2fd) raise RuntimeError(__name__, 'telec is too high?') ksn2f = self.ksn2f = (3 - self.nspin) * ksn2fd else: ksn2f = self.ksn2f = self.mo_occ self.nfermi = array([argmax(ksn2f[0,s]<self.nfermi_tol)\ for s in range(self.nspin)], dtype=int) self.vstart = array([argmax(1.0-ksn2f[0,s]>=self.nfermi_tol)\ for s in range(self.nspin)], dtype=int) # should not be this list arrays ?? self.xocc = [self.mo_coeff[0,s,:nfermi,:,0]\ for s,nfermi in enumerate(self.nfermi)] self.xvrt = [self.mo_coeff[0,s,vstart:,:,0]\ for s,vstart in enumerate(self.vstart)] if self.verbosity > 4: #print(__name__, '\t====> self.dtype ', self.dtype) print(__name__, '\t====> self.xocc[0].dtype ', self.xocc[0].dtype) print(__name__, '\t====> self.xvrt[0].dtype ', self.xvrt[0].dtype) print( __name__, '\t====> MO energies (ksn2e) (eV):\n{},\tType: {}'.format( self.ksn2e * HARTREE2EV, self.ksn2e.dtype)) print( __name__, '\t====> Occupations (ksn2f):\n{},\tType: {}'.format( self.ksn2f, self.ksn2f.dtype)) self.rf0_ncalls = 0 if not hasattr(self, 'pb'): print('no pb?') return pb = self.pb self.moms0, self.moms1 = pb.comp_moments(dtype=self.dtype) self.td_GPU = tddft_iter_gpu_c(GPU, self.mo_coeff[0, 0, :, :, 0], self.ksn2f, self.ksn2e, self.norbs, self.nfermi, self.nprod, self.vstart)
def func1(x, i2e, nelec, telec, norm_const): from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations nne = norm_const*(fermi_dirac_occupations(telec, i2e, x)).sum()-nelec return nne
def __init__(self, sv, pb, tddft_iter_tol=1e-2, tddft_iter_broadening=0.00367493, nfermi_tol=1e-5, telec=None, nelec=None, fermi_energy=None, xc_code='LDA,PZ', GPU=False, precision="single", load_kernel=False, **kvargs): """ Iterative TDDFT a la PK, DF, OC JCTC """ from pyscf.nao.m_fermi_dirac import fermi_dirac_occupations from pyscf.nao.m_comp_dm import comp_dm assert tddft_iter_tol > 1e-6 assert type(tddft_iter_broadening) == float assert sv.wfsx.x.shape[-1] == 1 # i.e. real eigenvectors we accept here if precision == "single": self.dtype = np.float32 self.dtypeComplex = np.complex64 self.gemm = blas.sgemm if scipy_ver > 0: self.spmv = blas.sspmv else: self.spmv = spmv_wrapper elif precision == "double": self.dtype = np.float64 self.dtypeComplex = np.complex128 self.gemm = blas.dgemm if scipy_ver > 0: self.spmv = blas.dspmv else: self.spmv = spmv_wrapper else: raise ValueError("precision can be only single or double") self.rf0_ncalls = 0 self.l0_ncalls = 0 self.matvec_ncalls = 0 self.tddft_iter_tol = tddft_iter_tol self.eps = tddft_iter_broadening self.sv, self.pb, self.norbs, self.nspin = sv, pb, sv.norbs, sv.nspin self.v_dab = pb.get_dp_vertex_sparse(dtype=self.dtype, sparseformat=coo_matrix).tocsr() self.cc_da = pb.get_da2cc_sparse(dtype=self.dtype, sparseformat=coo_matrix).tocsr() self.moms0, self.moms1 = pb.comp_moments(dtype=self.dtype) self.nprod = self.moms0.size if load_kernel: self.load_kernel(**kvargs) else: self.kernel, self.kernel_dim = pb.comp_coulomb_pack( dtype=self.dtype) # Lower Triangular Part of the kernel assert self.nprod == self.kernel_dim, "%r %r " % (self.nprod, self.kernel_dim) if xc_code.upper() != 'RPA': dm = comp_dm(sv.wfsx.x, sv.get_occupations()) pb.comp_fxc_pack(dm, xc_code, kernel=self.kernel, dtype=self.dtype, **kvargs) self.telec = sv.hsx.telec if telec is None else telec self.nelec = sv.hsx.nelec if nelec is None else nelec self.fermi_energy = sv.fermi_energy if fermi_energy is None else fermi_energy # probably unnecessary, require probably does a copy # problematic for the dtype, must there should be another option #self.x = np.require(sv.wfsx.x, dtype=self.dtype, requirements='CW') self.ksn2e = np.require(sv.wfsx.ksn2e, dtype=self.dtype, requirements='CW') ksn2fd = fermi_dirac_occupations(self.telec, self.ksn2e, self.fermi_energy) self.ksn2f = (3 - self.nspin) * ksn2fd self.nfermi = np.argmax(ksn2fd[0, 0, :] < nfermi_tol) self.vstart = np.argmax(1.0 - ksn2fd[0, 0, :] > nfermi_tol) self.xocc = sv.wfsx.x[0, 0, 0:self.nfermi, :, 0] # does python creates a copy at this point ? self.xvrt = sv.wfsx.x[0, 0, self.vstart:, :, 0] # does python creates a copy at this point ? self.tddft_iter_gpu = tddft_iter_gpu_c(GPU, self.v_dab, self.ksn2f, self.ksn2e, self.norbs, self.nfermi, self.vstart)