PAOFLOW.models.sk_fitting#
sk_fitting — Slater-Koster tight-binding fitting engine.
This module implements a hierarchy of three fitting classes that extract Slater-Koster (SK) tight-binding parameters from a PAOFLOW PAO Hamiltonian \(H(\mathbf{R})\) via eigenvalue-based least-squares optimisation with an analytic (Hellmann-Feynman) Jacobian.
Physics background#
Slater-Koster theory expresses every hopping matrix element between
two orbitals in terms of a small set of two-centre integrals
\(V_{ss\sigma}, V_{sp\sigma}, V_{pp\sigma}, V_{pp\pi}, \ldots, V_{dd\delta}\)
and the bond direction cosines \((l_x, l_y, l_z)\). The function
sk_element() implements the full Slater-Koster table for
\(s/p/d\) orbitals, including all \(\sqrt{3}\) prefactors.
sk_design_row() returns the linear coefficient vector of each SK
parameter for a given pair of orbitals and bond direction, enabling
vectorised Jacobian computation.
Class hierarchy#
SKFitterBase two-centre Slater-Koster fitter.
Enumerates all bonds up to n_shells neighbor shells from the \(H(\mathbf{R})\) grid.
Builds precomputed design tensors and block-sparse \(\partial H/\partial V\) arrays (
_dHk_shells).Fits on-site energies \(\varepsilon\) and hopping parameters \(V_\lambda\) by minimising the eigenvalue RMSE
\[\mathcal{L} = \sum_{\mathbf{k},n} \bigl(E_{n\mathbf{k}}^\text{SK}(p) - E_{n\mathbf{k}}^\text{PAO}\bigr)^2\]using
scipy.optimize.least_squareswith a Hellmann-Feynman Jacobian and multi-start random initialisation.Outputs a species-pair-keyed model dict compatible with
edtb_params.
SKFitterEDTB(extends SKFitter)Environment-dependent TB extension. Each hopping is screened by a bond-environment sum \(S_{ij}\):
\[V_\lambda^{\text{eff}}(i,j) = V_\lambda^{(2c)} \exp\!\bigl(-\gamma_\lambda\,S_{ij}\bigr), \qquad S_{ij} = \sum_{k \neq i,j} f_c(d_{ik})\,f_c(d_{jk})\]where \(f_c\) is a smooth cosine cutoff tapering to zero at
r_cut. The screening strength \(\gamma\) can be shared globally, per angular-momentum pair, or per SK channel (gamma_mode). Optionally fits environment-dependent on-site shifts \(\varepsilon_\alpha \to \varepsilon_\alpha + \eta_\alpha \sum_k f_c(d_{ik})\).MultiGeomEDTBMulti-geometry EDTB fitter. Fits a single shared parameter set \((\varepsilon, V_\lambda, \gamma, \eta)\) to DFT band structures from multiple atomic configurations simultaneously — essential for learning physically meaningful \(\gamma\) values. Geometries may differ in lattice parameter, strain, or surface termination (same species and orbital basis required). Evaluations across geometries are parallelised with
ThreadPoolExecutor(eighreleases the GIL). Supports species harmonisation when not all geometries contain the same species.
Module-level helpers#
sk_element()Full SK table for an \(s/p/d\) orbital pair and bond cosines.
sk_design_row()Length-10 linear coefficient vector of the SK parameters for a given orbital pair.
Key module-level constants#
SK_PARAM_NAMES,SK_LABELSCanonical names and labels for the 10 SK integrals (\(V_{ss\sigma}\) through \(V_{dd\delta}\)).
ORBITAL_NAMESChemistry real-orbital names
('s', 'px', ..., 'dz2').LPAIR_ACTIVE_NAMES,LPAIR_ACTIVE_INDICESActive SK parameters for each angular-momentum pair \((l, l')\).
SHELL_TO_ORBITALSOrbital name list for each angular-momentum shell.
Typical usage#
from PAOFLOW.models.sk_fitting import SKFitter, SKFitterEDTB, MultiGeomEDTB
# 1. Plain SK fit
fitter = SKFitter(arryp, attrp, n_shells=2, nkfit=6)
result = fitter.fit(n_trials=20, seed=123)
model = fitter.build_model_dict(result['p_opt'])
# 2. Staged EDTB: fix SK then fit γ
p_sk = result['p_opt']
edtb = SKFitterEDTB(arryp, attrp, n_shells=2, r_cut=8.0, gamma_mode='per_lpair')
result_edtb = edtb.fit(p0_sk=p_sk, n_trials=10)
model_edtb = edtb.build_model_dict(result_edtb['p_opt'])
# 3. Multi-geometry EDTB
geoms = [(arry_eq, attr_eq), (arry_p5, attr_p5), (arry_m5, attr_m5)]
mg = MultiGeomEDTB(geoms, n_shells=2, r_cut=8.0, gamma_mode='global')
result_mg = mg.fit(p0_sk=p_sk, n_trials=10, n_jobs=-1)
Reference#
J.C. Slater & G.F. Koster, Phys. Rev. 94, 1498 (1954).
Attributes#
Classes#
Slater-Koster eigenvalue-based fitter. |
|
Environment-dependent tight-binding (EDTB) extension of SKFitter. |
|
Multi-geometry environment-dependent tight-binding fitter. |
|
Multi-geometry distance-dependent EDTB fitter. |
|
SKFitterEDTB augmented with high-symmetry-path k-points and per-k weights. |
Functions#
|
Slater-Koster two-center hopping matrix element H(orb_a, orb_b). |
|
Coefficient of each SK parameter for matrix element H(orb_a, orb_b). |
Module Contents#
- PAOFLOW.models.sk_fitting.ORBITAL_NAMES = ('s', 'px', 'py', 'pz', 'dxy', 'dyz', 'dzx', 'dx2-y2', 'dz2')[source]#
- PAOFLOW.models.sk_fitting.SK_PARAM_NAMES = ['sss', 'sps', 'pps', 'ppp', 'sds', 'pds', 'pdp', 'dds', 'ddp', 'ddd'][source]#
- PAOFLOW.models.sk_fitting.SK_LABELS = ['Vssσ', 'Vspσ', 'Vppσ', 'Vppπ', 'Vsdσ', 'Vpdσ', 'Vpdπ', 'Vddσ', 'Vddπ', 'Vddδ'][source]#
- PAOFLOW.models.sk_fitting.sk_element(orb_a, orb_b, lx, ly, lz, sh)[source]#
Slater-Koster two-center hopping matrix element H(orb_a, orb_b).
- Parameters:
orb_a (str) – Orbital names from
ORBITAL_NAMES.orb_b (str) – Orbital names from
ORBITAL_NAMES.lx (float) – Direction cosines of the bond vector.
ly (float) – Direction cosines of the bond vector.
lz (float) – Direction cosines of the bond vector.
sh (dict) – SK parameter dict with keys from
SK_PARAM_NAMES.
- Returns:
The matrix element value.
- Return type:
- PAOFLOW.models.sk_fitting.sk_design_row(orb_a, orb_b, lx, ly, lz)[source]#
Coefficient of each SK parameter for matrix element H(orb_a, orb_b).
- Returns:
Length-10 array: entry k is the coefficient of
SK_PARAM_NAMES[k].- Return type:
np.ndarray
- class PAOFLOW.models.sk_fitting.SKFitter(arryp, attrp, *, n_shells=2, nkfit=6, verbose=True)[source]#
Slater-Koster eigenvalue-based fitter.
Constructs design tensors from a PAO Hamiltonian and fits SK parameters by minimising the eigenvalue RMSE on a uniform k-mesh.
- Parameters:
arryp (dict) – PAOFLOW
arraysdict (needsa_vectors,b_vectors,tau,atoms,shells,HRs; optionallyconfiguration).attrp (dict) – PAOFLOW
attributesdict (needsalat,natoms).n_shells (int) – Number of neighbor shells to include (default 2 → NN + NNN).
nkfit (int) – Subdivisions along each reciprocal axis for the fitting k-mesh (total k-points =
nkfit**3).verbose (bool) – Print progress information.
- extract_onsite_from_HR0()[source]#
Extract initial on-site energies from H(R=0) diagonal blocks.
Uses QE orbital ordering (m = 0, +1, -1, …) for t2g/eg splitting.
- Returns:
On-site parameter vector of length
n_onsite.- Return type:
np.ndarray
- fit(n_trials=10, seed=123, max_nfev=1000, ftol=1e-12, xtol=1e-12, gtol=1e-12, alpha=0.0, n_jobs=1)[source]#
Run multi-start least-squares optimisation.
- Parameters:
n_trials (int) – Number of random restarts.
seed (int or None) – Random seed for reproducibility.
max_nfev (int) – Max function evaluations per trial.
ftol (float) – Tolerances for
scipy.optimize.least_squares.xtol (float) – Tolerances for
scipy.optimize.least_squares.gtol (float) – Tolerances for
scipy.optimize.least_squares.alpha (float) – Tikhonov regularization strength (default 0 = no penalty). Adds
alpha * w_i * p_ipenalty rows to the residual, wherew_iis proportional to the neighbor-shell distance (farther shells are penalized more). On-site parameters are not penalized. Typical values: 0.01–1.0 (start small, increase if far-neighbor hoppings blow up).n_jobs (int) – Number of parallel workers for multi-start trials (default 1 = sequential). Use
-1for all available cores. Requiresjoblibwhenn_jobs != 1.
- Returns:
p_opt: best parameter vector.rmse: best RMSE (eV) (data-only, excluding penalty).max_err: max absolute error (eV).all_results: list of(rmse, p, OptimizeResult)sorted by RMSE.param_labels: parameter names.- Return type:
- build_model_dict(p)[source]#
Convert a fitted parameter vector into a model dict.
The output uses species-pair-keyed hoppings with explicit shell reference distances (Bohr), following the
edtb_paramsschema:"hoppings": { "Pt-Pt": [ {"r_ref": 5.247, "params": {"sss": ..., "sps": ...}}, ... ] }
- Parameters:
p (np.ndarray) – Parameter vector (length
n_params).- Returns:
Model dict with species-pair-keyed hoppings.
- Return type:
- class PAOFLOW.models.sk_fitting.SKFitterEDTB(arryp, attrp, *, n_shells=2, nkfit=6, r_cut, gamma_mode='global', fit_onsite_shift=False, verbose=True)[source]#
Bases:
SKFitterEnvironment-dependent tight-binding (EDTB) extension of SKFitter.
Augments the two-center SK hopping integrals with an environment-dependent screening factor:
\[V_\lambda^{\text{eff}}(i,j) = V_\lambda^{(2c)} \exp\!\bigl(-\gamma_\lambda\,S_{ij}\bigr)\]where \(S_{ij} = \sum_{k \neq i,j} f_c(d_{ik})\,f_c(d_{jk})\) is a bond screening sum and \(f_c\) is a smooth cosine cutoff that tapers to zero between \(0.8\,r_\text{cut}\) and \(r_\text{cut}\).
Optionally fits environment-dependent on-site shifts:
\[\varepsilon_\alpha \;\to\; \varepsilon_\alpha + \eta_\alpha \sum_k f_c(d_{ik})\]The screening strengths \(\gamma\) can be parametrised at three granularity levels (
gamma_mode):'global'— one \(\gamma\) for all channels (1 parameter).'per_lpair'— one per angular-momentum pair (ss, sp, pp, …; up to 6).'per_channel'— one per SK integral (ssσ, spσ, ppσ, ppπ, …; up to 10).
- Parameters:
n_shells (int) – Number of neighbor shells (default 2).
nkfit (int) – k-mesh subdivision (default 6).
r_cut (float) – Screening cutoff radius in Bohr.
gamma_mode ({'global', 'per_lpair', 'per_channel'}) – Granularity of screening parameters (default
'global').fit_onsite_shift (bool) – Whether to fit \(\eta\) on-site shift parameters (default False).
verbose (bool) – Print progress information.
Notes
For a single crystal structure the screening parameters are partially redundant with the shell-dependent hoppings. Meaningful \(\gamma\) values typically require multi-structure training data or external constraints on the two-center integrals (e.g. supply
p0_sktofit()so that only \(\gamma\) and \(\eta\) are free to adjust).Usage#
>>> fitter = SKFitterEDTB(arry, attr, n_shells=2, nkfit=6, r_cut=8.0) >>> result = fitter.fit(n_trials=10, seed=42) >>> model = fitter.build_model_dict(result['p_opt'])
Staged fitting (recommended):
>>> fitter_sk = SKFitter(arry, attr, n_shells=2) >>> p_sk = fitter_sk.fit(n_trials=20)['p_opt'] >>> fitter_edtb = SKFitterEDTB(arry, attr, n_shells=2, r_cut=8.0) >>> result = fitter_edtb.fit(p0_sk=p_sk, n_trials=10)
- fit(*, p0_sk=None, n_trials=10, seed=123, max_nfev=1000, ftol=1e-12, xtol=1e-12, gtol=1e-12, alpha=0.0, n_jobs=1)[source]#
Multi-start least-squares fit including screening parameters.
- Parameters:
p0_sk (np.ndarray, optional) – Initial SK parameter vector (length
n_sk). If provided the first trial uses these values directly; subsequent trials add a small random perturbation to the hopping part. If None, on-site energies are extracted from H(R=0) and hoppings are randomised (same behaviour asSKFitter).n_trials – Same as
SKFitter.fit().seed – Same as
SKFitter.fit().max_nfev – Same as
SKFitter.fit().ftol – Same as
SKFitter.fit().xtol – Same as
SKFitter.fit().gtol – Same as
SKFitter.fit().alpha – Same as
SKFitter.fit().n_jobs (int) – Number of parallel workers for multi-start trials (default 1 = sequential). Use
-1for all available cores. Requiresjoblibwhenn_jobs != 1.
- Returns:
p_opt: best parameter vector (lengthn_params).rmse: best RMSE (eV, data-only).max_err: max absolute error (eV).all_results: sorted list of(rmse, p, OptimizeResult).param_labels: parameter names.- Return type:
- build_model_dict(p)[source]#
Convert fitted parameters to an
SK_EDTBmodel dict.The screening
gammais wrapped in a species-pair key, consistent with the species-pair-keyed hoppings from the base class.- Parameters:
p (np.ndarray) – Full parameter vector (length
n_params).- Returns:
Model dict with
label='SK_EDTB'andscreeningblock.- Return type:
- class PAOFLOW.models.sk_fitting.MultiGeomEDTB(geometries, *, n_shells=2, nkfit='auto', r_cut, gamma_mode='global', fit_onsite_shift=False, weights=None, verbose=True)[source]#
Multi-geometry environment-dependent tight-binding fitter.
Fits a single shared set of parameters \((\varepsilon, V_\lambda, \gamma, \eta)\) to DFT band structures from multiple atomic configurations simultaneously, which is essential for learning physically meaningful screening strengths \(\gamma\) that capture the environment dependence of hopping integrals.
Each geometry is represented internally by an independent
SKFitterEDTBinstance (with its own screening sums \(S_{ij}\), design tensors, and reference eigenvalues). The combined objective is the (optionally weighted) concatenation of eigenvalue residuals over all geometries.Note
All geometries must share the same species, orbital basis, and shell structure so that the hopping parameter vector is identical. This is automatically satisfied when the training set consists of the same material at different lattice parameters, strains, surfaces, or defect configurations (with the same pseudopotential and projection basis).
Typical training sets#
Volume scan: equilibrium ± 2%, ± 5% isotropic expansion (easiest to generate, same symmetry).
Tetragonal distortion: c/a ≠ 1 strains that break cubic symmetry.
Surface slab: 5–7 layer slab with vacuum; atoms at the surface have reduced coordination → very different \(S_{ij}\).
- param geometries:
PAOFLOW data-dict pairs, one per configuration.
- type geometries:
list of (arryp, attrp) tuples
- param n_shells:
Number of neighbor shells (default 2).
- type n_shells:
int
- param nkfit:
k-mesh subdivision (default 6).
- type nkfit:
int
- param r_cut:
Screening cutoff radius in Bohr.
- type r_cut:
float
- param gamma_mode:
Screening parameter granularity.
- type gamma_mode:
{‘global’, ‘per_lpair’, ‘per_channel’}
- param fit_onsite_shift:
Whether to fit η on-site shift parameters (default False).
- type fit_onsite_shift:
bool
- param nkfit:
Subdivisions along each reciprocal axis for the fitting k-mesh. If an int, applies uniformly to all geometries. If a list, must have one entry per geometry; each entry can be an int (uniform) or a 3-tuple
(n1, n2, n3)for an anisotropic grid. Use'auto'(default) to automatically detect slab geometries and reduce the k-grid to 1 along the vacuum direction.- type nkfit:
int or list of int/tuple
- param weights:
Per-geometry weights for the loss function. Default: uniform (all 1.0). Increase weight on geometries that should be reproduced more accurately (e.g. equilibrium bulk).
- type weights:
list of float, optional
- param verbose:
Print progress information.
- type verbose:
bool
- param Usage:
- param —–:
- param >>> from sk_fitting import SKFitter:
- param MultiGeomEDTB:
- param >>> # Pre-fit SK on equilibrium geometry:
- param >>> fitter_sk = SKFitter(arry_eq:
- param attr_eq:
- param n_shells=3):
- param >>> p_sk = fitter_sk.fit(n_trials=20)[‘p_opt’]:
- param >>> # Multi-geometry EDTB:
- param >>> geoms = [(arry_eq:
- param attr_eq):
- param (arry_p5:
- param attr_p5):
- param (arry_m5:
- param attr_m5)]:
- param >>> mg = MultiGeomEDTB(geoms:
- param n_shells=3:
- param r_cut=8.0:
- param gamma_mode=’per_lpair’):
- param >>> result = mg.fit(p0_sk=p_sk:
- param n_trials=10:
- param n_jobs=-1):
- param >>> model = mg.build_model_dict(result[‘p_opt’]):
- fitters: list[SKFitterEDTB] = [][source]#
- extract_onsite_from_HR0()[source]#
Extract initial on-site energies, merging across geometries.
After species harmonisation each fitter has the full species set, but dummy-species slots return zero. This method collects real-species values from whichever geometry actually contains each species.
- fit(*, p0_sk=None, n_trials=10, seed=123, max_nfev=2000, ftol=1e-12, xtol=1e-12, gtol=1e-12, alpha=0.0, n_jobs=1, fix_onsite=None)[source]#
Multi-start least-squares fit across all geometries.
- Parameters:
p0_sk (np.ndarray, optional) – Initial SK parameter vector (length
n_sk). Typically from a single-geometrySKFitter.fit()on the equilibrium configuration.n_trials (int) – Number of random restarts.
seed (int or None) – Random seed for reproducibility.
max_nfev (int) – Max function evaluations per trial (default 2000, larger than single-geometry because the combined landscape is harder).
ftol (float) – Tolerances for
scipy.optimize.least_squares.xtol (float) – Tolerances for
scipy.optimize.least_squares.gtol (float) – Tolerances for
scipy.optimize.least_squares.alpha (float) – Tikhonov regularization strength.
n_jobs (int) – Parallel workers for multi-start trials (
-1= all cores).fix_onsite (dict, optional) – Fix on-site energies to given values instead of fitting them. Dict mapping species name to an on-site dict, e.g.
{'Si': {'s': -3.64, 'p': 2.14, 't2g': 6.30, 'eg': 6.37}, 'Ge': {'s': -5.30, 'p': 1.68, ...}}. Typically obtained from independently fitted bulk models viamodel.params['onsite']['Si'].
- Returns:
p_opt: best parameter vector (lengthn_params).rmse: best combined RMSE (eV).per_geom_rmse: list of per-geometry RMSE values (eV).max_err: max absolute eigenvalue error (eV).all_results: sorted list of(rmse, p, OptimizeResult).param_labels: parameter names.- Return type:
- build_model_dict(p, geom_idx=None)[source]#
Convert fitted parameters to a PAOFLOW
SK_EDTBmodel dict.- Parameters:
p (np.ndarray) – Full parameter vector (length
n_params).geom_idx (int or None) – Which geometry to use for lattice vectors and atom positions. If
None(default), the first geometry that contains all harmonised species is chosen automatically; this avoidscompute_pair_shell_distancesfailing on dummy-species pairs that have no atoms.
- Returns:
Model dict with
label='SK_EDTB'.- Return type:
- class PAOFLOW.models.sk_fitting.MultiGeomEDTB_DD(geometry_data, *, r_0, r_c, r_cut, gamma_mode='global', fit_onsite_shift=False, nkfit=6, weights=None, verbose=True)[source]#
Multi-geometry distance-dependent EDTB fitter.
Fits Goodwin-style hopping parameters shared across multiple geometries (e.g. bulk + slabs at different interlayer distances).
- Parameters:
geometry_data (list of (arryp, attrp) tuples) – PAOFLOW arrays/attributes for each geometry.
r_0 (float) – Reference NN distance (Bohr). Fixed, not fitted.
r_c (float) – Hopping cutoff (Bohr). Fixed, used in Goodwin exponent and as maximum bond distance.
r_cut (float) – Screening cutoff radius (Bohr).
gamma_mode (str) –
'global','per_lpair', or'per_channel'.fit_onsite_shift (bool) – Whether to fit η on-site coordination-shift parameters.
nkfit (int or list of int) – k-grid density for fitting. If a list, one per geometry.
weights (list of float, optional) – Per-geometry weights (default: uniform).
verbose (bool)
- fit(*, p0=None, n_trials=10, seed=123, max_nfev=2000, ftol=1e-12, xtol=1e-12, gtol=1e-12, alpha=0.0, bounds=None, n_jobs=1)[source]#
Multi-start least-squares fit.
- Parameters:
p0 (np.ndarray, optional) – Initial parameter vector.
n_trials (int) – Number of random restarts.
seed (int or None)
max_nfev (int)
ftol (float)
xtol (float)
gtol (float)
alpha (float) – Tikhonov regularization.
bounds (tuple of (lower, upper), optional) – Bounds for the parameter vector. Each is array of length n_params or
-np.inf/np.inf.n_jobs (int) – Parallel workers for multi-start trials (
-1= all cores). Requiresjoblibwhenn_jobs != 1.
- Return type:
- class PAOFLOW.models.sk_fitting.SKFitterEDTBHSP(*args, **kwargs)[source]#
Bases:
SKFitterEDTBSKFitterEDTB augmented with high-symmetry-path k-points and per-k weights.
Subclass of
SKFitterEDTBthat augments the fitting k-point pool with points sampled along the canonical high-symmetry band path. Each HSP k-point receives a configurable weight w_hsp relative to the uniform BZ-grid points (weight 1).Usage#
>>> fitter = SKFitterEDTBHSP(arry, attr, n_shells=3, nkfit=4, ...) >>> nk_added, path_str = fitter.augment_with_bands_path(nk=500, w_hsp=2.0, ibrav=2) >>> result = fitter.fit(n_trials=10, seed=123, alpha=0.1, n_jobs=-1)
- augment_with_bands_path(nk=500, w_hsp=1.0, ibrav=2, band_path=None, special_points=None)[source]#
Add high-symmetry-path k-points to the fitting pool.
- Parameters:
nk (int) – Approximate number of HSP k-points to add.
w_hsp (float) – Weight assigned to each HSP k-point (BZ-grid points have weight 1).
ibrav (int) – PAOFLOW lattice index (2 = FCC). Auto-path when band_path is None.
band_path (str or None) – Band path string (e.g.
'G-L-G-X-W-X-K-G'). None → auto from ibrav.special_points (dict or None) – Mapping label → (kx, ky, kz) in fractional coordinates. None → auto-determined from ibrav.
- Returns:
nk_added (int) – Number of k-points actually added.
path_str (str) – Band-path string returned by
get_path().
- extract_p0_sk(params_dict)[source]#
Extract the SK parameter sub-vector from a saved EDTB params dict.
Reverses
build_model_dictfor the SK part (on-site + hoppings), so the returned vector can be fed tofit(p0_sk=...).- Parameters:
params_dict (dict) – EDTB parameter dict (as stored in
*_params.json).- Returns:
SK parameter vector of length
n_sk.- Return type:
np.ndarray