# sisl.physics.Hamiltonian

class sisl.physics.Hamiltonian(geometry, dim=1, dtype=None, nnzpr=None, **kwargs)

Sparse Hamiltonian matrix object

Assigning or changing Hamiltonian elements is as easy as with standard numpy assignments:

>>> ham = Hamiltonian(...)
>>> ham.H[1, 2] = 0.1


which assigns 0.1 as the coupling constant between orbital 2 and 3. (remember that Python is 0-based elements).

For spin matrices the elements are defined with an extra dimension.

For a polarized matrix:

>>> M = Hamiltonian(..., spin="polarized")
>>> M[0, 0, 0] = # onsite spin up
>>> M[0, 0, 1] = # onsite spin down


For non-colinear the indices are a bit more tricky:

>>> M = Hamiltonian(..., spin="non-colinear")
>>> M[0, 0, M.M11] = # Re(up-up)
>>> M[0, 0, M.M22] = # Re(down-down)
>>> M[0, 0, M.M12r] = # Re(up-down)
>>> M[0, 0, M.M12i] = # Im(up-down)


For spin-orbit it looks like this:

>>> M = Hamiltonian(..., spin="spin-orbit")
>>> M[0, 0, M.M11r] = # Re(up-up)
>>> M[0, 0, M.M11i] = # Im(up-up)
>>> M[0, 0, M.M22r] = # Re(down-down)
>>> M[0, 0, M.M22i] = # Im(down-down)
>>> M[0, 0, M.M12r] = # Re(up-down)
>>> M[0, 0, M.M12i] = # Im(up-down)
>>> M[0, 0, M.M21r] = # Re(down-up)
>>> M[0, 0, M.M21i] = # Im(down-up)


Thus the number of orbitals is unchanged but a sub-block exists for the spin-block.

When transferring the matrix to a k-point the spin-box is local to each orbital, meaning that the spin-box for orbital i will be:

>>> Hk = ham.Hk()
>>> Hk[i*2:(i+1)*2, i*2:(i+1)*2]

Parameters
• geometry (Geometry) – parent geometry to create a Hamiltonian from. The Hamiltonian will have size equivalent to the number of orbitals in the geometry

• dim (int or Spin, optional) – number of components per element, may be a Spin object

• dtype (np.dtype, optional) – data type contained in the matrix. See details of Spin for default values.

• nnzpr (int, optional) – number of initially allocated memory per orbital in the matrix. For increased performance this should be larger than the actual number of entries per orbital.

• spin (Spin, optional) – equivalent to dim argument. This keyword-only argument has precedence over dim.

• orthogonal (bool, optional) – whether the matrix corresponds to a non-orthogonal basis. In this case the dimensionality of the matrix is one more than dim. This is a keyword-only argument.

Methods

 Hk([k, dtype, gauge, format]) Setup the Hamiltonian for a given k-point Rij([what, dtype]) Create a sparse matrix with the vectors between atoms/orbitals Sk([k, dtype, gauge, format]) Setup the overlap matrix for a given k-point add(other[, axis, offset]) Add two sparse matrices by adding the parameters to one set. append(other, axis[, eps, scale]) Append other along axis to construct a new connected sparse matrix construct(func[, na_iR, method, eta]) Automatically construct the sparse model based on a function that does the setting up of the elements copy([dtype]) A copy of this object create_construct(R, param) Create a simple function for passing to the construct function. dHk([k, dtype, gauge, format]) Setup the Hamiltonian derivative for a given k-point dSk([k, dtype, gauge, format]) Setup the $$k$$-derivatie of the overlap matrix for a given k-point ddHk([k, dtype, gauge, format]) Setup the Hamiltonian double derivative for a given k-point ddSk([k, dtype, gauge, format]) Setup the double $$k$$-derivatie of the overlap matrix for a given k-point edges([atoms, exclude, orbitals]) Retrieve edges (connections) for all atoms eig([k, gauge, eigvals_only]) Returns the eigenvalues of the physical quantity (using the non-Hermitian solver) eigenstate([k, gauge]) Calculate the eigenstates at k and return an EigenstateElectron object containing all eigenstates eigenvalue([k, gauge]) Calculate the eigenvalues at k and return an EigenvalueElectron object containing all eigenvalues for a given k eigh([k, gauge, eigvals_only]) Returns the eigenvalues of the physical quantity eigsh([k, n, gauge, eigvals_only]) Calculates a subset of eigenvalues of the physical quantity (default 10) eliminate_zeros(*args, **kwargs) Removes all zero elements from the sparse matrix empty([keep_nnz]) See empty for details fermi_level([bz, q, distribution, q_tol]) Calculate the Fermi-level using a Brillouinzone sampling and a target charge Finalizes the model fromsp(geometry, P[, S]) Create a sparse model from a preset Geometry and a list of sparse matrices iter_nnz([atoms, orbitals]) Iterations of the non-zero elements iter_orbitals([atoms, local]) Iterations of the orbital space in the geometry, two indices from loop nonzero([atoms, only_col]) Indices row and column indices where non-zero elements exists prepend(other, axis[, eps, scale]) See append for details read(sile, *args, **kwargs) Reads Hamiltonian from Sile using read_hamiltonian. remove(atoms) Remove a subset of this sparse matrix by only retaining the atoms corresponding to atoms remove_orbital(atoms, orbitals) Remove a subset of orbitals on atoms according to orbitals repeat(reps, axis) Create a repeated sparse orbital object, equivalent to Geometry.repeat replace(atoms, other[, other_atoms, eps, scale]) Replace atoms in self with other_atoms in other and retain couplings between them reset([dim, dtype, nnzpr]) The sparsity pattern has all elements removed and everything is reset. rij([what, dtype]) Create a sparse matrix with the distance between atoms/orbitals set_nsc(*args, **kwargs) Reset the number of allowed supercells in the sparse orbital Shift the electronic structure by a constant energy spalign(other) See align for details spsame(other) Compare two sparse objects and check whether they have the same entries. sub(atoms) Create a subset of this sparse matrix by only retaining the atoms corresponding to atoms sub_orbital(atoms, orbitals) Retain only a subset of the orbitals on atoms according to orbitals swap(a, b) Swaps atoms in the sparse geometry to obtain a new order of atoms tile(reps, axis) Create a tiled sparse orbital object, equivalent to Geometry.tile toSparseAtom([dim, dtype]) Convert the sparse object (without data) to a new sparse object with equivalent but reduced sparse pattern tocsr([dim, isc]) Return a csr_matrix for the specified dimension transform([matrix, dtype, spin, orthogonal]) Transform the matrix by either a matrix or new spin configuration transpose([hermitian, spin, sort]) A transpose copy of this object, possibly apply the Hermitian conjugate as well Create a new matrix with applied time-reversal-symmetry unrepeat(reps, axis[, segment, sym]) Unrepeats the sparse model into different parts (retaining couplings) untile(reps, axis[, segment, sym]) Untiles the sparse model into different parts (retaining couplings) write(sile, *args, **kwargs) Writes a Hamiltonian to the Sile as implemented in the Sile.write_hamiltonian method H Access the Hamiltonian elements S Access the overlap elements associated with the sparse matrix dim Number of components per element dkind Data type of sparse elements (in str) dtype Data type of sparse elements finalized Whether the contained data is finalized and non-used elements have been removed geometry Associated geometry nnz Number of non-zero elements non_orthogonal True if the object is using a non-orthogonal basis orthogonal True if the object is using an orthogonal basis shape Shape of sparse matrix spin Associated spin class
