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 { t: T, y: Y, 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 { t, y, msg } => write!(
99 f,
100 "Linear algebra error at (t, y) = ({}, {}): {}",
101 t, y, msg
102 ),
103 }
104 }
105}
106
107impl<T, Y> Debug for Error<T, Y>
108where
109 T: Real + Debug,
110 Y: State<T> + Debug,
111{
112 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 match self {
114 Self::BadInput { msg } => write!(
115 f,
116 "Bad input: {}. Check your problem definition, dimensions, and solver options.",
117 msg
118 ),
119 Self::MaxSteps { t, y } => {
120 write!(
121 f,
122 "Maximum step count reached at (t, y) = ({:?}, {:?}). Try increasing max_steps, relaxing tolerances, or shortening the integration interval.",
123 t, y
124 )
125 }
126 Self::StepSize { t, y } => {
127 write!(
128 f,
129 "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.",
130 t, y
131 )
132 }
133 Self::Stiffness { t, y } => {
134 write!(
135 f,
136 "Stiffness detected at (t, y) = ({:?}, {:?}). Switch to a stiff method (e.g., DIRK or IRK) or relax tolerances to improve stability.",
137 t, y
138 )
139 }
140 Self::OutOfBounds {
141 t_interp,
142 t_prev,
143 t_curr,
144 } => {
145 write!(
146 f,
147 "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.",
148 t_interp, t_prev, t_curr
149 )
150 }
151 Self::NoLags => write!(
152 f,
153 "Invalid DDE configuration: number of lags L must be > 0. If there are no delays, use an ODE solver instead."
154 ),
155 Self::InsufficientHistory {
156 t_delayed,
157 t_prev,
158 t_curr,
159 } => {
160 write!(
161 f,
162 "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.",
163 t_delayed, t_prev, t_curr
164 )
165 }
166 Self::LinearAlgebra { t, y, msg } => write!(
167 f,
168 "Linear algebra error at (t, y) = ({:?}, {:?}): {}",
169 t, y, msg
170 ),
171 }
172 }
173}
174
175impl<T, Y> std::error::Error for Error<T, Y>
176where
177 T: Real + Debug + Display,
178 Y: State<T> + Debug + Display,
179{
180}