sk_builder.slater_koster_model

SlaterKosterModel class.

This module provides the SlaterKosterModel class which represents Slater-Koster (SK) tight-binding models. Currently SK parameters for spds* models are supported.

Copyright © 2022-2025 HQS Quantum Simulations GmbH. All Rights Reserved.

class SlaterKosterModel:

Class representing Slater-Koster tight-binding model.

A representation of a two-center Slater-Koster tight-binding model. Currently supported parametrizations: spds*.

TODO: Write more extensive doc string.

SlaterKosterModel( sk_params: dict, structure: dict, precision: int = 3, number_discretized_bonds: Optional[int] = None, verbose: bool = True)

Initialize Slater-Koster model.

After initialization this object provides methods returning various elements of the tight-binding Hamiltonian, derived from the standard Slater-Koster parameter.

Arguments:
  • sk_params (dict): Dictionary containing Slater-Koster parameter.
  • structure (dict): Dictionary containing information about structure.
  • precision (int): Number of decimal places to round displacement vectors. Defaults to 3.
  • number_discretized_bonds (Optional[int]): Sets the number of similar bonds identified for the averaged operator based on the joint distribution of both atoms participating in a bond. Defaults to None, which implies that it is set to the square of the number of species in the random alloy.
  • verbose (bool): Flag triggering output. Defaults to True.
def clear_external_potentials(self) -> None:

Reset list of external potentials.

This clears the list of external potentials.

def add_electric_field( self, electric_field: numpy.ndarray, enforce_zero_mean: bool = True) -> None:

Add electric field to Hamiltonian.

The electric field is included as linear potential $V_\mathrm{E}$ given by $$V_\mathrm{E}(\vec{r}) = \vec{E} \cdot \vec{r},$$ where $\vec{E}$ specified by the vector electric_field (in eV / Angstrom).

Arguments:
  • electric_field (np.ndarray): Electric field (expected in eV / Angstrom).
  • enforce_zero_mean (bool): Flag indicating whether to normalize \ the potential to zero mean over the entire system. \ Defaults to True.
Raises:
  • ValueError: If electric field is not a 3D vector.
def add_harmonic_potential( self, stiffness: numpy.ndarray, origin: Optional[numpy.ndarray] = None, enforce_zero_mean: bool = True) -> None:

Add harmonic potential to Hamiltonian.

The harmonic potential $V_\mathrm{harmonic}$ is defined as $$ V_\mathrm{harmonic} = \frac{1}{2} (\vec{r} - \vec{r}_0) \cdot \underline{S} \cdot (\vec{r} - \vec{r}_0) $$ with $\underline{S}$ being the stiffness matrix and $\vec{r}_0$ the center of the harmonic potential, specified by the 'origin' argument. If 'origin' is not provided by the user, the geometric center of the system is used.

Arguments:
  • stiffness (np.ndarray): Oscillator strength (expected in eV / Angstrom^2).
  • origin (Optional[np.ndarray]): Center of harmonic potential. \ Defaults to None, which implies geometric center.
  • enforce_zero_mean (bool): Flag indicating whether to normalize \ the potential to zero mean over the entire system. \ Defaults to True.
Raises:
  • ValueError: If oscillator strength is not a 3x3 matrix.
  • ValueError: If origin is provided, but not a 3D vector.
def add_magnetic_field( self, magnetic_field: numpy.ndarray, gauge: Literal['planar', 'symmetric', 'minimal'] = 'minimal') -> None:

Add magnetic field to Hamiltonian.

Magnetic field is expected in Tesla. The method converts it into the internal units, which take eV (energy), m_e (mass), e (charge) and Angstrom (length) as base units.

Arguments:
  • magnetic_field (np.ndarray): Constant magnetic field (in Tesla).
  • gauge (Literal["planar", "symmetric", "minimal"]): Gauge choice. Defaults to "minimal", which implies that the vector potential does not depend on "z", in general, and only on "x" if the user- specified magnetic field is in the y-z plane.
Raises:
  • ValueError: If gauge is not one of the supported options.
