#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::fmt::{Debug, Display};
use crate::traits::{Real, State};
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(PartialEq, Clone)]
pub enum Error<T, Y>
where
T: Real,
Y: State<T>,
{
BadInput { msg: String },
MaxSteps { t: T, y: Y },
StepSize { t: T, y: Y },
Stiffness { t: T, y: Y },
OutOfBounds { t_interp: T, t_prev: T, t_curr: T },
NoLags,
InsufficientHistory { t_delayed: T, t_prev: T, t_curr: T },
LinearAlgebra { msg: String },
}
impl<T, Y> Display for Error<T, Y>
where
T: Real + Display,
Y: State<T> + Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::BadInput { msg } => write!(
f,
"Bad input: {}. Check your problem definition, dimensions, and solver options.",
msg
),
Self::MaxSteps { t, y } => {
write!(
f,
"Maximum step count reached at (t, y) = ({}, {}). Try increasing max_steps, relaxing tolerances, or shortening the integration interval.",
t, y
)
}
Self::StepSize { t, y } => write!(
f,
"Step size became too small at (t, y) = ({}, {}). This often indicates stiffness or overly tight tolerances. Consider using a stiff solver (DIRK/IRK), relaxing rtol/atol, or rescaling the problem.",
t, y
),
Self::Stiffness { t, y } => write!(
f,
"Stiffness detected at (t, y) = ({}, {}). Switch to a stiff method (e.g., DIRK or IRK) or relax tolerances to improve stability.",
t, y
),
Self::OutOfBounds {
t_interp,
t_prev,
t_curr,
} => {
write!(
f,
"Interpolation error: requested t_interp {} is outside the last step: [t_prev {}, t_curr {}]. Dense output is only valid within a completed step; request t within this interval or use t_eval to sample during integration.",
t_interp, t_prev, t_curr
)
}
Self::NoLags => write!(
f,
"Invalid DDE configuration: number of lags L must be > 0. If there are no delays, use an ODE solver instead."
),
Self::InsufficientHistory {
t_delayed,
t_prev,
t_curr,
} => {
write!(
f,
"Insufficient history to interpolate at delayed time {} (window: [t_prev {}, t_curr {}]). Possible causes: max_delay is too small or history pruning is too aggressive, or steps advanced before enough history accumulated. Consider increasing max_delay, providing a longer initial history, or reducing maximum step size.",
t_delayed, t_prev, t_curr
)
}
Self::LinearAlgebra { msg } => write!(f, "Linear algebra error: {}", msg),
}
}
}
impl<T, Y> Debug for Error<T, Y>
where
T: Real + Debug,
Y: State<T> + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::BadInput { msg } => write!(
f,
"Bad input: {}. Check your problem definition, dimensions, and solver options.",
msg
),
Self::MaxSteps { t, y } => {
write!(
f,
"Maximum step count reached at (t, y) = ({:?}, {:?}). Try increasing max_steps, relaxing tolerances, or shortening the integration interval.",
t, y
)
}
Self::StepSize { t, y } => {
write!(
f,
"Step size became too small at (t, y) = ({:?}, {:?}). This often indicates stiffness or overly tight tolerances. Consider using a stiff solver (DIRK/IRK), relaxing rtol/atol, or rescaling the problem.",
t, y
)
}
Self::Stiffness { t, y } => {
write!(
f,
"Stiffness detected at (t, y) = ({:?}, {:?}). Switch to a stiff method (e.g., DIRK or IRK) or relax tolerances to improve stability.",
t, y
)
}
Self::OutOfBounds {
t_interp,
t_prev,
t_curr,
} => {
write!(
f,
"Interpolation error: requested t_interp {:?} is outside the last step: [t_prev {:?}, t_curr {:?}]. Dense output is only valid within a completed step; request t within this interval or use t_eval to sample during integration.",
t_interp, t_prev, t_curr
)
}
Self::NoLags => write!(
f,
"Invalid DDE configuration: number of lags L must be > 0. If there are no delays, use an ODE solver instead."
),
Self::InsufficientHistory {
t_delayed,
t_prev,
t_curr,
} => {
write!(
f,
"Insufficient history to interpolate at delayed time {:?} (window: [t_prev {:?}, t_curr {:?}]). Possible causes: max_delay is too small or history pruning is too aggressive, or steps advanced before enough history accumulated. Consider increasing max_delay, providing a longer initial history, or reducing maximum step size.",
t_delayed, t_prev, t_curr
)
}
Self::LinearAlgebra { msg } => write!(f, "Linear algebra error: {}", msg),
}
}
}
impl<T, Y> std::error::Error for Error<T, Y>
where
T: Real + Debug + Display,
Y: State<T> + Debug + Display,
{
}