1use core::fmt;
10
11pub type NumraResult<T> = Result<T, NumraError>;
13
14#[derive(Clone, Debug, PartialEq)]
16pub enum NumraError {
17 Linalg(LinalgError),
19 Convergence(ConvergenceError),
21 InvalidInput(String),
23 StepSizeTooSmall { h: f64, h_min: f64 },
25 MaxIterations { iterations: usize, max: usize },
27 Stiffness { t: f64, message: String },
29 EventTermination { t: f64, event_index: usize },
31 Optimization(OptimizationError),
33}
34
35impl fmt::Display for NumraError {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 match self {
38 NumraError::Linalg(e) => write!(f, "Linear algebra error: {}", e),
39 NumraError::Convergence(e) => write!(f, "Convergence error: {}", e),
40 NumraError::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
41 NumraError::StepSizeTooSmall { h, h_min } => {
42 write!(f, "Step size {} below minimum {}", h, h_min)
43 }
44 NumraError::MaxIterations { iterations, max } => {
45 write!(f, "Maximum iterations ({}) exceeded at {}", max, iterations)
46 }
47 NumraError::Stiffness { t, message } => {
48 write!(f, "Stiffness detected at t={}: {}", t, message)
49 }
50 NumraError::EventTermination { t, event_index } => {
51 write!(f, "Event {} terminated integration at t={}", event_index, t)
52 }
53 NumraError::Optimization(e) => write!(f, "Optimization error: {}", e),
54 }
55 }
56}
57
58#[cfg(feature = "std")]
59impl std::error::Error for NumraError {}
60
61#[derive(Clone, Debug, PartialEq)]
63pub enum LinalgError {
64 Singular { step: usize },
66 DimensionMismatch {
68 expected: (usize, usize),
69 actual: (usize, usize),
70 },
71 NotSquare { nrows: usize, ncols: usize },
73 NotPositiveDefinite,
75 IterativeNotConverged { iterations: usize, residual: f64 },
77 EigenDecompositionFailed,
79 SvdFailed,
81}
82
83impl fmt::Display for LinalgError {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 match self {
86 LinalgError::Singular { step } => {
87 write!(f, "Matrix is singular (detected at step {})", step)
88 }
89 LinalgError::DimensionMismatch { expected, actual } => {
90 write!(
91 f,
92 "Dimension mismatch: expected {:?}, got {:?}",
93 expected, actual
94 )
95 }
96 LinalgError::NotSquare { nrows, ncols } => {
97 write!(f, "Matrix is not square: {}x{}", nrows, ncols)
98 }
99 LinalgError::NotPositiveDefinite => {
100 write!(f, "Matrix is not positive definite")
101 }
102 LinalgError::IterativeNotConverged {
103 iterations,
104 residual,
105 } => {
106 write!(
107 f,
108 "Iterative solver did not converge after {} iterations (residual: {})",
109 iterations, residual
110 )
111 }
112 LinalgError::EigenDecompositionFailed => {
113 write!(f, "Eigenvalue decomposition failed")
114 }
115 LinalgError::SvdFailed => {
116 write!(f, "SVD computation failed")
117 }
118 }
119 }
120}
121
122impl From<LinalgError> for NumraError {
123 fn from(e: LinalgError) -> Self {
124 NumraError::Linalg(e)
125 }
126}
127
128#[derive(Clone, Debug, PartialEq)]
130pub enum ConvergenceError {
131 Newton { iterations: usize, residual: f64 },
133 FixedPoint { iterations: usize, delta: f64 },
135}
136
137impl fmt::Display for ConvergenceError {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 match self {
140 ConvergenceError::Newton {
141 iterations,
142 residual,
143 } => {
144 write!(
145 f,
146 "Newton iteration did not converge after {} iterations (residual: {})",
147 iterations, residual
148 )
149 }
150 ConvergenceError::FixedPoint { iterations, delta } => {
151 write!(
152 f,
153 "Fixed point iteration did not converge after {} iterations (delta: {})",
154 iterations, delta
155 )
156 }
157 }
158 }
159}
160
161impl From<ConvergenceError> for NumraError {
162 fn from(e: ConvergenceError) -> Self {
163 NumraError::Convergence(e)
164 }
165}
166
167#[derive(Clone, Debug, PartialEq)]
169pub enum OptimizationError {
170 LineSearchFailed { iterations: usize, step_size: f64 },
172 NotDescentDirection { directional_derivative: f64 },
174 NotConverged {
176 iterations: usize,
177 gradient_norm: f64,
178 },
179 InvalidFunctionValue { value: f64 },
181}
182
183impl fmt::Display for OptimizationError {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 match self {
186 OptimizationError::LineSearchFailed {
187 iterations,
188 step_size,
189 } => {
190 write!(
191 f,
192 "Line search failed after {} iterations (step size: {})",
193 iterations, step_size
194 )
195 }
196 OptimizationError::NotDescentDirection {
197 directional_derivative,
198 } => {
199 write!(
200 f,
201 "Search direction is not a descent direction (directional derivative: {})",
202 directional_derivative
203 )
204 }
205 OptimizationError::NotConverged {
206 iterations,
207 gradient_norm,
208 } => {
209 write!(
210 f,
211 "Optimization did not converge after {} iterations (gradient norm: {})",
212 iterations, gradient_norm
213 )
214 }
215 OptimizationError::InvalidFunctionValue { value } => {
216 write!(f, "Function evaluation returned invalid value: {}", value)
217 }
218 }
219 }
220}
221
222impl From<OptimizationError> for NumraError {
223 fn from(e: OptimizationError) -> Self {
224 NumraError::Optimization(e)
225 }
226}