differential_equations/
error.rs

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