示例#1
0
    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 = 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.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
示例#2
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
示例#3
0
    def read_wfsx(self, fname, **kvargs):
        """ An occasional reading of the SIESTA's .WFSX file """
        from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c
        self.wfsx = siesta_wfsx_c(fname=fname, **kvargs)

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

        return self
 def read_wfsx(self, fname, **kvargs):
   """ An occasional reading of the SIESTA's .WFSX file """
   from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c
   self.wfsx = siesta_wfsx_c(fname=fname, **kvargs)
   
   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,:,:])
   
   return self
示例#5
0
    def init_siesta_xml(self, **kw):
        from pyscf.nao.m_siesta_xml import siesta_xml
        from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c
        from pyscf.nao.m_siesta_ion_xml import siesta_ion_xml
        from pyscf.nao.m_siesta_hsx import siesta_hsx_c
        from timeit import default_timer as timer
        """
      Initialise system var using only the siesta files (siesta.xml in particular is needed)

      System variables:
      -----------------
        label (string): calculation label
        chdir (string): calculation directory
        xml_dict (dict): information extracted from the xml siesta output, see m_siesta_xml
        wfsx: class use to extract the information about wavefunctions, see m_siesta_wfsx
        hsx: class to store a sparse representation of hamiltonian and overlap, see m_siesta_hsx
        norbs_sc (integer): number of orbital
        ucell (array, float): unit cell
        sp2ion (list): species to ions, list of the species associated to the information from the ion files, see m_siesta_ion_xml
        ao_log: Atomic orbital on an logarithmic grid, see m_ao_log
        atom2coord (array, float): array containing the coordinates of each atom.
        natm, natoms (integer): number of atoms
        norbs (integer): number of orbitals
        nspin (integer): number of spin
        nkpoints (integer): number of kpoints
        fermi_energy (float): Fermi energy
        atom2sp (list): atom to specie, list associating the atoms to their specie number
        atom2s: atom -> first atomic orbital in a global orbital counting
        atom2mu_s: atom -> first multiplett (radial orbital) in a global counting of radial orbitals
        sp2symbol (list): list associating the species to their symbol
        sp2charge (list): list associating the species to their charge
        state (string): this is an internal information on the current status of the class
    """
        #label='siesta', cd='.', verbose=0,

        self.label = label = kw['label'] if 'label' in kw else 'siesta'
        self.cd = cd = kw['cd'] if 'cd' in kw else '.'
        self.verbose = verbose = kw['verbose'] if 'verbose' in kw else 0
        self.xml_dict = siesta_xml(cd + '/' + self.label + '.xml')
        self.wfsx = siesta_wfsx_c(**kw)
        self.hsx = siesta_hsx_c(fname=cd + '/' + self.label + '.HSX', **kw)
        self.norbs_sc = self.wfsx.norbs if self.hsx.orb_sc2orb_uc is None else len(
            self.hsx.orb_sc2orb_uc)
        self.ucell = self.xml_dict["ucell"]
        ##### The parameters as fields
        self.sp2ion = []
        for sp in self.wfsx.sp2strspecie:
            self.sp2ion.append(siesta_ion_xml(cd + '/' + sp + '.ion.xml'))

        _siesta_ion_add_sp2(self, self.sp2ion)
        self.ao_log = ao_log_c().init_ao_log_ion(self.sp2ion)

        self.atom2coord = self.xml_dict['atom2coord']
        self.natm = self.natoms = len(self.xml_dict['atom2sp'])
        self.norbs = self.wfsx.norbs
        self.nspin = self.wfsx.nspin
        self.nkpoints = self.wfsx.nkpoints
        self.fermi_energy = self.xml_dict['fermi_energy']

        strspecie2sp = {}
        # initialise a dictionary with species string as key
        # associated to the specie number
        for sp, strsp in enumerate(self.wfsx.sp2strspecie):
            strspecie2sp[strsp] = sp

        # list of atoms associated to them specie number
        self.atom2sp = np.empty((self.natm), dtype=np.int64)
        for o, atom in enumerate(self.wfsx.orb2atm):
            self.atom2sp[atom - 1] = strspecie2sp[self.wfsx.orb2strspecie[o]]

        self.atom2s = np.zeros((self.natm + 1), dtype=np.int64)
        for atom, sp in enumerate(self.atom2sp):
            self.atom2s[atom +
                        1] = self.atom2s[atom] + self.ao_log.sp2norbs[sp]

        # atom2mu_s list of atom associated to them multipletts (radial orbitals)
        self.atom2mu_s = np.zeros((self.natm + 1), dtype=np.int64)
        for atom, sp in enumerate(self.atom2sp):
            self.atom2mu_s[atom +
                           1] = self.atom2mu_s[atom] + self.ao_log.sp2nmult[sp]

        orb2m = self.get_orb2m()
        _siesta2blanko_csr(orb2m, self.hsx.s4_csr, self.hsx.orb_sc2orb_uc)

        for s in range(self.nspin):
            _siesta2blanko_csr(orb2m, self.hsx.spin2h4_csr[s],
                               self.hsx.orb_sc2orb_uc)

        #t1 = timer()
        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, :, :])
        #t2 = timer(); print(t2-t1, 'rsh wfsx'); t1 = timer()

        self.sp2symbol = [
            str(ion['symbol'].replace(' ', '')) for ion in self.sp2ion
        ]
        self.sp2charge = self.ao_log.sp2charge
        self.init_libnao()
        self.state = 'should be useful for something'

        # Trying to be similar to mole object from pySCF
        self._xc_code = 'LDA,PZ'  # estimate how ?
        self._nelectron = self.hsx.nelec
        self.cart = False
        self.spin = self.nspin - 1
        self.stdout = sys.stdout
        self.symmetry = False
        self.symmetry_subgroup = None
        self._built = True
        self.max_memory = 20000
        self.incore_anyway = False
        self.nbas = self.atom2mu_s[-1]  # total number of radial orbitals
        self.mu2orb_s = np.zeros((self.nbas + 1), dtype=np.int64)
        for sp, mu_s in zip(self.atom2sp, self.atom2mu_s):
            for mu, j in enumerate(self.ao_log.sp_mu2j[sp]):
                self.mu2orb_s[mu_s + mu +
                              1] = self.mu2orb_s[mu_s + mu] + 2 * j + 1

        self._atom = [(self.sp2symbol[sp], list(self.atom2coord[ia, :]))
                      for ia, sp in enumerate(self.atom2sp)]
        return self
