def read_hamiltonian(self, **kwargs): """ Returns the electronic structure from the siesta.TSHS file """ # First read the geometry geom = self.read_geometry() # Now read the sizes used... sizes = _siesta.read_tshs_sizes(self.file) spin = sizes[0] no = sizes[2] nnz = sizes[4] ncol, col, dH, dS = _siesta.read_tshs_hs(self.file, spin, no, nnz) # Create the Hamiltonian container H = Hamiltonian(geom, spin, nnzpr=1, orthogonal=False) # Create the new sparse matrix H._csr.ncol = ncol.astype(np.int32, copy=False) H._csr.ptr = np.insert(np.cumsum(ncol, dtype=np.int32), 0, 0) # Correct fortran indices H._csr.col = col.astype(np.int32, copy=False) - 1 H._csr._nnz = len(col) H._csr._D = np.empty([nnz, spin + 1], np.float64) H._csr._D[:, :spin] = dH[:, :] H._csr._D[:, spin] = dS[:] return H
def read_hamiltonian(self, hermitian=True, dtype=np.float64, **kwargs): """ Reads a Hamiltonian (including the geometry) Reads the Hamiltonian model """ # Read the geometry in this file geom = self.read_geometry() # Rewind to ensure we can read the entire matrix structure self.fh.seek(0) # With the geometry in place we can read in the entire matrix # Create a new sparse matrix from scipy.sparse import lil_matrix H = lil_matrix((geom.no, geom.no_s), dtype=dtype) S = lil_matrix((geom.no, geom.no_s), dtype=dtype) def i2o(geom, i): try: # pure orbital return int(i) except: # ia[o] # atom ia and the orbital o j = i.replace('[', ' ').replace(']', ' ').split() return geom.a2o(int(j[0])) + int(j[1]) # Start reading in the supercell while True: found, l = self.step_to('matrix', reread=False) if not found: break # Get supercell ls = l.split() try: isc = np.array([int(ls[i]) for i in range(2, 5)], np.int32) except: isc = np.array([0, 0, 0], np.int32) off1 = geom.sc_index(isc) * geom.no off2 = geom.sc_index(-isc) * geom.no l = self.readline() while not l.startswith('end'): ls = l.split() jo = i2o(geom, ls[0]) io = i2o(geom, ls[1]) h = float(ls[2]) try: s = float(ls[3]) except: s = 0. H[jo, io + off1] = h S[jo, io + off1] = s if hermitian: S[io, jo + off2] = s H[io, jo + off2] = h l = self.readline() return Hamiltonian.fromsp(geom, H, S)
def read_hamiltonian(self, **kwargs): """ Returns the electronic structure from the siesta.TSHS file """ # Now read the sizes used... Gamma, spin, no, no_s, nnz = _siesta.read_hsx_sizes(self.file) _bin_check(self, 'read_hamiltonian', 'could not read Hamiltonian sizes.') ncol, col, dH, dS, dxij = _siesta.read_hsx_hsx(self.file, Gamma, spin, no, no_s, nnz) _bin_check(self, 'read_hamiltonian', 'could not read Hamiltonian.') # Try and immediately attach a geometry geom = kwargs.get('geometry', kwargs.get('geom', None)) if geom is None: # We have *no* clue about the if np.allclose(dxij, 0.): # We truly, have no clue, # Just generate a boxed system xyz = [[x, 0, 0] for x in range(no)] geom = Geometry(xyz, Atom(1), sc=[no, 1, 1]) else: # Try to figure out the supercell warn( self.__class__.__name__ + '.read_hamiltonian ' '(currently we can not calculate atomic positions from xij array)' ) if geom.no != no: raise SileError( str(self) + '.read_hamiltonian could not use the ' 'passed geometry as the number of atoms or orbitals is ' 'inconsistent with HSX file.') # Create the Hamiltonian container H = Hamiltonian(geom, spin, nnzpr=1, dtype=np.float32, orthogonal=False) # Create the new sparse matrix H._csr.ncol = ncol.astype(np.int32, copy=False) H._csr.ptr = np.insert(np.cumsum(ncol, dtype=np.int32), 0, 0) # Correct fortran indices H._csr.col = col.astype(np.int32, copy=False) - 1 H._csr._nnz = len(col) H._csr._D = _a.emptyf([nnz, spin + 1]) H._csr._D[:, :spin] = dH[:, :] H._csr._D[:, spin] = dS[:] _mat_spin_convert(H) # Convert the supercells to sisl supercells if no_s // no == np.product(geom.nsc): _csr_from_siesta(geom, H._csr) return H
def read_hamiltonian(self, **kwargs): """ Returns the electronic structure from the siesta.TSHS file """ tshs_g = self.read_geometry() geom = _geometry_align(tshs_g, kwargs.get('geometry', tshs_g), self.__class__, 'read_hamiltonian') # read the sizes used... sizes = _siesta.read_tshs_sizes(self.file) _bin_check(self, 'read_hamiltonian', 'could not read sizes.') isc = _siesta.read_tshs_cell(self.file, sizes[3])[2].T _bin_check(self, 'read_hamiltonian', 'could not read cell.') spin = sizes[0] no = sizes[2] nnz = sizes[4] ncol, col, dH, dS = _siesta.read_tshs_hs(self.file, spin, no, nnz) _bin_check(self, 'read_hamiltonian', 'could not read Hamiltonian and overlap matrix.') # Check whether it is an orthogonal basis set orthogonal = np.abs(dS).sum() == geom.no # Create the Hamiltonian container H = Hamiltonian(geom, spin, nnzpr=1, orthogonal=orthogonal) # Create the new sparse matrix H._csr.ncol = ncol.astype(np.int32, copy=False) H._csr.ptr = np.insert(np.cumsum(ncol, dtype=np.int32), 0, 0) # Correct fortran indices H._csr.col = col.astype(np.int32, copy=False) - 1 H._csr._nnz = len(col) if orthogonal: H._csr._D = _a.emptyd([nnz, spin]) H._csr._D[:, :] = dH[:, :] else: H._csr._D = _a.emptyd([nnz, spin + 1]) H._csr._D[:, :spin] = dH[:, :] H._csr._D[:, spin] = dS[:] _mat_spin_convert(H) # Convert to sisl supercell _csr_from_sc_off(H.geometry, isc, H._csr) # Find all indices where dS == 1 (remember col is in fortran indices) idx = col[np.isclose(dS, 1.).nonzero()[0]] if np.any(idx > no): print('Number of orbitals: {}'.format(no)) print(idx) raise SileError( str(self) + '.read_hamiltonian could not assert ' 'the supercell connections in the primary unit-cell.') return H
def read_hamiltonian(self, **kwargs): """ Returns the electronic structure from the siesta.TSHS file """ tshs_g = self.read_geometry() geom = kwargs.get('geometry', tshs_g) if geom.na != tshs_g.na or geom.no != tshs_g.no: raise SileError(self.__class__.__name__ + '.read_hamiltonian could not use the ' 'passed geometry as the number of atoms or orbitals is inconsistent ' 'with TSHS file.') # Ensure that the number of supercells is correct if np.any(geom.nsc != tshs_g.nsc): geom.set_nsc(tshs_g.nsc) # read the sizes used... sizes = _siesta.read_tshs_sizes(self.file) isc = _siesta.read_tshs_cell(self.file, sizes[3])[2].T spin = sizes[0] no = sizes[2] nnz = sizes[4] ncol, col, dH, dS = _siesta.read_tshs_hs(self.file, spin, no, nnz) # Check whether it is an orthogonal basis set orthogonal = np.abs(dS).sum() == geom.no # Create the Hamiltonian container H = Hamiltonian(geom, spin, nnzpr=1, orthogonal=orthogonal) # Create the new sparse matrix H._csr.ncol = ncol.astype(np.int32, copy=False) H._csr.ptr = np.insert(np.cumsum(ncol, dtype=np.int32), 0, 0) # Correct fortran indices H._csr.col = col.astype(np.int32, copy=False) - 1 H._csr._nnz = len(col) if orthogonal: H._csr._D = np.empty([nnz, spin], np.float64) H._csr._D[:, :] = dH[:, :] else: H._csr._D = np.empty([nnz, spin+1], np.float64) H._csr._D[:, :spin] = dH[:, :] H._csr._D[:, spin] = dS[:] # Convert to sisl supercell _csr_from_sc_off(H.geometry, isc, H._csr) # Find all indices where dS == 1 (remember col is in fortran indices) idx = col[np.isclose(dS, 1.).nonzero()[0]] if np.any(idx > no): print('Number of orbitals: {}'.format(no)) print(idx) raise SileError(self.__class__.__name__ + '.read_hamiltonian could not assert ' 'the supercell connections in the primary unit-cell.') return H
def read_hamiltonian(self, **kwargs): """ Returns the electronic structure from the siesta.TSHS file """ # Now read the sizes used... Gamma, spin, no, no_s, nnz = _siesta.read_hsx_sizes(self.file) ncol, col, dH, dS, dxij = _siesta.read_hsx_hsx(self.file, Gamma, spin, no, no_s, nnz) # Try and immediately attach a geometry geom = kwargs.get('geometry', kwargs.get('geom', None)) if geom is None: # We have *no* clue about the if np.allclose(dxij, 0.): # We truly, have no clue, # Just generate a boxed system xyz = [[x, 0, 0] for x in range(no)] geom = Geometry(xyz, Atom(1), sc=[no, 1, 1]) else: # Try to figure out the supercell warn( self.__class__.__name__ + ".read_hamiltonian (currently we can not calculate atomic positions from" " xij array)") if geom.no != no: raise ValueError( "Reading HSX files requires the input geometry to have the " "correct number of orbitals {} / {}.".format(no, geom.no)) # Create the Hamiltonian container H = Hamiltonian(geom, spin, nnzpr=1, dtype=np.float32, orthogonal=False) # Create the new sparse matrix H._csr.ncol = ncol.astype(np.int32, copy=False) H._csr.ptr = np.insert(np.cumsum(ncol, dtype=np.int32), 0, 0) # Correct fortran indices H._csr.col = col.astype(np.int32, copy=False) - 1 H._csr._nnz = len(col) H._csr._D = np.empty([nnz, spin + 1], np.float32) H._csr._D[:, :spin] = dH[:, :] H._csr._D[:, spin] = dS[:] return H
def _read_hamiltonian(self, geom, dtype=np.float64, **kwargs): """ Reads a Hamiltonian Reads the Hamiltonian model """ cutoff = kwargs.get('cutoff', 0.00001) # Rewind to ensure we can read the entire matrix structure self.fh.seek(0) # Time of creation self.readline() # Number of orbitals no = int(self.readline()) if no != geom.no: raise ValueError( self.__class__.__name__ + '.read_hamiltonian has found inconsistent number ' 'of orbitals in _hr.dat vs the geometry. Remember to re-run Wannier90?' ) # Number of Wigner-Seitz degeneracy points nrpts = int(self.readline()) # First read across the Wigner-Seitz degeneracy # This is formatted with 15 per-line. if nrpts % 15 == 0: nlines = nrpts else: nlines = nrpts + 15 - nrpts % 15 ws = [] for _ in range(nlines // 15): ws.extend(list(map(int, self.readline().split()))) # Convert to numpy array and invert (for weights) ws = 1. / np.array(ws, np.float64).flatten() # Figure out the number of supercells # and maintain the Hamiltonian in the ham list nsc = [0, 0, 0] # List for holding the Hamiltonian ham = [] iws = -1 while True: l = self.readline() if l == '': break # Split here... l = l.split() # Get super-cell, row and column iA, iB, iC, r, c = map(int, l[:5]) nsc[0] = max(nsc[0], abs(iA)) nsc[1] = max(nsc[1], abs(iB)) nsc[2] = max(nsc[2], abs(iC)) # Update index for degeneracy, if required if r + c == 2: iws += 1 # Get degeneracy of this element f = ws[iws] # Store in the Hamiltonian array: # isc # row # column # Hr # Hi ham.append(([iA, iB, iC], r - 1, c - 1, float(l[5]) * f, float(l[6]) * f)) # Update number of super-cells geom.set_nsc([i * 2 + 1 for i in nsc]) # With the geometry in place we can read in the entire matrix # Create a new sparse matrix Hr = lil_matrix((geom.no, geom.no_s), dtype=dtype) Hi = lil_matrix((geom.no, geom.no_s), dtype=dtype) # populate the Hamiltonian by examining the cutoff value for isc, r, c, hr, hi in ham: # Calculate the column corresponding to the # correct super-cell c = c + geom.sc_index(isc) * geom.no if abs(hr) > cutoff: Hr[r, c] = hr if abs(hi) > cutoff: Hi[r, c] = hi del ham if np.dtype(dtype).kind == 'c': Hr = Hr.tocsr() Hi = Hi.tocsr() Hr = Hr + 1j * Hi return Hamiltonian.fromsp(geom, Hr)