property H

Access the Hamiltonian elements

Hk(k=(0, 0, 0), dtype=None, gauge='R', format='csr', *args, **kwargs)[source]

Setup the Hamiltonian for a given k-point

Creation and return of the Hamiltonian for a given k-point (default to Gamma).

Notes

Currently the implemented gauge for the k-point is the cell vector gauge:

$\mathbf H(k) = \mathbf H_{\nu\mu} e^{i k R}$

where $$R$$ is an integer times the cell vector and $$\nu$$, $$\mu$$ are orbital indices.

Another possible gauge is the orbital distance which can be written as

$\mathbf H(k) = \mathbf H_{\nu\mu} e^{i k r}$

where $$r$$ is the distance between the orbitals.

Parameters
• k (array_like) – the k-point to setup the Hamiltonian at

• dtype (numpy.dtype , optional) – the data type of the returned matrix. Do NOT request non-complex data-type for non-Gamma k. The default data-type is numpy.complex128

• gauge ({'R', 'r'}) – the chosen gauge, R for cell vector gauge, and r for orbital distance gauge.

• format ({'csr', 'array', 'dense', 'coo', ...}) – the returned format of the matrix, defaulting to the scipy.sparse.csr_matrix, however if one always requires operations on dense matrices, one can always return in numpy.ndarray (‘array’/’dense’/’matrix’). Prefixing with ‘sc:’, or simply ‘sc’ returns the matrix in supercell format with phases. This is useful for e.g. bond-current calculations where individual hopping + phases are required.

• spin (int, optional) – if the Hamiltonian is a spin polarized one can extract the specific spin direction matrix by passing an integer (0 or 1). If the Hamiltonian is not Spin.POLARIZED this keyword is ignored.

dHk

Hamiltonian derivative with respect to k

ddHk

Hamiltonian double derivative with respect to k

Returns

matrix – the Hamiltonian matrix at $$k$$. The returned object depends on format.

Return type

numpy.ndarray or scipy.sparse.*_matrix

Rij(what='orbital', dtype=<class 'numpy.float64'>)

Create a sparse matrix with the vectors between atoms/orbitals

Parameters
• what ({'orbital', 'atom'}) – which kind of sparse vector matrix to return, either an atomic vector matrix or an orbital vector matrix. The orbital matrix is equivalent to the atomic one with the same vectors repeated for the same atomic orbitals. The default is the same type as the parent class.

• dtype (numpy.dtype, optional) – the data-type of the sparse matrix.

Notes

The returned sparse matrix with vectors are taken from the current sparse pattern. I.e. a subsequent addition of sparse elements will make them inequivalent. It is thus important to only create the sparse vector matrix when the sparse structure is completed.

property S

Access the overlap elements associated with the sparse matrix

Sk(k=(0, 0, 0), dtype=None, gauge='R', format='csr', *args, **kwargs)

Setup the overlap matrix for a given k-point

Creation and return of the overlap matrix for a given k-point (default to Gamma).

Notes

Currently the implemented gauge for the k-point is the cell vector gauge:

$\mathbf S(k) = \mathbf S_{\nu\mu} e^{i k R}$

where $$R$$ is an integer times the cell vector and $$\nu$$, $$\mu$$ are orbital indices.

Another possible gauge is the orbital distance which can be written as

$\mathbf S(k) = \mathbf S_{\nu\mu} e^{i k r}$

where $$r$$ is the distance between the orbitals.

Parameters
• k (array_like, optional) – the k-point to setup the overlap at (default Gamma point)

• dtype (numpy.dtype, optional) – the data type of the returned matrix. Do NOT request non-complex data-type for non-Gamma k. The default data-type is numpy.complex128

• gauge ({"R", "r"}) – the chosen gauge, R for cell vector gauge, and r for orbital distance gauge.

• format ({"csr", "array", "matrix", "coo", ...}) – the returned format of the matrix, defaulting to the scipy.sparse.csr_matrix, however if one always requires operations on dense matrices, one can always return in numpy.ndarray (“array”/”dense”/”matrix”). Prefixing with “sc:”, or simply “sc” returns the matrix in supercell format with phases. This is useful for e.g. bond-current calculations where individual hopping + phases are required.

dSk

Overlap matrix derivative with respect to k

ddSk

Overlap matrix double derivative with respect to k

Returns

matrix – the overlap matrix at $$k$$. The returned object depends on format.

Return type

numpy.ndarray or scipy.sparse.*_matrix

__init__(geometry, dim=1, dtype=None, nnzpr=None, **kwargs)[source]

Initialize Hamiltonian

Add two sparse matrices by adding the parameters to one set. The final matrix will have no couplings between self and other

