1#[cfg(feature = "doc")]
2pub mod doc;
3
4#[cfg(test)]
5mod test;
6
7mod dae;
8mod ode;
9
10pub use dae::{
11 ExplicitDaeFirstOrderMinimize, ExplicitDaeFirstOrderRoot, ExplicitDaeSecondOrderMinimize,
12 ExplicitDaeZerothOrderRoot, ImplicitDaeFirstOrderMinimize, ImplicitDaeFirstOrderRoot,
13 ImplicitDaeSecondOrderMinimize, ImplicitDaeZerothOrderRoot,
14 explicit::variable_step::{
15 explicit::{
16 ExplicitDaeVariableStepExplicit, ExplicitDaeVariableStepExplicitFirstOrderMinimize,
17 ExplicitDaeVariableStepExplicitFirstOrderRoot,
18 ExplicitDaeVariableStepExplicitSecondOrderMinimize,
19 ExplicitDaeVariableStepExplicitZerothOrderRoot, ExplicitDaeVariableStepFirstSameAsLast,
20 },
21 implicit::{
22 ImplicitDaeVariableStepExplicit, ImplicitDaeVariableStepExplicitFirstOrderMinimize,
23 ImplicitDaeVariableStepExplicitFirstOrderRoot,
24 ImplicitDaeVariableStepExplicitSecondOrderMinimize,
25 ImplicitDaeVariableStepExplicitZerothOrderRoot,
26 },
27 },
28};
29pub use ode::{
30 FixedStep, OdeIntegrator, VariableStep,
31 explicit::{
32 Explicit,
33 fixed_step::{
34 FixedStepExplicit, bogacki_shampine::BogackiShampine as BogackiShampineFixedStep,
35 dormand_prince::DormandPrince as DormandPrinceFixedStep, euler::Euler, heun::Heun,
36 midpoint::Midpoint, ralston::Ralston, verner_8::Verner8 as Verner8FixedStep,
37 verner_9::Verner9 as Verner9FixedStep,
38 },
39 variable_step::{
40 VariableStepExplicit,
41 VariableStepExplicitFirstSameAsLast,
42 bogacki_shampine::BogackiShampine,
43 dormand_prince::DormandPrince,
44 verner_8::Verner8,
48 verner_9::Verner9,
49 },
50 },
51 implicit::{
52 ImplicitFirstOrder, ImplicitZerothOrder, backward_euler::BackwardEuler,
53 midpoint::Midpoint as ImplicitMidpoint, trapezoidal::Trapezoidal,
54 },
55};
56
57pub type Ode1 = Euler;
59
60pub type Ode1be = BackwardEuler;
62
63pub type Ode2 = Heun;
68
69pub type Ode23 = BogackiShampine;
71
72pub type Ode3 = BogackiShampineFixedStep;
74
75pub type Ode45 = DormandPrince;
77
78pub type Ode5 = DormandPrinceFixedStep;
80
81pub type Ode78 = Verner8;
83
84pub type Ode8 = Verner8FixedStep;
86
87pub type Ode89 = Verner9;
89
90pub type Ode9 = Verner9FixedStep;
92
93use crate::{
94 defeat_message,
95 math::{Scalar, TestError},
96};
97use std::fmt::{self, Debug, Display, Formatter};
98
99pub enum IntegrationError {
101 InconsistentInitialConditions,
102 InitialTimeNotLessThanFinalTime,
103 Intermediate(String),
104 LengthTimeLessThanTwo,
105 MinimumStepSizeReached(Scalar, String),
106 MinimumStepSizeUpstream(Scalar, String, String),
107 TimeStepNotSet(Scalar, Scalar, String),
108 Upstream(String, String),
109}
110
111impl From<String> for IntegrationError {
112 fn from(error: String) -> Self {
113 Self::Intermediate(error)
114 }
115}
116
117impl Debug for IntegrationError {
118 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
119 let error = match self {
120 Self::InconsistentInitialConditions => {
121 "\x1b[1;91mThe initial condition z_0 is not consistent with g(t_0, y_0)."
122 .to_string()
123 }
124 Self::InitialTimeNotLessThanFinalTime => {
125 "\x1b[1;91mThe initial time must precede the final time.".to_string()
126 }
127 Self::Intermediate(message) => message.to_string(),
128 Self::LengthTimeLessThanTwo => {
129 "\x1b[1;91mThe time must contain at least two entries.".to_string()
130 }
131 Self::MinimumStepSizeReached(dt_min, integrator) => {
132 format!(
133 "\x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
134 In integrator: {integrator}."
135 )
136 }
137 Self::MinimumStepSizeUpstream(dt_min, error, integrator) => {
138 format!(
139 "{error}\x1b[0;91m\n\
140 Causing error: \x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
141 In integrator: {integrator}."
142 )
143 }
144 Self::TimeStepNotSet(t0, tf, integrator) => {
145 format!(
146 "\x1b[1;91mA positive time step must be set within [{t0:?}, {tf:?}].\x1b[0;91m\n\
147 In integrator: {integrator}."
148 )
149 }
150 Self::Upstream(error, integrator) => {
151 format!(
152 "{error}\x1b[0;91m\n\
153 In integrator: {integrator}."
154 )
155 }
156 };
157 write!(f, "\n{}\n\x1b[0;2;31m{}\x1b[0m\n", error, defeat_message())
158 }
159}
160
161impl Display for IntegrationError {
162 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
163 let error = match self {
164 Self::InconsistentInitialConditions => {
165 "\x1b[1;91mThe initial condition z_0 is not consistent with g(t_0, y_0)."
166 .to_string()
167 }
168 Self::InitialTimeNotLessThanFinalTime => {
169 "\x1b[1;91mThe initial time must precede the final time.".to_string()
170 }
171 Self::Intermediate(message) => message.to_string(),
172 Self::LengthTimeLessThanTwo => {
173 "\x1b[1;91mThe time must contain at least two entries.".to_string()
174 }
175 Self::MinimumStepSizeReached(dt_min, integrator) => {
176 format!(
177 "\x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
178 In integrator: {integrator}."
179 )
180 }
181 Self::MinimumStepSizeUpstream(dt_min, error, integrator) => {
182 format!(
183 "{error}\x1b[0;91m\n\
184 Causing error: \x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
185 In integrator: {integrator}."
186 )
187 }
188 Self::TimeStepNotSet(t0, tf, integrator) => {
189 format!(
190 "\x1b[1;91mA positive time step must be set within [{t0:?}, {tf:?}].\x1b[0;91m\n\
191 In integrator: {integrator}."
192 )
193 }
194 Self::Upstream(error, integrator) => {
195 format!(
196 "{error}\x1b[0;91m\n\
197 In integrator: {integrator}."
198 )
199 }
200 };
201 write!(f, "{error}\x1b[0m")
202 }
203}
204
205impl From<IntegrationError> for String {
206 fn from(error: IntegrationError) -> Self {
207 format!("{}", error)
208 }
209}
210
211impl From<IntegrationError> for TestError {
212 fn from(error: IntegrationError) -> Self {
213 TestError {
214 message: error.to_string(),
215 }
216 }
217}