differential_equations/
error.rs

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