The final sparse matrix will not have any couplings between self and other. Not even if they have commensurate overlapping regions. If you want to create couplings you have to use append but that requires the structures are commensurate in the coupling region.

Parameters
• other (SparseGeometry) – the other sparse matrix to be added, all atoms will be appended

• axis (int or None, optional) – whether a specific axis of the cell will be added to the final geometry. For None the final cell will be that of self, otherwise the lattice vector corresponding to axis will be appended.

• offset ((3,), optional) – offset in geometry of other when adding the atoms.

append

append two matrices by also adding overlap couplings

prepend
append(other, axis, eps=0.005, scale=1)

Append other along axis to construct a new connected sparse matrix

This method tries to append two sparse geometry objects together by the following these steps:

1. Create the new extended geometry

2. Use neighbor cell couplings from self as the couplings to other This may cause problems if the coupling atoms are not exactly equi-positioned. If the coupling coordinates and the coordinates in other differ by more than 0.01 Ang, a warning will be issued. If this difference is above eps the couplings will be removed.

When appending sparse matrices made up of atoms, this method assumes that the orbitals on the overlapping atoms have the same orbitals, as well as the same orbital ordering.

Examples

>>> sporb = SparseOrbital(....)
>>> sporb2 = sporb.append(sporb, 0)
>>> sporbt = sporb.tile(2, 0)
>>> sporb2.spsame(sporbt)
True


To retain couplings only from the left sparse matrix, do:

>>> sporb = left.append(right, 0, scale=(2, 0))
>>> sporb = (sporb + sporb.transpose()) / 2


To retain couplings only from the right sparse matrix, do:

>>> sporb = left.append(right, 0, scale=(0, 2.))
>>> sporb = (sporb + sporb.transpose()) / 2


Notes

The current implementation does not preserve the hermiticity of the matrix. If you want to preserve hermiticity of the matrix you have to do the following:

>>> sm = (sm + sm.transpose()) / 2

Parameters
• other (object) – must be an object of the same type as self

• axis (int) – axis to append the two sparse geometries along

• eps (float, optional) – tolerance that all coordinates must be within to allow an append. It is important that this value is smaller than half the distance between the two closests atoms such that there is no ambiguity in selecting equivalent atoms. An internal stricter eps is used as a baseline, see above.

• scale (float or array_like, optional) – the scale used for the overlapping region. For scalar values it corresponds to passing: (scale, scale). For array-like input scale refers to the scale of the matrix elements coupling from self, while scale is the scale of the matrix elements in other.

prepend

equivalent scheme as this method

add

merge two matrices without considering overlap or commensurability

transpose

ensure hermiticity by using this routine

replace

replace a sub-set of atoms with another sparse matrix

Geometry.append, Geometry.prepend

SparseCSR.scale_columns

method used to scale the two matrix elements values

Raises

ValueError – if the two geometries are not compatible for either coordinate, orbital or supercell errors

Returns

a new instance with two sparse matrices joined and appended together

Return type

object

construct(func, na_iR=1000, method='rand', eta=None)

Automatically construct the sparse model based on a function that does the setting up of the elements

This may be called in two variants.

1. Pass a function (func), see e.g. create_construct which does the setting up.

2. Pass a tuple/list in func which consists of two elements, one is R the radii parameters for the corresponding parameters. The second is the parameters corresponding to the R[i] elements. In this second case all atoms must only have one orbital.

Parameters
• func (callable or array_like) –

this function must take 4 arguments. 1. Is this object (self) 2. Is the currently examined atom (ia) 3. Is the currently bounded indices (idxs) 4. Is the currently bounded indices atomic coordinates (idxs_xyz) An example func could be:

>>> def func(self, ia, atoms, atoms_xyz=None):
...     idx = self.geometry.close(ia, R=[0.1, 1.44], atoms=atoms, atoms_xyz=atoms_xyz)
...     self[ia, idx] = 0
...     self[ia, idx] = -2.7


• na_iR (int, optional) – number of atoms within the sphere for speeding up the iter_block loop.

• method ({'rand', str}) – method used in Geometry.iter_block, see there for details

• eta (bool, optional) – whether an ETA will be printed

create_construct

a generic function used to create a generic function which this routine requires

tile

tiling after construct is much faster for very large systems

repeat

repeating after construct is much faster for very large systems

copy(dtype=None)

A copy of this object

Parameters

dtype (numpy.dtype, optional) – it is possible to convert the data to a different data-type If not specified, it will use self.dtype

create_construct(R, param)

Create a simple function for passing to the construct function.

This is to relieve the creation of simplistic functions needed for setting up sparse elements.

For simple matrices this returns a function:

>>> def func(self, ia, atoms, atoms_xyz=None):
...     idx = self.geometry.close(ia, R=R, atoms=atoms, atoms_xyz=atoms_xyz)
...     for ix, p in zip(idx, param):
...         self[ia, ix] = p


In the non-colinear case the matrix element $$M_{ij}$$ will be set to input values param if $$i \le j$$ and the Hermitian conjugated values for $$j < i$$.

Notes

This function only works for geometry sparse matrices (i.e. one element per atom). If you have more than one element per atom you have to implement the function your-self.

This method issues warnings if the on-site terms are not Hermitian for spin-orbit systems. Do note that it still creates the matrices based on the input.

Parameters
• R (array_like) – radii parameters for different shells. Must have same length as param or one less. If one less it will be extended with R/100

• param (array_like) – coupling constants corresponding to the R ranges. param[0,:] are the elements for the all atoms within R of each atom.

construct

routine to create the sparse matrix from a generic function (as returned from create_construct)

dHk(k=(0, 0, 0), dtype=None, gauge='R', format='csr', *args, **kwargs)[source]

Setup the Hamiltonian derivative for a given k-point

Creation and return of the Hamiltonian derivative for a given k-point (default to Gamma).

Notes

Currently the implemented gauge for the k-point is the cell vector gauge:

$\nabla_k \mathbf H_\alpha(k) = i R_\alpha \mathbf H_{\nu\mu} e^{i k R}$

where $$R$$ is an integer times the cell vector and $$\nu$$, $$\mu$$ are orbital indices. And $$\alpha$$ is one of the Cartesian directions.