示例#6
0
    def init_ase_atoms(self, Atoms, **kvargs):
        """ Initialise system vars using siesta file and Atom object from ASE."""
        from pyscf.nao.m_siesta_xml import siesta_xml
        from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c
        from pyscf.nao.m_siesta_ion_xml import siesta_ion_xml
        from pyscf.nao.m_siesta_hsx import siesta_hsx_c

        self.label = 'ase' if label is None else label
        self.xml_dict = siesta_xml(self.label)
        self.wfsx = siesta_wfsx_c(self.label)
        self.hsx = siesta_hsx_c(self.label, **kvargs)
        self.norbs_sc = self.wfsx.norbs if self.hsx.orb_sc2orb_uc is None else len(
            self.hsx.orb_sc2orb_uc)

        try:
            import ase
        except:
            warn('no ASE installed: try via siesta.xml')
            self.init_siesta_xml(**kvargs)

        self.Atoms = Atoms

        ##### The parameters as fields
        self.sp2ion = []
        species = []
        for sp in Atoms.get_chemical_symbols():
            if sp not in species:
                species.append(sp)
                self.sp2ion.append(siesta_ion_xml(sp + '.ion.xml'))

        _add_mu_sp2(self, self.sp2ion)
        self.sp2ao_log = ao_log_c(self.sp2ion)

        self.natm = self.natoms = Atoms.get_positions().shape[0]
        self.norbs = self.wfsx.norbs
        self.nspin = self.wfsx.nspin
        self.nkpoints = self.wfsx.nkpoints

        strspecie2sp = {}
        for sp in range(len(self.wfsx.sp2strspecie)):
            strspecie2sp[self.wfsx.sp2strspecie[sp]] = sp

        self.atom2sp = np.empty((self.natoms), dtype='int64')
        for i, sp in enumerate(Atoms.get_chemical_symbols()):
            self.atom2sp[i] = strspecie2sp[sp]

        self.atom2s = np.zeros((sv.natm + 1), dtype=np.int64)
        for atom, sp in enumerate(sv.atom2sp):
            atom2s[atom + 1] = atom2s[atom] + self.ao_log.sp2norbs[sp]

        self.atom2mu_s = np.zeros((self.natm + 1), dtype=np.int64)
        for atom, sp in enumerate(self.atom2sp):
            self.atom2mu_s[atom +
                           1] = self.atom2mu_s[atom] + self.ao_log.sp2nmult[sp]

        orb2m = get_orb2m(self)
        _siesta2blanko_csr(orb2m, self.hsx.s4_csr, self.hsx.orb_sc2orb_uc)

        for s in range(self.nspin):
            _siesta2blanko_csr(orb2m, self.hsx.spin2h4_csr[s],
                               self.hsx.orb_sc2orb_uc)

        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.sp2symbol = [
            str(ion['symbol'].replace(' ', '')) for ion in self.sp2ion
        ]
        self.sp2charge = self.ao_log.sp2charge
        self.nbas = self.atom2mu_s[-1]  # total number of radial orbitals
        self.mu2orb_s = np.zeros((self.nbas + 1), dtype=np.int64)
        for sp, mu_s in zip(self.atom2sp, self.atom2mu_s):
            for mu, j in enumerate(self.ao_log.sp_mu2j[sp]):
                self.mu2orb_s[mu_s + mu +
                              1] = self.mu2orb_s[mu_s + mu] + 2 * j + 1
        self.state = 'should be useful for something'
        return self
