1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
use std::error::Error;
use std::fmt::{Display, Formatter};
/// Describes why the nonlinear solve stopped.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TerminationReason {
/// The residual or method-specific convergence check succeeded.
Converged,
/// The maximum number of outer iterations was reached.
MaxIterations,
/// The trial step became too small to make progress.
StepTooSmall,
/// The method stopped because progress stalled.
Stagnation,
/// Too many trial steps were rejected.
RejectedStepLimit,
}
/// Errors returned by the nonlinear solver pipeline.
#[derive(Debug, Clone, PartialEq)]
pub enum SolveError {
/// A vector or matrix has an unexpected dimension.
DimensionMismatch {
/// Expected dimension.
expected: usize,
/// Actual dimension.
actual: usize,
/// Short description of the failing context.
context: &'static str,
},
/// Solver configuration is invalid.
InvalidConfig(String),
/// The declared symbolic parameter schema is invalid.
InvalidParameterSchema(String),
/// Parameter values were created for a different ordered schema.
ParameterSchemaMismatch(String),
/// The declared symbolic variable schema is invalid.
InvalidVariableSchema(String),
/// An equation references a symbol absent from the declared schema.
UndeclaredSymbol {
/// Zero-based equation index.
equation_index: usize,
/// Referenced symbol name.
name: String,
},
/// A parameter value is not finite.
NonFiniteParameterValue {
/// Index of the invalid parameter.
index: usize,
/// Invalid value.
value: f64,
},
/// Initial point violates the provided bounds.
InfeasibleInitialGuess {
/// Index of the offending variable.
index: usize,
/// Current variable value.
value: f64,
/// Lower bound.
lower: f64,
/// Upper bound.
upper: f64,
},
/// An initial unknown value is NaN or infinite.
NonFiniteInitialGuess {
/// Index of the invalid variable.
index: usize,
/// Invalid value.
value: f64,
},
/// Residual evaluation failed.
ResidualEvaluation(String),
/// Jacobian evaluation failed.
JacobianEvaluation(String),
/// Compiled AOT artifact was selected, but no linked in-process runtime was available.
CompiledAotRuntimeUnavailable(String),
/// A compiled AOT artifact was required, but no registered artifact exists.
CompiledAotArtifactMissing(String),
/// A generated AOT crate is known, but the compiled artifact is not built yet.
CompiledAotArtifactNotBuilt(String),
/// Automatic AOT build was requested without an output directory.
AotBuildOutputDirMissing,
/// Automatic AOT build failed.
AotBuildFailed(String),
/// Linear system solve failed.
LinearSolveFailure(String),
/// Jacobian is singular or too ill-conditioned.
SingularJacobian,
/// Numerical breakdown such as NaN or Inf.
NumericalBreakdown(String),
}
impl Display for SolveError {
/// Formats a human-readable error message.
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SolveError::DimensionMismatch {
expected,
actual,
context,
} => {
write!(
f,
"dimension mismatch in {context}: expected {expected}, got {actual}"
)
}
SolveError::InvalidConfig(msg) => write!(f, "invalid solver configuration: {msg}"),
SolveError::InvalidParameterSchema(msg) => {
write!(f, "invalid nonlinear parameter schema: {msg}")
}
SolveError::ParameterSchemaMismatch(msg) => {
write!(f, "nonlinear parameter schema mismatch: {msg}")
}
SolveError::InvalidVariableSchema(msg) => {
write!(f, "invalid nonlinear variable schema: {msg}")
}
SolveError::UndeclaredSymbol {
equation_index,
name,
} => write!(
f,
"equation {equation_index} references undeclared symbol '{name}'"
),
SolveError::NonFiniteParameterValue { index, value } => {
write!(
f,
"non-finite nonlinear parameter at index {index}: {value}"
)
}
SolveError::InfeasibleInitialGuess {
index,
value,
lower,
upper,
} => write!(
f,
"initial guess at index {index} = {value} violates bounds [{lower}, {upper}]"
),
SolveError::NonFiniteInitialGuess { index, value } => {
write!(f, "non-finite initial guess at index {index}: {value}")
}
SolveError::ResidualEvaluation(msg) => write!(f, "residual evaluation failed: {msg}"),
SolveError::JacobianEvaluation(msg) => write!(f, "jacobian evaluation failed: {msg}"),
SolveError::CompiledAotRuntimeUnavailable(msg) => {
write!(f, "compiled AOT runtime unavailable: {msg}")
}
SolveError::CompiledAotArtifactMissing(msg) => {
write!(f, "compiled AOT artifact missing: {msg}")
}
SolveError::CompiledAotArtifactNotBuilt(msg) => {
write!(f, "compiled AOT artifact not built: {msg}")
}
SolveError::AotBuildOutputDirMissing => {
write!(
f,
"automatic AOT build requested without an output directory"
)
}
SolveError::AotBuildFailed(msg) => write!(f, "automatic AOT build failed: {msg}"),
SolveError::LinearSolveFailure(msg) => write!(f, "linear solve failed: {msg}"),
SolveError::SingularJacobian => write!(f, "jacobian is singular or ill-conditioned"),
SolveError::NumericalBreakdown(msg) => write!(f, "numerical breakdown: {msg}"),
}
}
}
impl Error for SolveError {}