Another possible gauge is the orbital distance which can be written as

$\nabla_k \mathbf H_\alpha(k) = i r_\alpha \mathbf H_{\nu\mu} e^{i k r}$

where $$r$$ is the distance between the orbitals.

Parameters
• k (array_like) – the k-point to setup the Hamiltonian at

• dtype (numpy.dtype , optional) – the data type of the returned matrix. Do NOT request non-complex data-type for non-Gamma k. The default data-type is numpy.complex128

• gauge ({'R', 'r'}) – the chosen gauge, R for cell vector gauge, and r for orbital distance gauge.

• format ({'csr', 'array', 'dense', 'coo', ...}) – the returned format of the matrix, defaulting to the scipy.sparse.csr_matrix, however if one always requires operations on dense matrices, one can always return in numpy.ndarray (‘array’/’dense’/’matrix’).

• spin (int, optional) – if the Hamiltonian is a spin polarized one can extract the specific spin direction matrix by passing an integer (0 or 1). If the Hamiltonian is not Spin.POLARIZED this keyword is ignored.

Hk

Hamiltonian with respect to k

ddHk

Hamiltonian double derivative with respect to k

Returns

for each of the Cartesian directions a $$\partial \mathbf H(k)/\partial k_\alpha$$ is returned.

Return type

tuple

dSk(k=(0, 0, 0), dtype=None, gauge='R', format='csr', *args, **kwargs)

Setup the $$k$$-derivatie of the overlap matrix for a given k-point

Creation and return of the derivative of the overlap matrix for a given k-point (default to Gamma).

Notes

Currently the implemented gauge for the k-point is the cell vector gauge:

$\nabla_k \mathbf S_\alpha(k) = i R_\alpha \mathbf S_{\nu\mu} e^{i k R}$

where $$R$$ is an integer times the cell vector and $$\nu$$, $$\mu$$ are orbital indices. And $$\alpha$$ is one of the Cartesian directions.

Another possible gauge is the orbital distance which can be written as

$\nabla_k \mathbf S_\alpha(k) = i r_\alpha \mathbf S_{ij} e^{i k r}$

where $$r$$ is the distance between the orbitals.

Parameters
• k (array_like, optional) – the k-point to setup the overlap at (default Gamma point)

• dtype (numpy.dtype, optional) – the data type of the returned matrix. Do NOT request non-complex data-type for non-Gamma k. The default data-type is numpy.complex128

• gauge ({"R", "r"}) – the chosen gauge, R for cell vector gauge, and r for orbital distance gauge.

• format ({"csr", "array", "matrix", "coo", ...}) – the returned format of the matrix, defaulting to the scipy.sparse.csr_matrix, however if one always requires operations on dense matrices, one can always return in numpy.ndarray (“array”/”dense”/”matrix”).

Sk

Overlap matrix at k

ddSk

Overlap matrix double derivative at k

Returns

for each of the Cartesian directions a $$\partial \mathbf S(k)/\partial k$$ is returned.

Return type

tuple

ddHk(k=(0, 0, 0), dtype=None, gauge='R', format='csr', *args, **kwargs)[source]

Setup the Hamiltonian double derivative for a given k-point

Creation and return of the Hamiltonian double derivative for a given k-point (default to Gamma).

Notes

Currently the implemented gauge for the k-point is the cell vector gauge:

$\nabla_k^2 \mathbf H_{\alpha\beta}(k) = - R_\alpha R_\beta \mathbf H_{\nu\mu} e^{i k R}$

where $$R$$ is an integer times the cell vector and $$\nu$$, $$\mu$$ are orbital indices. And $$\alpha$$ and $$\beta$$ are one of the Cartesian directions.

Another possible gauge is the orbital distance which can be written as

$\nabla_k^2 \mathbf H_{\alpha\beta}(k) = - r_\alpha r_\beta \mathbf H_{\nu\mu} e^{i k r}$

where $$r$$ is the distance between the orbitals.

Parameters
• k (array_like) – the k-point to setup the Hamiltonian at

• dtype (numpy.dtype , optional) – the data type of the returned matrix. Do NOT request non-complex data-type for non-Gamma k. The default data-type is numpy.complex128

• gauge ({'R', 'r'}) – the chosen gauge, R for cell vector gauge, and r for orbital distance gauge.

• format ({'csr', 'array', 'dense', 'coo', ...}) – the returned format of the matrix, defaulting to the scipy.sparse.csr_matrix, however if one always requires operations on dense matrices, one can always return in numpy.ndarray (‘array’/’dense’/’matrix’).

• spin (int, optional) – if the Hamiltonian is a spin polarized one can extract the specific spin direction matrix by passing an integer (0 or 1). If the Hamiltonian is not Spin.POLARIZED this keyword is ignored.

Hk

Hamiltonian with respect to k

dHk

Hamiltonian derivative with respect to k

Returns

for each of the Cartesian directions (in Voigt representation); xx, yy, zz, zy, xz, xy

Return type

list of matrices

ddSk(k=(0, 0, 0), dtype=None, gauge='R', format='csr', *args, **kwargs)

Setup the double $$k$$-derivatie of the overlap matrix for a given k-point

Creation and return of the double derivative of the overlap matrix for a given k-point (default to Gamma).

Notes

Currently the implemented gauge for the k-point is the cell vector gauge:

$\nabla_k^2 \mathbf S_{\alpha\beta}(k) = - R_\alpha R_\beta \mathbf S_{\nu\mu} e^{i k R}$

where $$R$$ is an integer times the cell vector and $$\nu$$, $$\mu$$ are orbital indices. And $$\alpha$$ and $$\beta$$ are one of the Cartesian directions.

Another possible gauge is the orbital distance which can be written as

$\nabla_k^2 \mathbf S_{\alpha\beta}(k) = - r_\alpha r_\beta \mathbf S_{ij} e^{i k r}$

where $$r$$ is the distance between the orbitals.

Parameters
• k (array_like, optional) – the k-point to setup the overlap at (default Gamma point)

• dtype (numpy.dtype, optional) – the data type of the returned matrix. Do NOT request non-complex data-type for non-Gamma k. The default data-type is numpy.complex128