def get_positions(self) -> numpy.ndarray:

Get position of all atoms.

NOTE: The returned array is of shape ( number of unit cells along x, number of unit cells along y, number of unit cells along z, number of atoms per unit cell, 3 (number of Cartesian coordinates), )

Returns:

np.ndarray: Array holding position of all atoms.

def generate_hash(self) -> str:

Generate hash based on structural input and sample/distribution.

Raises:
  • ValueError: If neither sample nor distribution has been loaded previously.
Returns:

str: hash string composed of input hash and either sample or distribution hash.

def write_operator(self) -> sk_builder.models.SerializedOperator:

Write operator analysis to file.

Given the structural input during initialization and an explicit sample for the alloy the linear operator representing the Hamiltonian is serialized to a file using numpy's savez_compressed function. The relevant information for loading this serialized operator is represented by the returned SerializedOperator object, a pydantic model holding the filename for the binary file written for a set of numpy arrays and some properties facilitating loading the various numpy arrays stored in the binary file.

Returns:

SerializedOperator: Model representing serialized operator.

Raises:
  • ValueError: If neither sample nor distribution have been loaded previously.
def read_operator(self, serialized_operator: sk_builder.models.SerializedOperator) -> None:

Read operator analysis from file.

Based on a SerializedOperator object, this function loads the relevant numpy arrays from a binary file written by numpy's savez_compressed function and sets the relevant properties of the SlaterKosterModel object.

Arguments:
  • serialized_operator (SerializedOperator): Model representing serialized operator.
Raises:
  • ValueError: If simulation size of serialized operator is incompatible with system size.
  • ValueError: If hash check for serialized operator fails.
def load_sample( self, sample: numpy.ndarray, initialize_operator: bool = True, bloch_vector: Optional[numpy.ndarray] = None, compute_offdiagonals_bulk: bool = False) -> None:

Load random alloy sample.

Loading a sample triggers the construction of the Hamiltonian operator corresponding to the given sample.

Arguments:
  • sample (np.ndarray): input sample to be loaded
  • initialize_operator (bool): Flag triggering construction of operator. Defaults to True.
  • bloch_vector (Optional[np.ndarray]): Bloch vector to used across boundaries. Defaults to None, which implies that "Gamma" or (0, 0, 0) is used as bloch vector.
  • compute_offdiagonals_bulk (bool): Flag triggering construction of "bulk" operator. Defaults to False.
Raises:
  • ValueError: If sample size is incompatible with number of atoms.
def load_distribution( self, distribution: numpy.ndarray, initialize_operator: bool = True, bloch_vector: Optional[numpy.ndarray] = None, compute_offdiagonals_bulk: bool = False) -> None:

Load random alloy distribution.

Loading a distribution implies that an averaged Hamiltonian operator, corresponding to the given distribution, is generated.

This is the equivalent of loading infinitely many samples from the same distribution and averaging the resulting operators.

Arguments:
  • distribution (np.ndarray): Random alloy distribution.
  • initialize_operator (bool): Flag triggering construction of operator. Defaults to True.
  • bloch_vector (Optional[np.ndarray]): Bloch vector to used across boundaries. Defaults to None, which implies that "Gamma" or (0, 0, 0) is used as bloch vector.
  • compute_offdiagonals_bulk (bool): Flag triggering construction of "bulk" operator. Defaults to False.
Raises:
  • ValueError: If distribution is incompatible with number of atoms.
  • ValueError: If distribution is incompatible with number of species.
def get_hamiltonian(self, prune: bool = False) -> scipy.sparse._csr.csr_array:

Return full Hamiltonian as sparse (CSR) matrix.

Arguments:
  • prune (bool): Flag indicating whether to prune sparse matrix. Defaults to False.
Returns:

SPM.csr_array: Hamiltonian for full system as sparse (CSR) matrix.

def get_velocity( self, velocity_component: Literal['x', 'y', 'z'], prune: bool = False) -> scipy.sparse._csr.csr_array:

Return velocity as sparse (CSR) matrix.

