Beispiel #1
0
    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
Beispiel #2
0
    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)
Beispiel #3
0
    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
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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
Beispiel #7
0
    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)