• gauge ({"R", "r"}) – the chosen gauge, R for cell vector gauge, and r for orbital distance gauge.

• format ({"csr", "array", "matrix", "coo", ...}) – the returned format of the matrix, defaulting to the scipy.sparse.csr_matrix, however if one always requires operations on dense matrices, one can always return in numpy.ndarray (“array”/”dense”/”matrix”).

Sk

Overlap matrix at k

dSk

Overlap matrix derivative at k

Returns

for each of the Cartesian directions (in Voigt representation); xx, yy, zz, zy, xz, xy

Return type

list of matrices

property dim

Number of components per element

property dkind

Data type of sparse elements (in str)

property dtype

Data type of sparse elements

edges(atoms=None, exclude=None, orbitals=None)

Retrieve edges (connections) for all atoms

The returned edges are unique and sorted (see numpy.unique) and are returned in supercell indices (i.e. 0 <= edge < self.geometry.no_s).

Parameters
• atoms (int or list of int) – the edges are returned only for the given atom (but by using all orbitals of the requested atom). The returned edges are also atoms.

• exclude (int or list of int or None, optional) – remove edges which are in the exclude list, this list refers to orbitals.

• orbitals (int or list of int) – the edges are returned only for the given orbital. The returned edges are orbitals.

SparseCSR.edges

the underlying routine used for extracting the edges

eig(k=(0, 0, 0), gauge='R', eigvals_only=True, **kwargs)

Returns the eigenvalues of the physical quantity (using the non-Hermitian solver)

Setup the system and overlap matrix with respect to the given k-point and calculate the eigenvalues.

All subsequent arguments gets passed directly to scipy.linalg.eig

Parameters

spin (int, optional) – the spin-component to calculate the eigenvalue spectrum of, note that this parameter is only valid for Spin.POLARIZED matrices.

eigenstate(k=(0, 0, 0), gauge='R', **kwargs)[source]

Calculate the eigenstates at k and return an EigenstateElectron object containing all eigenstates

Parameters
• k (array_like*3, optional) – the k-point at which to evaluate the eigenstates at

• gauge (str, optional) – the gauge used for calculating the eigenstates

• sparse (bool, optional) – if True, eigsh will be called, else eigh will be called (default).

• format (str, optional) – see eigh for details, this will be passed to the EigenstateElectron instance to be used in subsequent calls, may speed up post-processing.

• **kwargs (dict, optional) – passed arguments to the eigh/eighs routine

eigh

eigenvalue routine

eigsh

eigenvalue routine

Return type

EigenstateElectron

eigenvalue(k=(0, 0, 0), gauge='R', **kwargs)[source]

Calculate the eigenvalues at k and return an EigenvalueElectron object containing all eigenvalues for a given k

Parameters
• k (array_like*3, optional) – the k-point at which to evaluate the eigenvalues at

• gauge (str, optional) – the gauge used for calculating the eigenvalues

• sparse (bool, optional) – if True, eigsh will be called, else eigh will be called (default).

• format (str, optional) – see eigh for details, this will be passed to the EigenstateElectron instance to be used in subsequent calls, may speed up post-processing.

• **kwargs (dict, optional) – passed arguments to the eigh routine

eigh

eigenvalue routine

eigsh

eigenvalue routine

Return type

EigenvalueElectron

eigh(k=(0, 0, 0), gauge='R', eigvals_only=True, **kwargs)

Returns the eigenvalues of the physical quantity

Setup the system and overlap matrix with respect to the given k-point and calculate the eigenvalues.

All subsequent arguments gets passed directly to scipy.linalg.eigh

Parameters

spin (int, optional) – the spin-component to calculate the eigenvalue spectrum of, note that this parameter is only valid for Spin.POLARIZED matrices.

eigsh(k=(0, 0, 0), n=10, gauge='R', eigvals_only=True, **kwargs)

Calculates a subset of eigenvalues of the physical quantity (default 10)

Setup the quantity and overlap matrix with respect to the given k-point and calculate a subset of the eigenvalues using the sparse algorithms.

All subsequent arguments gets passed directly to scipy.linalg.eigsh

Parameters

spin (int, optional) – the spin-component to calculate the eigenvalue spectrum of, note that this parameter is only valid for Spin.POLARIZED matrices.

eliminate_zeros(*args, **kwargs)

Removes all zero elements from the sparse matrix

This is an in-place operation.

SparseCSR.eliminate_zeros

method called, see there for parameters

empty(keep_nnz=False)

See empty for details

fermi_level(bz=None, q=None, distribution='fermi_dirac', q_tol=1e-10)[source]

Calculate the Fermi-level using a Brillouinzone sampling and a target charge

The Fermi-level will be calculated using an iterative approach by first calculating all eigenvalues and subsequently fitting the Fermi level to the final charge (q).

Parameters
• bz (Brillouinzone, optional) – sampled k-points and weights, the bz.parent will be equal to this object upon return default to Gamma-point

• q (float, list of float, optional) – seeked charge, if not set will be equal to self.geometry.q0. If a list of two is passed there will be calculated a Fermi-level per spin-channel. If the Hamiltonian is not spin-polarized the sum of the list will be used and only a single fermi-level will be returned.

• distribution (str, func, optional) – used distribution, must accept the keyword mu as parameter for the Fermi-level

• q_tol (float, optional) – tolerance of charge for finding the Fermi-level

Returns

the Fermi-level of the system (or two if two different charges are passed)

Return type

float or array_like

finalize()

Finalizes the model

Finalizes the model so that all non-used elements are removed. I.e. this simply reduces the memory requirement for the sparse matrix.

Note that adding more elements to the sparse matrix is more time-consuming than for a non-finalized sparse matrix due to the internal data-representation.

property finalized

Whether the contained data is finalized and non-used elements have been removed

classmethod fromsp(geometry, P, S=None, **kwargs)

Create a sparse model from a preset Geometry and a list of sparse matrices

The passed sparse matrices are in one of scipy.sparse formats.

Parameters
• geometry (Geometry) – geometry to describe the new sparse geometry

• P (list of scipy.sparse or scipy.sparse) – the new sparse matrices that are to be populated in the sparse matrix

