Skip to main content

Rustb/
error.rs

1//! src/error.rs
2//! This module defines the custom error types for the entire tight-binding library.
3//! By using a centralized error enum, we can replace all panics with recoverable
4//! Results, making the library safer and more robust for consumers.
5
6use crate::atom_struct::AtomType;
7use crate::{OrbProj, SpinDirection};
8use ndarray::{Array1, Array2, ShapeError};
9use num_complex::Complex;
10use thiserror::Error;
11
12/// The primary error type for all fallible operations in this library.
13#[derive(Error, Debug)]
14pub enum TbError {
15    // --- I/O and Parsing Errors ---
16    #[error("I/O error: {0}")]
17    Io(#[from] std::io::Error),
18
19    #[error("Failed to parse data from file '{file}': {message}")]
20    FileParse { file: String, message: String },
21
22    #[error("Invalid orbital projection string: '{0}'")]
23    InvalidOrbitalProjection(String),
24
25    #[error("Invalid atom type string: '{0}'")]
26    InvalidAtomType(String),
27
28    #[error("Failed to create directory '{path}': {message}")]
29    DirectoryCreation { path: String, message: String },
30
31    #[error("Failed to create file '{path}': {message}")]
32    FileCreation { path: String, message: String },
33
34    // --- Linear Algebra and Numerical Errors ---
35    #[error("Linear algebra operation failed: {0}")]
36    Linalg(#[from] ndarray_linalg::error::LinalgError),
37
38    #[error("LAPACK routine '{routine}' failed with non-zero info code: {info}")]
39    Lapack { routine: &'static str, info: i32 },
40
41    #[error("Matrix inversion failed: matrix is singular or ill-conditioned")]
42    MatrixInversionFailed,
43
44    #[error("Eigenvalue computation failed")]
45    EigenvalueComputationFailed,
46
47    #[error("SVD computation failed")]
48    SvdComputationFailed,
49
50    // --- Invalid Input and Arguments ---
51    #[error("Dimension mismatch for '{context}': expected {expected}, got {found}")]
52    DimensionMismatch {
53        context: String,
54        expected: usize,
55        found: usize,
56    },
57
58    #[error("Invalid array shape: expected {expected:?}, got {found:?}")]
59    InvalidArrayShape {
60        expected: Vec<usize>,
61        found: Vec<usize>,
62    },
63
64    #[error("The path for the Wilson Loop is not closed. Remainder vector: {0:?}")]
65    UnclosedWilsonLoop(Array1<f64>),
66
67    #[error("The provided direction index '{index}' is out of bounds for dimension '{dim}'")]
68    InvalidDirectionIndex { index: usize, dim: usize },
69
70    #[error("Invalid supercell size 'num' for cut_piece: {0}. Must be >= 1.")]
71    InvalidSupercellSize(usize),
72
73    #[error("Invalid shape identifier for cut_dot: {0}. Supported shapes are 3, 4, 6, 8.")]
74    InvalidShapeIdentifier(usize),
75
76    #[error(
77        "The supercell transformation matrix U must have integer elements and a non-zero determinant."
78    )]
79    InvalidSupercellMatrix,
80
81    #[error("Spin direction '{0:?}' is invalid for a model without spin.")]
82    SpinNotAllowed(SpinDirection),
83
84    #[error("Invalid k-point mesh dimensions: {0:?}")]
85    InvalidKmeshDimensions(Array1<usize>),
86
87    #[error("Invalid energy range: min={min}, max={max}")]
88    InvalidEnergyRange { min: f64, max: f64 },
89
90    // --- Model Consistency and Physics Errors ---
91    #[error("On-site hopping energy must be a real number, but got {0}")]
92    OnsiteHoppingMustBeReal(Complex<f64>),
93
94    #[error(
95        "Internal model inconsistency: Hopping for vector R={r:?} exists, but its Hermitian conjugate for -R does not."
96    )]
97    MissingHermitianConjugateHopping { r: Array1<isize> },
98
99    #[error("Invalid operation for a zero-dimensional model.")]
100    InvalidOperationForZeroDimension,
101
102    #[error("Model has not been properly initialized")]
103    ModelNotInitialized,
104
105    #[error("No bands found in the specified energy range")]
106    NoBandsInEnergyRange,
107
108    #[error("Convergence failed after {iterations} iterations")]
109    ConvergenceFailed { iterations: usize },
110
111    // --- Slater-Koster Specific Errors ---
112    #[error(
113        "Missing Slater-Koster parameter '{param}' for atom pair {atom1:?}-{atom2:?} at shell {shell}"
114    )]
115    SkParameterMissing {
116        param: String,
117        atom1: AtomType,
118        atom2: AtomType,
119        shell: usize,
120    },
121
122    #[error("Unsupported orbital combination: {0:?} - {1:?}")]
123    UnsupportedOrbitalCombination(OrbProj, OrbProj),
124
125    #[error("Invalid neighbor search range: {0}")]
126    InvalidSearchRange(i32),
127
128    #[error("No neighbor shells found")]
129    NoShellsFound,
130
131    // --- Feature Not Implemented ---
132    #[error("Hybrid orbital projection '{0}' is not currently supported for this operation")]
133    HybridOrbitalNotSupported(String),
134
135    #[error("Feature '{0}' is not yet implemented")]
136    NotImplemented(String),
137
138    // --- New error variants to replace panics ---
139    #[error(
140        "Lattice matrix dimension error: second dimension length must equal dim_r, but got {actual} (expected {expected})"
141    )]
142    LatticeDimensionError { expected: usize, actual: usize },
143
144    #[error("R vector length error: expected {expected}, got {actual}")]
145    RVectorLengthError { expected: usize, actual: usize },
146
147    #[error("Invalid k-path operation for zero-dimensional model")]
148    ZeroDimKPathError,
149
150    #[error("Path length mismatch: expected {expected}, got {actual}")]
151    PathLengthMismatch { expected: usize, actual: usize },
152
153    #[error("Invalid direction index: {index} for dimension {dim}")]
154    InvalidDirection { index: usize, dim: usize },
155
156    #[error("Invalid shape: {shape}. Supported shapes: {supported:?}")]
157    InvalidShape { shape: usize, supported: Vec<usize> },
158
159    #[error("Invalid dimension for operation: {dim}. Supported dimensions: {supported:?}")]
160    InvalidDimension { dim: usize, supported: Vec<usize> },
161
162    #[error("Duplicate orbitals found in orbital list")]
163    DuplicateOrbitals,
164
165    #[error("Invalid supercell transformation matrix determinant: {det}")]
166    InvalidSupercellDet { det: f64 },
167
168    #[error("Invalid atom positions or count in unit cell")]
169    InvalidAtomConfiguration,
170
171    #[error("Transformation matrix dimension mismatch: expected {expected}, got {actual}")]
172    TransformationMatrixDimMismatch { expected: usize, actual: usize },
173
174    #[error("Missing Hermitian conjugate for R vector: {r:?}")]
175    MissingHermitianConjugate { r: Array1<isize> },
176
177    #[error("Invalid spin value: {spin}. Supported values: {supported:?}")]
178    InvalidSpinValue { spin: usize, supported: Vec<usize> },
179
180    #[error("Temperature T=0 not supported for this operation")]
181    ZeroTemperatureNotSupported,
182
183    #[error("Invalid k-vector length: expected {expected}, got {actual}")]
184    KVectorLengthMismatch { expected: usize, actual: usize },
185
186    #[error("LAPACK eigenvalue computation failed with info code: {info}")]
187    LapackEigenFailed { info: i32 },
188
189    // --- Generic Error ---
190    #[error("Unexpected error: {0}")]
191    Other(String),
192}
193
194/// A specialized `Result` type for this library's operations.
195pub type Result<T> = std::result::Result<T, TbError>;