conspire/math/integrate/
mod.rs1#[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 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
41pub type Ode1 = Euler;
43
44pub type Ode1be = BackwardEuler;
46
47pub type Ode2 = Heun;
52
53pub type Ode23 = BogackiShampine;
55
56pub type Ode3 = BogackiShampineFixedStep;
58
59pub type Ode45 = DormandPrince;
61
62pub type Ode5 = DormandPrinceFixedStep;
64
65pub type Ode78 = Verner8;
67
68pub type Ode89 = Verner9;
70
71use crate::{
72 defeat_message,
73 math::{Scalar, TestError},
74};
75use std::fmt::{self, Debug, Display, Formatter};
76
77pub 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}