• S (scipy.sparse, optional) – if provided this refers to the overlap matrix and will force the returned sparse matrix to be non-orthogonal

• **kwargs (optional) – any arguments that are directly passed to the __init__ method of the class.

Returns

a new sparse matrix that holds the passed geometry and the elements of P and optionally being non-orthogonal if S is not none

Return type

SparseGeometry

property geometry

Associated geometry

iter_nnz(atoms=None, orbitals=None)

Iterations of the non-zero elements

An iterator on the sparse matrix with, row and column

Examples

>>> for i, j in self.iter_nnz():
...    self[i, j] # is then the non-zero value

Parameters
• atoms (int or array_like) – only loop on the non-zero elements coinciding with the orbitals on these atoms (not compatible with the orbitals keyword)

• orbitals (int or array_like) – only loop on the non-zero elements coinciding with the orbital (not compatible with the atoms keyword)

iter_orbitals(atoms=None, local=False)

Iterations of the orbital space in the geometry, two indices from loop

An iterator returning the current atomic index and the corresponding orbital index.

>>> for ia, io in self.iter_orbitals():


In the above case io always belongs to atom ia and ia may be repeated according to the number of orbitals associated with the atom ia.

Parameters
• atoms (int or array_like, optional) – only loop on the given atoms, default to all atoms

• local (bool, optional) – whether the orbital index is the global index, or the local index relative to the atom it resides on.

Yields
• ia – atomic index

• io – orbital index

Geometry.iter_orbitals

method used to iterate orbitals

property nnz

Number of non-zero elements

property non_orthogonal

True if the object is using a non-orthogonal basis

nonzero(atoms=None, only_col=False)

Indices row and column indices where non-zero elements exists

Parameters
• atoms (int or array_like of int, optional) – only return the tuples for the requested atoms, default is all atoms But for all orbitals.

• only_col (bool, optional) – only return then non-zero columns

SparseCSR.nonzero

the equivalent function call

property orthogonal

True if the object is using an orthogonal basis

plot

Handles all plotting possibilities for a class

prepend(other, axis, eps=0.005, scale=1)

See append for details

This is currently equivalent to:

>>> other.append(self, axis, eps, scale)


Parameters
• sile (Sile, str or pathlib.Path) – a Sile object which will be used to read the Hamiltonian and the overlap matrix (if any) if it is a string it will create a new sile using get_sile.

• * (args passed directly to read_hamiltonian(,**)) –

remove(atoms)

Remove a subset of this sparse matrix by only retaining the atoms corresponding to atoms

Parameters

atoms (array_like of int or Atom) – indices of removed atoms or Atom for direct removal of all atoms

Geometry.remove

equivalent to the resulting Geometry from this routine

Geometry.sub

the negative of Geometry.remove

sub

the opposite of remove, i.e. retain a subset of atoms

remove_orbital(atoms, orbitals)

Remove a subset of orbitals on atoms according to orbitals

For more detailed examples, please see the equivalent (but opposite) method sub_orbital.

Parameters
• atoms (array_like of int or Atom) – indices of atoms or Atom that will be reduced in size according to orbitals

• orbitals (array_like of int or Orbital) – indices of the orbitals on atoms that are removed from the sparse matrix.

sub_orbital

retaining a set of orbitals (see here for examples)

repeat(reps, axis)

Create a repeated sparse orbital object, equivalent to Geometry.repeat

The already existing sparse elements are extrapolated to the new supercell by repeating them in blocks like the coordinates.

Parameters
• reps (int) – number of repetitions along cell-vector axis

• axis (int) – 0, 1, 2 according to the cell-direction

Geometry.repeat

the same ordering as the final geometry

Geometry.tile

a different ordering of the final geometry

tile

a different ordering of the final geometry

replace(atoms, other, other_atoms=None, eps=0.005, scale=1.0)

Replace atoms in self with other_atoms in other and retain couplings between them

This method replaces a subset of atoms in self with another sparse geometry retaining any couplings between them. The algorithm checks whether the coupling atoms have the same number of orbitals. Meaning that atoms in the overlapping region should have the same connections and number of orbitals per atom. It will _not_ check whether the orbitals or atoms _are_ the same, nor the order of the orbitals.

The replacement algorithm takes the couplings from self -> other on atoms belonging to self and other -> self from other. This will in some cases mean that the matrix becomes non-symmetric. See in Notes for details on symmetrizing the matrices.

Examples

>>> minimal = SparseOrbital(....)
>>> big = minimal.tile(2, 0)
>>> big2 = big.replace(np.arange(big.na), minimal)
>>> big.spsame(big2)
True


To ensure hermiticity and using the average of the couplings from big and minimal one can do:

>>> big2 = big.replace(np.arange(big.na), minimal)
>>> big2 = (big2 + big2.transpose()) / 2


