1#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use std::fmt::{Debug, Display};
7
8use crate::traits::{Real, State};
9
10#[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 BadInput { msg: String },
20
21 MaxSteps { t: T, y: Y },
23
24 StepSize { t: T, y: Y },
26
27 Stiffness { t: T, y: Y },
29
30 OutOfBounds { t_interp: T, t_prev: T, t_curr: T },
32
33 NoLags,
35
36 InsufficientHistory { t_delayed: T, t_prev: T, t_curr: T },
38
39 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}