differential_equations/
error.rs

1//! Errors for Differential Equations Crate
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use std::fmt::{Debug, Display};
7
8use crate::traits::{Real, State};
9
10/// Error for Differential Equations Crate
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[derive(PartialEq, Clone)]
13pub enum Error<T, Y>
14where
15    T: Real,
16    Y: State<T>,
17{
18    /// NumericalMethod input was bad
19    BadInput { msg: String },
20
21    /// Maximum steps reached
22    MaxSteps { t: T, y: Y },
23
24    /// Step size became too small
25    StepSize { t: T, y: Y },
26
27    /// Stiffness detected
28    Stiffness { t: T, y: Y },
29
30    /// Out of bounds error
31    OutOfBounds { t_interp: T, t_prev: T, t_curr: T },
32
33    /// DDE requires at least one lag (L > 0)
34    NoLags,
35
36    /// Not enough history retained to evaluate a delayed state
37    InsufficientHistory { t_delayed: T, t_prev: T, t_curr: T },
38
39    /// General linear algebra error
40    LinearAlgebra { msg: String },
41}
42
43impl<T, Y> Display for Error<T, Y>
44where
45    T: Real + Display,
46    Y: State<T> + Display,
47{
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        match self {
50            Self::BadInput { msg } => write!(
51                f,
52                "Bad input: {}. Check your problem definition, dimensions, and solver options.",
53                msg
54            ),
55            Self::MaxSteps { t, y } => {
56                write!(
57                    f,
58                    "Maximum step count reached at (t, y) = ({}, {}). Try increasing max_steps, relaxing tolerances, or shortening the integration interval.",
59                    t, y
60                )
61            }
62            Self::StepSize { t, y } => write!(
63                f,
64                "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.",
65                t, y
66            ),
67            Self::Stiffness { t, y } => write!(
68                f,
69                "Stiffness detected at (t, y) = ({}, {}). Switch to a stiff method (e.g., DIRK or IRK) or relax tolerances to improve stability.",
70                t, y
71            ),
72            Self::OutOfBounds {
73                t_interp,
74                t_prev,
75                t_curr,
76            } => {
77                write!(
78                    f,
79                    "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.",
80                    t_interp, t_prev, t_curr
81                )
82            }
83            Self::NoLags => write!(
84                f,
85                "Invalid DDE configuration: number of lags L must be > 0. If there are no delays, use an ODE solver instead."
86            ),
87            Self::InsufficientHistory {
88                t_delayed,
89                t_prev,
90                t_curr,
91            } => {
92                write!(
93                    f,
94                    "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.",
95                    t_delayed, t_prev, t_curr
96                )
97            }
98            Self::LinearAlgebra { msg } => write!(f, "Linear algebra error: {}", msg),
99        }
100    }
101}
102
103impl<T, Y> Debug for Error<T, Y>
104where
105    T: Real + Debug,
106    Y: State<T> + Debug,
107{
108    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109        match self {
110            Self::BadInput { msg } => write!(
111                f,
112                "Bad input: {}. Check your problem definition, dimensions, and solver options.",
113                msg
114            ),
115            Self::MaxSteps { t, y } => {
116                write!(
117                    f,
118                    "Maximum step count reached at (t, y) = ({:?}, {:?}). Try increasing max_steps, relaxing tolerances, or shortening the integration interval.",
119                    t, y
120                )
121            }
122            Self::StepSize { t, y } => {
123                write!(
124                    f,
125                    "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.",
126                    t, y
127                )
128            }
129            Self::Stiffness { t, y } => {
130                write!(
131                    f,
132                    "Stiffness detected at (t, y) = ({:?}, {:?}). Switch to a stiff method (e.g., DIRK or IRK) or relax tolerances to improve stability.",
133                    t, y
134                )
135            }
136            Self::OutOfBounds {
137                t_interp,
138                t_prev,
139                t_curr,
140            } => {
141                write!(
142                    f,
143                    "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.",
144                    t_interp, t_prev, t_curr
145                )
146            }
147            Self::NoLags => write!(
148                f,
149                "Invalid DDE configuration: number of lags L must be > 0. If there are no delays, use an ODE solver instead."
150            ),
151            Self::InsufficientHistory {
152                t_delayed,
153                t_prev,
154                t_curr,
155            } => {
156                write!(
157                    f,
158                    "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.",
159                    t_delayed, t_prev, t_curr
160                )
161            }
162            Self::LinearAlgebra { msg } => write!(f, "Linear algebra error: {}", msg),
163        }
164    }
165}
166
167impl<T, Y> std::error::Error for Error<T, Y>
168where
169    T: Real + Debug + Display,
170    Y: State<T> + Debug + Display,
171{
172}