To retain couplings only from the big sparse matrix, one should do the following (note the subsequent transposing which ensures hermiticy and is effectively copying couplings from big to the replaced region.

>>> big2 = big.replace(np.arange(big.na), minimal, scale=(2, 0))
>>> big2 = (big2 + big2.transpose()) / 2


To only retain couplings from the minimal sparse matrix:

>>> big2 = big.replace(np.arange(big.na), minimal, scale=(0, 2))
>>> big2 = (big2 + big2.transpose()) / 2


Notes

The current implementation does not preserve the hermiticity of the matrix. If you want to preserve hermiticity of the matrix you have to do the following:

>>> sm = (sm + sm.transpose()) / 2


Also note that the ordering of the atoms will be range(atoms.min()), range(len(other_atoms)), <rest>.

Algorithms that utilizes atomic indices should be careful.

When the tolerance eps is high, the elements may be more prone to differences in the symmetry elements. A good idea would be to check the difference between the couplings. The below variable diff will contain the difference (self -> other) - (other -> self)

>>> diff = sm - sm.transpose()

Parameters
• atoms (array_like) – which atoms in self that are removed and replaced with other.sub(other_atoms)

• other (object) – must be an object of the same type as self, a subset is taken from this sparse matrix and combined with self to create a new sparse matrix

• other_atoms (array_like, optional) – to select a subset of atoms in other that are taken out. Defaults to all atoms in other.

• eps (float, optional) – coordinate tolerance for allowing replacement. It is important that this value is at least smaller than half the distance between the two closests atoms such that there is no ambiguity in selecting equivalent atoms.

• scale (float or array_like, optional) – the scale used for the overlapping region. For scalar values it corresponds to passing: (scale, scale). For array-like input scale refers to the scale of the matrix elements coupling from self, while scale is the scale of the matrix elements in other.

prepend

prepend two sparse matrices, see append for details

add

merge two matrices without considering overlap or commensurability

transpose

may be used to ensure hermiticity (symmetrization of the matrix elements)

append

append two sparse matrices

Geometry.append, Geometry.prepend

SparseCSR.scale_columns

method used to scale the two matrix elements values

Raises
• ValueError – if the two geometries are not compatible for either coordinate, orbital or supercell errors

• AssertionError – if the two geometries are not compatible for either coordinate, orbital or supercell errors

Warns

SislWarning – in case the overlapping atoms are not comprising the same atomic specie. In some cases this may not be a problem. However, care must be taken by the user if this warning is issued.

Returns

a new instance with two sparse matrices merged together by replacing some atoms

Return type

object

reset(dim=None, dtype=<class 'numpy.float64'>, nnzpr=None)

The sparsity pattern has all elements removed and everything is reset.

The object will be the same as if it had been initialized with the same geometry as it were created with.

Parameters
• dim (int, optional) – number of dimensions per element, default to the current number of elements per matrix element.

• dtype (numpy.dtype, optional) – the datatype of the sparse elements

• nnzpr (int, optional) – number of non-zero elements per row

rij(what='orbital', dtype=<class 'numpy.float64'>)

Create a sparse matrix with the distance between atoms/orbitals

Parameters
• what ({'orbital', 'atom'}) – which kind of sparse distance matrix to return, either an atomic distance matrix or an orbital distance matrix. The orbital matrix is equivalent to the atomic one with the same distance repeated for the same atomic orbitals. The default is the same type as the parent class.

• dtype (numpy.dtype, optional) – the data-type of the sparse matrix.

Notes

The returned sparse matrix with distances are taken from the current sparse pattern. I.e. a subsequent addition of sparse elements will make them inequivalent. It is thus important to only create the sparse distance when the sparse structure is completed.

set_nsc(*args, **kwargs)

Reset the number of allowed supercells in the sparse orbital

If one reduces the number of supercells any sparse element that references the supercell will be deleted.

See SuperCell.set_nsc for allowed parameters.

SuperCell.set_nsc

the underlying called method

property shape

Shape of sparse matrix

shift(E)[source]

Shift the electronic structure by a constant energy

This is equal to performing this operation:

$\mathbf H_\sigma = \mathbf H_\sigma + E \mathbf S$

where $$\mathbf H_\sigma$$ correspond to the spin diagonal components of the Hamiltonian.

Parameters

E (float or (2,)) – the energy (in eV) to shift the electronic structure, if two values are passed the two first spin-components get shifted individually.

spalign(other)

See align for details

property spin

Associated spin class

spsame(other)

Compare two sparse objects and check whether they have the same entries.

This does not necessarily mean that the elements are the same

sub(atoms)

Create a subset of this sparse matrix by only retaining the atoms corresponding to atoms

Negative indices are wrapped and thus works, supercell atoms are also wrapped to the unit-cell.

Parameters

atoms (array_like of int or Atom) – indices of retained atoms or Atom for retaining only that atom

Examples

>>> obj = SparseOrbital(...)
>>> obj.sub(1) # only retain the second atom in the SparseGeometry
>>> obj.sub(obj.atoms.atom) # retain all atoms which is equivalent to
>>>                            # the first atomic specie


Geometry.remove

the negative of Geometry.sub

Geometry.sub

equivalent to the resulting Geometry from this routine

remove

the negative of sub, i.e. remove a subset of atoms

sub_orbital(atoms, orbitals)

Retain only a subset of the orbitals on atoms according to orbitals

This allows one to retain only a given subset of the sparse matrix elements.

Parameters
• atoms (array_like of int or Atom) – indices of atoms or Atom that will be reduced in size according to orbitals

• orbitals (array_like of int or Orbital) – indices of the orbitals on atoms that are retained in the sparse matrix, the list of orbitals will be sorted. One cannot re-arrange matrix elements currently.

Notes

Future implementations may allow one to re-arange orbitals using this method.

When using this method the internal species list will be populated by another specie that is named after the orbitals removed. This is to distinguish different atoms.

Examples

>>> # a Carbon atom with 2 orbitals
>>> C = sisl.Atom('C', [1., 2.])
>>> # an oxygen atom with 3 orbitals
>>> O = sisl.Atom('O', [1., 2., 2.4])
>>> geometry = sisl.Geometry([ * 3,  * 3]], 2, [C, O])
>>> obj = SparseOrbital(geometry).tile(3, 0)
>>> # fill in obj data...


Now obj is a sparse geometry with 2 different species and 6 atoms (3 of each). They are ordered [C, O, C, O, C, O]. In the following we will note species that are different from the original by a ' in the list.

