conspire/math/integrate/
mod.rs

1#[cfg(feature = "doc")]
2pub mod doc;
3
4#[cfg(test)]
5mod test;
6
7mod ode;
8
9pub use ode::{
10    FixedStep, OdeSolver, VariableStep,
11    explicit::{
12        Explicit,
13        fixed_step::{
14            FixedStepExplicit, bogacki_shampine::BogackiShampine as BogackiShampineFixedStep,
15            dormand_prince::DormandPrince as DormandPrinceFixedStep, euler::Euler, heun::Heun,
16            midpoint::Midpoint, ralston::Ralston,
17        },
18        internal_variables::ExplicitInternalVariables,
19        variable_step::{
20            VariableStepExplicit,
21            VariableStepExplicitFirstSameAsLast,
22            bogacki_shampine::BogackiShampine,
23            dormand_prince::DormandPrince,
24            internal_variables::{
25                VariableStepExplicitInternalVariables,
26                VariableStepExplicitInternalVariablesFirstSameAsLast,
27            },
28            // heun_euler::HeunEuler,
29            // midpoint_euler::MidpointEuler,
30            // ralston_euler::RalstonEuler,
31            verner_8::Verner8,
32            verner_9::Verner9,
33        },
34    },
35    implicit::{
36        ImplicitFirstOrder, ImplicitZerothOrder, backward_euler::BackwardEuler,
37        midpoint::Midpoint as ImplicitMidpoint, trapezoidal::Trapezoidal,
38    },
39};
40
41/// Alias for [`Euler`].
42pub type Ode1 = Euler;
43
44/// Alias for [`BackwardEuler`].
45pub type Ode1be = BackwardEuler;
46
47// /// Alias for [`HeunEuler`].
48// pub type Ode12 = HeunEuler;
49
50/// Alias for [`Heun`].
51pub type Ode2 = Heun;
52
53/// Alias for [`BogackiShampine`].
54pub type Ode23 = BogackiShampine;
55
56/// Alias for [`BogackiShampineFixedStep`].
57pub type Ode3 = BogackiShampineFixedStep;
58
59/// Alias for [`DormandPrince`].
60pub type Ode45 = DormandPrince;
61
62/// Alias for [`DormandPrinceFixedStep`].
63pub type Ode5 = DormandPrinceFixedStep;
64
65/// Alias for [`Verner8`].
66pub type Ode78 = Verner8;
67
68/// Alias for [`Verner9`].
69pub type Ode89 = Verner9;
70
71use crate::{
72    defeat_message,
73    math::{Scalar, TestError},
74};
75use std::fmt::{self, Debug, Display, Formatter};
76
77/// Possible errors encountered when integrating.
78pub enum IntegrationError {
79    InconsistentInitialConditions,
80    InitialTimeNotLessThanFinalTime,
81    Intermediate(String),
82    LengthTimeLessThanTwo,
83    MinimumStepSizeReached(Scalar, String),
84    MinimumStepSizeUpstream(Scalar, String, String),
85    TimeStepNotSet(Scalar, Scalar, String),
86    Upstream(String, String),
87}
88
89impl From<String> for IntegrationError {
90    fn from(error: String) -> Self {
91        Self::Intermediate(error)
92    }
93}
94
95impl Debug for IntegrationError {
96    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
97        let error = match self {
98            Self::InconsistentInitialConditions => {
99                "\x1b[1;91mThe initial condition z_0 is not consistent with g(t_0, y_0)."
100                    .to_string()
101            }
102            Self::InitialTimeNotLessThanFinalTime => {
103                "\x1b[1;91mThe initial time must precede the final time.".to_string()
104            }
105            Self::Intermediate(message) => message.to_string(),
106            Self::LengthTimeLessThanTwo => {
107                "\x1b[1;91mThe time must contain at least two entries.".to_string()
108            }
109            Self::MinimumStepSizeReached(dt_min, integrator) => {
110                format!(
111                    "\x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
112                    In integrator: {integrator}."
113                )
114            }
115            Self::MinimumStepSizeUpstream(dt_min, error, integrator) => {
116                format!(
117                    "{error}\x1b[0;91m\n\
118                    Causing error: \x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
119                    In integrator: {integrator}."
120                )
121            }
122            Self::TimeStepNotSet(t0, tf, integrator) => {
123                format!(
124                    "\x1b[1;91mA positive time step must be set within [{t0:?}, {tf:?}].\x1b[0;91m\n\
125                    In integrator: {integrator}."
126                )
127            }
128            Self::Upstream(error, integrator) => {
129                format!(
130                    "{error}\x1b[0;91m\n\
131                    In integrator: {integrator}."
132                )
133            }
134        };
135        write!(f, "\n{}\n\x1b[0;2;31m{}\x1b[0m\n", error, defeat_message())
136    }
137}
138
139impl Display for IntegrationError {
140    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
141        let error = match self {
142            Self::InconsistentInitialConditions => {
143                "\x1b[1;91mThe initial condition z_0 is not consistent with g(t_0, y_0)."
144                    .to_string()
145            }
146            Self::InitialTimeNotLessThanFinalTime => {
147                "\x1b[1;91mThe initial time must precede the final time.".to_string()
148            }
149            Self::Intermediate(message) => message.to_string(),
150            Self::LengthTimeLessThanTwo => {
151                "\x1b[1;91mThe time must contain at least two entries.".to_string()
152            }
153            Self::MinimumStepSizeReached(dt_min, integrator) => {
154                format!(
155                    "\x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
156                    In integrator: {integrator}."
157                )
158            }
159            Self::MinimumStepSizeUpstream(dt_min, error, integrator) => {
160                format!(
161                    "{error}\x1b[0;91m\n\
162                    Causing error: \x1b[1;91mMinimum time step ({dt_min:?}) reached.\x1b[0;91m\n\
163                    In integrator: {integrator}."
164                )
165            }
166            Self::TimeStepNotSet(t0, tf, integrator) => {
167                format!(
168                    "\x1b[1;91mA positive time step must be set within [{t0:?}, {tf:?}].\x1b[0;91m\n\
169                    In integrator: {integrator}."
170                )
171            }
172            Self::Upstream(error, integrator) => {
173                format!(
174                    "{error}\x1b[0;91m\n\
175                    In integrator: {integrator}."
176                )
177            }
178        };
179        write!(f, "{error}\x1b[0m")
180    }
181}
182
183impl From<IntegrationError> for String {
184    fn from(error: IntegrationError) -> Self {
185        format!("{}", error)
186    }
187}
188
189impl From<IntegrationError> for TestError {
190    fn from(error: IntegrationError) -> Self {
191        TestError {
192            message: error.to_string(),
193        }
194    }
195}