use faer::sparse::CreationError;
use thiserror::Error;
#[derive(Error, Debug, Clone)]
pub enum DiffsolError {
#[error("Linear solver error: {0}")]
LinearSolverError(#[from] LinearSolverError),
#[error("Non-linear solver error: {0}")]
NonLinearSolverError(#[from] NonLinearSolverError),
#[error("ODE solver error: {0}")]
OdeSolverError(#[from] OdeSolverError),
#[error("Matrix error: {0}")]
MatrixError(#[from] MatrixError),
#[cfg(feature = "cuda")]
#[error("Cuda error: {0}")]
VectorError(#[from] CudaError),
#[error("DiffSL Parser error: {0}")]
DiffslParserError(String),
#[error("DiffSL Compiler error: {0}")]
DiffslCompilerError(String),
#[error("Error: {0}")]
Other(String),
}
#[derive(Error, Debug, Clone)]
pub enum LinearSolverError {
#[error("LU not initialized")]
LuNotInitialized,
#[error("LU solve failed")]
LuSolveFailed,
#[error("Linear solver not setup")]
LinearSolverNotSetup,
#[error("Linear solver matrix not square")]
LinearSolverMatrixNotSquare,
#[error("Linear solver matrix not compatible with vector")]
LinearSolverMatrixVectorNotCompatible,
#[error("KLU failed to analyze")]
KluFailedToAnalyze,
#[error("KLU failed to factorize")]
KluFailedToFactorize,
#[error("Error: {0}")]
Other(String),
}
#[derive(Error, Debug, Clone)]
pub enum NonLinearSolverError {
#[error("Initial condition solver did not converge")]
InitialConditionDidNotConverge,
#[error("Newton iterations did not converge, maximum iterations reached")]
NewtonMaxIterations,
#[error("Newton iteration diverged")]
NewtonDiverged,
#[error("Newton linesearch failed to find a suitable step in max iterations")]
LinesearchFailedMaxIterations,
#[error("Newton linesearch failed, minimum step size reached")]
LinesearchFailedMinStep,
#[error("LU solve failed")]
LuSolveFailed,
#[error("Jacobian not reset before calling solve")]
JacobianNotReset,
#[error("State has wrong length: expected {expected}, got {found}")]
WrongStateLength { expected: usize, found: usize },
#[error("Error: {0}")]
Other(String),
}
#[derive(Debug, Error, Clone)]
pub enum OdeSolverError {
#[error(
"Stop time = {} is less than current state time = {}",
stop_time,
state_time
)]
StopTimeBeforeCurrentTime { stop_time: f64, state_time: f64 },
#[error("Mass matrix not supported for this solver")]
MassMatrixNotSupported,
#[error("Stop time is at the current state time")]
StopTimeAtCurrentTime,
#[error("Interpolation vector is not the correct length, expected {expected}, got {found}")]
InterpolationVectorWrongSize { expected: usize, found: usize },
#[error("Number of sensitivities does not match number of parameters")]
SensitivityCountMismatch { expected: usize, found: usize },
#[error("Interpolation time is after current time")]
InterpolationTimeAfterCurrentTime,
#[error("Interpolation time is not within the current step. Step size is zero after calling state_mut()")]
InterpolationTimeOutsideCurrentStep,
#[error("Interpolation time is greater than current time")]
InterpolationTimeGreaterThanCurrentTime,
#[error("State not set")]
StateNotSet,
#[error("Sensitivity solve failed")]
SensitivitySolveFailed,
#[error(
"Exceeded maximum number of nonlinear solver failures ({num_failures}) at time = {time}"
)]
TooManyNonlinearSolverFailures { time: f64, num_failures: usize },
#[error("Exceeded maximum number of error test failures ({num_failures}) at time = {time}")]
TooManyErrorTestFailures { time: f64, num_failures: usize },
#[error("Step size is too small at time = {time}")]
StepSizeTooSmall { time: f64 },
#[error("Sensitivity requested but equations do not support it")]
SensitivityNotSupported,
#[error("A reset operator requires a root operator to propagate sensitivities")]
ResetRequiresRootOperator,
#[error("Failed to get mutable reference to equations. If there is a solver created with this problem, call solver.take_state() to release the problem")]
FailedToGetMutableReference,
#[error("Builder error: {0}")]
BuilderError(String),
#[error("State is not consistent with the problem equations")]
StateProblemMismatch,
#[error("t_eval must be increasing and all values must be greater than or equal to the current time")]
InvalidTEval,
#[error("Sundials error: {0}")]
SundialsError(String),
#[error("Problem not set")]
ProblemNotSet,
#[error("Jacobian not available")]
JacobianNotAvailable,
#[error("Invalid Tableau: {0}")]
InvalidTableau(String),
#[error("Error: {0}")]
Other(String),
}
#[derive(Error, Debug, Clone)]
pub enum MatrixError {
#[error("Failed to create matrix from triplets: {0}")]
FailedToCreateMatrixFromTriplets(#[from] CreationError),
#[error("Cannot union matrices with different shapes")]
UnionIncompatibleShapes,
#[error("Cannot create a matrix with zero rows or columns")]
MatrixShapeError,
#[error("Index out of bounds")]
IndexOutOfBounds,
#[error("Error: {0}")]
Other(String),
}
#[cfg(feature = "cuda")]
#[derive(Error, Debug, Clone)]
pub enum CudaError {
#[error("Failed to allocate memory on GPU")]
CudaMemoryAllocationError,
#[error("Failed to initialize CUDA: {0}")]
CudaInitializationError(String),
#[error("Cuda error: {0}")]
Other(String),
}
#[cfg(feature = "cuda")]
#[macro_export]
macro_rules! cuda_error {
($variant:ident) => {
DiffsolError::from(CudaError::$variant)
};
($variant:ident, $($arg:tt)*) => {
DiffsolError::from(CudaError::$variant($($arg)*))
};
}
#[macro_export]
macro_rules! linear_solver_error {
($variant:ident) => {
DiffsolError::from(LinearSolverError::$variant)
};
($variant:ident, $($arg:tt)*) => {
DiffsolError::from(LinearSolverError::$variant($($arg)*))
};
}
#[macro_export]
macro_rules! non_linear_solver_error {
($variant:ident) => {
DiffsolError::from(NonLinearSolverError::$variant)
};
($variant:ident, $($arg:tt)*) => {
DiffsolError::from(NonLinearSolverError::$variant($($arg)*))
};
}
#[macro_export]
macro_rules! ode_solver_error {
($variant:ident) => {
DiffsolError::from(OdeSolverError::$variant)
};
($variant:ident, $($arg:tt)*) => {
DiffsolError::from(OdeSolverError::$variant($($arg)*.to_string()))
};
}
#[macro_export]
macro_rules! matrix_error {
($variant:ident) => {
DiffsolError::from(MatrixError::$variant)
};
($variant:ident, $($arg:tt)*) => {
DiffsolError::from(MatrixError::$variant($($arg)*))
};
}
#[macro_export]
macro_rules! other_error {
($msg:expr) => {
DiffsolError::Other($msg.to_string())
};
}