示例#7
0
文件: nao.py 项目: chrinide/pyscf
  def init_label(self, **kw):
    from pyscf.nao.m_siesta_xml import siesta_xml
    from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c
    from pyscf.nao.m_siesta_ion_xml import siesta_ion_xml
    from pyscf.nao.m_siesta_hsx import siesta_hsx_c
    from timeit import default_timer as timer
    """
      Initialise system var using only the siesta files (siesta.xml in particular is needed)

      System variables:
      -----------------
        label (string): calculation label
        chdir (string): calculation directory
        xml_dict (dict): information extracted from the xml siesta output, see m_siesta_xml
        wfsx: class use to extract the information about wavefunctions, see m_siesta_wfsx
        hsx: class to store a sparse representation of hamiltonian and overlap, see m_siesta_hsx
        norbs_sc (integer): number of orbital
        ucell (array, float): unit cell
        sp2ion (list): species to ions, list of the species associated to the information from the ion files, see m_siesta_ion_xml
        ao_log: Atomic orbital on an logarithmic grid, see m_ao_log
        atom2coord (array, float): array containing the coordinates of each atom.
        natm, natoms (integer): number of atoms
        norbs (integer): number of orbitals
        nspin (integer): number of spin
        nkpoints (integer): number of kpoints
        fermi_energy (float): Fermi energy
        atom2sp (list): atom to specie, list associating the atoms to their specie number
        atom2s: atom -> first atomic orbital in a global orbital counting
        atom2mu_s: atom -> first multiplett (radial orbital) in a global counting of radial orbitals
        sp2symbol (list): list associating the species to their symbol
        sp2charge (list): list associating the species to their charge
        state (string): this is an internal information on the current status of the class
    """

    #label='siesta', cd='.', verbose=0, **kvargs

    self.label = label = kw['label'] if 'label' in kw else 'siesta'
    self.cd = cd = kw['cd'] if 'cd' in kw else '.'
    self.xml_dict = siesta_xml(cd+'/'+self.label+'.xml')
    self.wfsx = siesta_wfsx_c(**kw)
    self.hsx = siesta_hsx_c(fname=cd+'/'+self.label+'.HSX', **kw)
    self.norbs_sc = self.wfsx.norbs if self.hsx.orb_sc2orb_uc is None else len(self.hsx.orb_sc2orb_uc)
    self.ucell = self.xml_dict["ucell"]
    ##### The parameters as fields     
    self.sp2ion = []
    for sp in self.wfsx.sp2strspecie: self.sp2ion.append(siesta_ion_xml(cd+'/'+sp+'.ion.xml'))

    _siesta_ion_add_sp2(self, self.sp2ion)
    self.ao_log = ao_log_c().init_ao_log_ion(self.sp2ion, **kw)

    self.atom2coord = self.xml_dict['atom2coord']
    self.natm=self.natoms=len(self.xml_dict['atom2sp'])
    self.norbs  = self.wfsx.norbs 
    self.nspin  = self.wfsx.nspin
    self.nkpoints  = self.wfsx.nkpoints
    self.fermi_energy = self.xml_dict['fermi_energy']

    strspecie2sp = {}
    # initialise a dictionary with species string as key
    # associated to the specie number
    for sp,strsp in enumerate(self.wfsx.sp2strspecie): strspecie2sp[strsp] = sp
    
    # list of atoms associated to them specie number
    self.atom2sp = np.empty((self.natm), dtype=np.int64)
    for o,atom in enumerate(self.wfsx.orb2atm):
      self.atom2sp[atom-1] = strspecie2sp[self.wfsx.orb2strspecie[o]]

    self.atom2s = np.zeros((self.natm+1), dtype=np.int64)
    for atom,sp in enumerate(self.atom2sp):
        self.atom2s[atom+1]=self.atom2s[atom]+self.ao_log.sp2norbs[sp]

    # atom2mu_s list of atom associated to them multipletts (radial orbitals)
    self.atom2mu_s = np.zeros((self.natm+1), dtype=np.int64)
    for atom,sp in enumerate(self.atom2sp):
        self.atom2mu_s[atom+1]=self.atom2mu_s[atom]+self.ao_log.sp2nmult[sp]
    
    orb2m = self.get_orb2m()
    _siesta2blanko_csr(orb2m, self.hsx.s4_csr, self.hsx.orb_sc2orb_uc)

    for s in range(self.nspin):
      _siesta2blanko_csr(orb2m, self.hsx.spin2h4_csr[s], self.hsx.orb_sc2orb_uc)
    
    #t1 = timer()
    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,:,:])
    #t2 = timer(); print(t2-t1, 'rsh wfsx'); t1 = timer()

    
    self.sp2symbol = [str(ion['symbol'].replace(' ', '')) for ion in self.sp2ion]
    self.sp2charge = self.ao_log.sp2charge
    self.state = 'should be useful for something'

    # Trying to be similar to mole object from pySCF 
    self._xc_code   = 'LDA,PZ' # estimate how ? 
    self._nelectron = self.hsx.nelec
    self.cart = False
    self.spin = self.nspin-1
    self.stdout = sys.stdout
    self.symmetry = False
    self.symmetry_subgroup = None
    self._built = True 
    self.max_memory = 20000
    self.incore_anyway = False
    self.nbas = self.atom2mu_s[-1] # total number of radial orbitals
    self.mu2orb_s = np.zeros((self.nbas+1), dtype=np.int64)
    for sp,mu_s in zip(self.atom2sp,self.atom2mu_s):
      for mu,j in enumerate(self.ao_log.sp_mu2j[sp]): self.mu2orb_s[mu_s+mu+1] = self.mu2orb_s[mu_s+mu] + 2*j+1
        
    self._atom = [(self.sp2symbol[sp], list(self.atom2coord[ia,:])) for ia,sp in enumerate(self.atom2sp)]
    return self