Implementation include the leading $-\imath / \hbar$, which assumes that energies (Slater-Koster parameters) are provided in eV and length are provided in Angstrom.

Arguments:
  • velocity_component (Literal["x", "y", "z"]): Component of velocity to return.
  • prune (bool): Flag indicating whether to prune sparse matrix. Defaults to False.
Returns:

SPM.csr_array: Velocity operator as sparse (CSR) matrix.

def get_hamiltonian_bloch(self, kpt: numpy.ndarray) -> numpy.ndarray:

Produces the VCA version of the Hamiltonian at the specified k-point.

Arguments:
  • kpt (np.ndarray): k-point of shape capable of being "squeezed" into (3,).
Returns:

np.ndarray: The VCA version of the system Hamiltonian at the specified k-point as shape (l, l), where l is the dimension the unit cell.

def get_linear_operator( self, state: numpy.ndarray, shift: float = 0.0, scale: float = 1.0, batch_size: int = 1) -> Callable[[numpy.ndarray, numpy.ndarray], numpy.ndarray]:

Returns function implementing the application of the Hamiltonian.

NOTE: The supplied shift moves the spectrum of the Hamiltonian in the negative direction. This implies that choosing as shift the center of the spectrum, e.g., shift = 0.5 * (ev_min + ev_max) with ev_min being the lower bound and ev_max the upper bound of the spectrum, will center the spectrum at zero.

NOTE: The supplied scale is applied after shifting the spectrum. This implies that supplying a shift = 0.5 * (ev_min + ev_max) and a scale = 2 / (ev_max - ev_min) will map the spectrum into the interval (-1, 1).

Arguments:
  • state (np.ndarray): Template for output state.
  • shift (float): Constant shift applied to spectrum of Hamiltonian. Defaults to 0.0.
  • scale (float): Scale applied to spectrum of Hamiltonian (after shift!). Defaults to 1.0.
  • batch_size (int): Number of states in batch. Defaults to 1.
Returns:

Callable: Function implementing application of Hamiltonian.

Raises:
  • ValueError: If template state does not have correct shape for linear operator.
def get_linear_operator_mkl( self, state: numpy.ndarray, shift: float = 0.0, scale: float = 1.0, batch_size: int = 1) -> Callable[[numpy.ndarray, numpy.ndarray], numpy.ndarray]:

Returns function implementing the application of the Hamiltonian using MKL.

Implementation uses MKL via the sparse_dot_mkl Python package.

NOTE: The supplied shift moves the spectrum of the Hamiltonian in the negative direction. This implies that choosing as shift the center of the spectrum, e.g., shift = 0.5 * (ev_min + ev_max) with ev_min being the lower bound and ev_max the upper bound of the spectrum, will center the spectrum at zero.

NOTE: The supplied scale is applied after shifting the spectrum. This implies that supplying a shift = 0.5 * (ev_min + ev_max) and a scale = 2 / (ev_max - ev_min) will map the spectrum into the interval (-1, 1).

Arguments:
  • state (np.ndarray): Template for output state.
  • shift (float): Constant shift applied to spectrum of Hamiltonian. Defaults to 0.0.
  • scale (float): Scale applied to spectrum of Hamiltonian (after shift!). Defaults to 1.0.
  • batch_size (int): Number of states in batch. Defaults to 1.
Returns:

Callable: Function implementing application of Hamiltonian.

def get_velocity_operator( self, state: numpy.ndarray, velocity_component: Literal['x', 'y', 'z'], scale: float = 1.0, batch_size: int = 1) -> Callable[[numpy.ndarray, numpy.ndarray], numpy.ndarray]:

Returns function implementing the application of the velocity operator.

Arguments:
  • state (np.ndarray): Template for output state.
  • velocity_component (Literal["x", "y", "z"]): Cartesian direction of velocity.
  • scale (float): Scale applied to spectrum of Hamiltonian (after shift!). Defaults to 1.0.
  • batch_size (int): Number of states in batch. Defaults to 1.
Returns:

Callable: Function implementing application of Hamiltonian.