Retain 2nd orbital on the 2nd atom: [C, O', C, O, C, O]

>>> new_obj = obj.sub_orbital(1, 1)


Retain 2nd orbital on 1st and 2nd atom: [C', O', C, O, C, O]

>>> new_obj = obj.sub_orbital([0, 1], 1)


Retain 2nd orbital on the 1st atom and 3rd orbital on 4th atom: [C', O, C, O', C, O]

>>> new_obj = obj.sub_orbital(0, 1).sub_orbital(3, 2)


Retain 2nd orbital on all atoms equivalent to the first atom: [C', O, C', O, C', O]

>>> new_obj = obj.sub_orbital(obj.geometry.atoms, 1)


Retain 1st orbital on 1st atom, and 2nd orbital on 3rd and 5th atom: [C', O, C'', O, C'', O]

>>> new_obj = obj.sub_orbital(0, 0).sub_orbital([2, 4], 1)


remove_orbital

removing a set of orbitals (opposite of this)

swap(a, b)

Swaps atoms in the sparse geometry to obtain a new order of atoms

This can be used to reorder elements of a geometry.

Parameters
• a (array_like) – the first list of atomic coordinates

• b (array_like) – the second list of atomic coordinates

tile(reps, axis)

Create a tiled sparse orbital object, equivalent to Geometry.tile

The already existing sparse elements are extrapolated to the new supercell by repeating them in blocks like the coordinates.

Parameters
• reps (int) – number of repetitions along cell-vector axis

• axis (int) – 0, 1, 2 according to the cell-direction

repeat

a different ordering of the final geometry

untile

opposite of this method

Geometry.tile

the same ordering as the final geometry

Geometry.repeat

a different ordering of the final geometry

toSparseAtom(dim=None, dtype=None)

Convert the sparse object (without data) to a new sparse object with equivalent but reduced sparse pattern

This converts the orbital sparse pattern to an atomic sparse pattern.

Parameters
• dim (int, optional) – number of dimensions allocated in the SparseAtom object, default to the same

• dtype (numpy.dtype, optional) – used data-type for the sparse object. Defaults to the same.

tocsr(dim=0, isc=None, **kwargs)

Return a csr_matrix for the specified dimension

Parameters
• dim (int, optional) – the dimension in the sparse matrix (for non-orthogonal cases the last dimension is the overlap matrix)

• isc (int, optional) – the supercell index, or all (if isc=None)

transform(matrix=None, dtype=None, spin=None, orthogonal=None)

Transform the matrix by either a matrix or new spin configuration

1. General transformation: * If matrix is provided, a linear transformation $$R^n \rightarrow R^m$$ is applied to the $$n$$-dimensional elements of the original sparse matrix. The spin and orthogonal flags are optional but need to be consistent with the creation of an m-dimensional matrix.

This method will copy over the overlap matrix in case the matrix argument only acts on the non-overlap matrix elements and both input and output matrices are non-orthogonal.

2. Spin conversion: If spin is provided (without matrix), the spin class is changed according to the following conversions:

Upscaling * unpolarized -> (polarized, non-colinear, spinorbit): Copy unpolarized value to both up and down components * polarized -> (non-colinear, spinorbit): Copy up and down components * non-colinear -> spinorbit: Copy first four spin components * all other new spin components are set to zero

Downscaling * (polarized, non-colinear, spinorbit) -> unpolarized: Set unpolarized value to a mix 0.5*up + 0.5*down * (non-colinear, spinorbit) -> polarized: Keep up and down spin components * spinorbit -> non-colinear: Keep first four spin components * all other spin components are dropped

3. Orthogonality: If the orthogonal flag is provided, the overlap matrix is either dropped or explicitly introduced as the identity matrix.

Notes

The transformation matrix does not act on the rows and columns, only on the final dimension of the matrix.

Parameters
• matrix (array_like, optional) – transformation matrix of shape $$m \times n$$. Default is no transformation.

• dtype (numpy.dtype, optional) – data type contained in the matrix. Defaults to the input type.

• spin (str, sisl.Spin, optional) – spin class of created matrix. Defaults to the input type.

• orthogonal (bool, optional) – flag to control if the new matrix includes overlaps. Defaults to the input type.

transpose(hermitian=False, spin=True, sort=True)

A transpose copy of this object, possibly apply the Hermitian conjugate as well

Parameters
• hermitian (bool, optional) – if true, also emply a spin-box Hermitian operator to ensure TRS, otherwise only return the transpose values.

• spin (bool, optional) – whether the spin-box is also transposed if this is false, and hermitian is true, then only imaginary values will change sign.

• sort (bool, optional) – the returned columns for the transposed structure will be sorted if this is true, default

trs()

Create a new matrix with applied time-reversal-symmetry

Time reversal symmetry is applied using the following equality:

$2\mathbf M^{\mathrm{TRS}} = \mathbf M + \boldsymbol\sigma_y \mathbf M^* \boldsymbol\sigma_y$

where $$*$$ is the conjugation operator.

unrepeat(reps, axis, segment=0, *args, sym=True, **kwargs)

Unrepeats the sparse model into different parts (retaining couplings)

Please see untile for details, the algorithm and arguments are the same however, this is the opposite of repeat.

untile(reps, axis, segment=0, *args, sym=True, **kwargs)

Untiles the sparse model into different parts (retaining couplings)

Recreates a new sparse object with only the cutted atoms in the structure. This will preserve matrix elements in the supercell.

Parameters
• reps (int) – number of repetitions the tiling function created (opposite meaning as in untile)

• axis (int) – which axis to untile along

• segment (int, optional) – which segment to retain. Generally each segment should be equivalent, however requesting individiual segments can help uncover inconsistencies in the sparse matrix

• *args – arguments passed directly to Geometry.untile

• sym (bool, optional) – if True, the algorithm will ensure the returned matrix is symmetrized (i.e. return (M + M.transpose())/2, else return data as is. False should generally only be used for debugging precision of the matrix elements, or if one wishes to check the warnings.

• **kwargs – keyword arguments passed directly to Geometry.untile

Notes

Untiling structures with nsc == 1 along axis are assumed to have periodic boundary conditions.

When untiling structures with nsc == 1 along axis it is important to untile as much as possible. This is because otherwise the algorithm cannot determine the correct couplings. Therefore to create a geometry of 3 times a unit-cell, one should untile to the unit-cell, and subsequently tile 3 times.

Consider for example a system of 4 atoms, each atom connects to its 2 neighbours. Due to the PBC atom 0 will connect to 1 and 3. Untiling this structure in 2 will group couplings of atoms 0 and 1. As it will only see one coupling to the right it will halve the coupling and use the same coupling to the left, which is clearly wrong.

In the following the latter is the correct way to do it.

>>> SPM.untile(2, 0) != SPM.untile(4, 0).tile(2, 0)

Raises

ValueError : – in case the matrix elements are not conseuctive when determining the new supercell structure. This may often happen if untiling a matrix too few times, and then untiling it again.

tile
Geometry.untile
Writes a Hamiltonian to the Sile as implemented in the Sile.write_hamiltonian method