예제 #1
0
  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)
예제 #2
0
  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)]
예제 #3
0
파일: mf.py 프로젝트: chrinide/pyscf
  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
예제 #4
0
 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)
예제 #5
0
파일: mf.py 프로젝트: chrinide/pyscf
 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
예제 #6
0
 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)
예제 #7
0
 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)
예제 #8
0
  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)
예제 #9
0
    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')
예제 #10
0
파일: mf.py 프로젝트: chrinide/pyscf
 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)
예제 #11
0
파일: mf.py 프로젝트: chrinide/pyscf
 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
예제 #12
0
    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)
예제 #13
0
  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)
예제 #14
0
파일: nao.py 프로젝트: zzy2014/pyscf
    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)
예제 #15
0
    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)
예제 #16
0
    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)
예제 #17
0
    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)
예제 #18
0
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
예제 #19
0
    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)