示例#8
0
文件: nao.py 项目: zzy2014/pyscf
    def init_wfsx_fname(self, **kw):
        """  Initialise system var starting with a given WFSX file  """
        from pyscf.nao.m_tools import read_xyz
        from pyscf.nao.m_fermi_energy import fermi_energy
        from pyscf.nao.m_siesta_xml import siesta_xml
        from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c
        from pyscf.nao.m_siesta_ion_xml import siesta_ion_xml
        from pyscf.nao.m_siesta_hsx import siesta_hsx_c
        from timeit import default_timer as timer

        self.label = label = kw['label'] if 'label' in kw else 'siesta'
        self.cd = cd = kw['cd'] if 'cd' in kw else '.'

        fname = kw['wfsx_fname'] if 'wfsx_fname' in kw else None
        self.wfsx = siesta_wfsx_c(fname=fname, **kw)
        self.hsx = siesta_hsx_c(fname=cd + '/' + self.label + '.HSX', **kw)
        self.norbs_sc = self.wfsx.norbs if self.hsx.orb_sc2orb_uc is None else len(
            self.hsx.orb_sc2orb_uc)
        self.natm = self.natoms = max(self.wfsx.orb2atm)
        self.norbs = len(self.wfsx.orb2atm)
        self.norbs_sc = self.norbs
        self.nspin = self.wfsx.nspin
        self.ucell = 30.0 * np.eye(3)
        self.nkpoints = self.wfsx.nkpoints

        self.sp2ion = []
        for sp in self.wfsx.sp2strspecie:
            self.sp2ion.append(siesta_ion_xml(cd + '/' + sp + '.ion.xml'))
        _siesta_ion_add_sp2(self, self.sp2ion)
        #self.ao_log = ao_log_c().init_ao_log_ion(self.sp2ion, **kw)
        self.ao_log = ao_log(sp2ion=self.sp2ion, **kw)
        self.kb_log = ao_log(sp2ion=self.sp2ion, fname='kbs', **kw)

        strspecie2sp = {}
        # initialise a dictionary with species string as a key associated to the specie number
        for sp, strsp in enumerate(self.wfsx.sp2strspecie):
            strspecie2sp[strsp] = sp

        # list of atoms associated to them specie number
        self.atom2sp = np.empty((self.natm), dtype=np.int64)
        for o, atom in enumerate(self.wfsx.orb2atm):
            self.atom2sp[atom - 1] = strspecie2sp[self.wfsx.orb2strspecie[o]]

        self.atom2s = np.zeros((self.natm + 1), dtype=np.int64)
        for atom, sp in enumerate(self.atom2sp):
            self.atom2s[atom +
                        1] = self.atom2s[atom] + self.ao_log.sp2norbs[sp]

        # atom2mu_s list of atom associated to them multipletts (radial orbitals)
        self.atom2mu_s = np.zeros((self.natm + 1), dtype=np.int64)
        for atom, sp in enumerate(self.atom2sp):
            self.atom2mu_s[atom +
                           1] = self.atom2mu_s[atom] + self.ao_log.sp2nmult[sp]

        self.nbas = self.atom2mu_s[-1]  # total number of radial orbitals
        self.mu2orb_s = np.zeros((self.nbas + 1), dtype=np.int64)
        for sp, mu_s in zip(self.atom2sp, self.atom2mu_s):
            for mu, j in enumerate(self.ao_log.sp_mu2j[sp]):
                self.mu2orb_s[mu_s + mu +
                              1] = self.mu2orb_s[mu_s + mu] + 2 * j + 1

        #t1 = timer()
        orb2m = self.get_orb2m()
        _siesta2blanko_csr(orb2m, self.hsx.s4_csr, self.hsx.orb_sc2orb_uc)

        for s in range(self.nspin):
            _siesta2blanko_csr(orb2m, self.hsx.spin2h4_csr[s],
                               self.hsx.orb_sc2orb_uc)

        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, :, :])
        #t2 = timer(); print(t2-t1, 'rsh wfsx'); t1 = timer()

        # Get self.atom2coord via .xml or .xyz files
        try:
            self.xml_dict = siesta_xml(cd + '/' + self.label + '.xml')
            self.atom2coord = self.xml_dict['atom2coord']
            self.fermi_energy = self.xml_dict['fermi_energy']
        except:
            print(__name__,
                  'no siesta.xml file --> excepting with siesta.xyz file')
            a2sym, a2coord = read_xyz(cd + '/' + self.label + '.xyz')
            self.atom2coord = a2coord * 1.8897259886
            # cross-check of loaded .xyz file:
            atom2sym_ref = np.array([
                self.sp2ion[sp]['symbol'].strip()
                for atom, sp in enumerate(self.atom2sp)
            ])
            for ia, (a1, a2) in enumerate(zip(a2sym, atom2sym_ref)):
                if a1 != a2:
                    raise RuntimeError('.xyz wrong? %d %s %s ' % (ia, a1, a2))
            self.fermi_energy = fermi_energy(self.wfsx.ksn2e, self.hsx.nelec,
                                             self.hsx.telec)

        self.sp2symbol = [
            str(ion['symbol'].replace(' ', '')) for ion in self.sp2ion
        ]
        self.sp2charge = self.ao_log.sp2charge

        # Trying to be similar to mole object from pySCF
        self._xc_code = 'LDA,PZ'  # estimate how ?
        self._nelectron = self.hsx.nelec
        self.cart = False
        self.spin = self.nspin - 1
        self.stdout = sys.stdout
        self.symmetry = False
        self.symmetry_subgroup = None
        self._built = True
        self.max_memory = 20000
        self.incore_anyway = False
        self._atom = [(self.sp2symbol[sp], list(self.atom2coord[ia, :]))
                      for ia, sp in enumerate(self.atom2sp)]
        self.state = 'should be useful for something'
        return self
  def init_ase_atoms(self, Atoms, **kvargs):
    """ Initialise system vars using siesta file and Atom object from ASE."""
    from pyscf.nao.m_siesta_xml import siesta_xml
    from pyscf.nao.m_siesta_wfsx import siesta_wfsx_c
    from pyscf.nao.m_siesta_ion_xml import siesta_ion_xml
    from pyscf.nao.m_siesta_hsx import siesta_hsx_c

    self.label = 'ase' if label is None else label
    self.xml_dict = siesta_xml(self.label)
    self.wfsx = siesta_wfsx_c(self.label)
    self.hsx = siesta_hsx_c(self.label, **kvargs)
    self.norbs_sc = self.wfsx.norbs if self.hsx.orb_sc2orb_uc is None else len(self.hsx.orb_sc2orb_uc)

    try:
      import ase
    except:
      warn('no ASE installed: try via siesta.xml')
      self.init_siesta_xml(**kvargs)

    self.Atoms = Atoms
   
    ##### The parameters as fields     
    self.sp2ion = []
    species = []
    for sp in Atoms.get_chemical_symbols():
      if sp not in species:
        species.append(sp)
        self.sp2ion.append(siesta_ion_xml(sp+'.ion.xml'))
    
    _add_mu_sp2(self, self.sp2ion)
    self.sp2ao_log = ao_log_c(self.sp2ion)
  
    self.natm=self.natoms= Atoms.get_positions().shape[0]
    self.norbs  = self.wfsx.norbs
    self.nspin  = self.wfsx.nspin
    self.nkpoints  = self.wfsx.nkpoints

    strspecie2sp = {}
    for sp in range(len(self.wfsx.sp2strspecie)): strspecie2sp[self.wfsx.sp2strspecie[sp]] = sp
    
    self.atom2sp = np.empty((self.natoms), dtype='int64')
    for i, sp in enumerate(Atoms.get_chemical_symbols()):
      self.atom2sp[i] = strspecie2sp[sp]
    
    self.atom2s = np.zeros((sv.natm+1), dtype=np.int64)
    for atom,sp in enumerate(sv.atom2sp): atom2s[atom+1]=atom2s[atom]+self.ao_log.sp2norbs[sp]

    self.atom2mu_s = np.zeros((self.natm+1), dtype=np.int64)
    for atom,sp in enumerate(self.atom2sp): self.atom2mu_s[atom+1]=self.atom2mu_s[atom]+self.ao_log.sp2nmult[sp]

    orb2m = get_orb2m(self)
    _siesta2blanko_csr(orb2m, self.hsx.s4_csr, self.hsx.orb_sc2orb_uc)

    for s in range(self.nspin):
      _siesta2blanko_csr(orb2m, self.hsx.spin2h4_csr[s], self.hsx.orb_sc2orb_uc)
    
    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.sp2symbol = [str(ion['symbol'].replace(' ', '')) for ion in self.sp2ion]
    self.sp2charge = self.ao_log.sp2charge
    self.nbas = self.atom2mu_s[-1] # total number of radial orbitals
    self.mu2orb_s = np.zeros((self.nbas+1), dtype=np.int64)
    for sp,mu_s in zip(self.atom2sp,self.atom2mu_s):
      for mu,j in enumerate(self.ao_log.sp_mu2j[sp]): self.mu2orb_s[mu_s+mu+1] = self.mu2orb_s[mu_s+mu] + 2*j+1
    self.state = 'should be useful for something'
    return self