1use crate::math::{
2 Banded, Scalar, Tensor, TensorVec, Vector,
3 integrate::{
4 ImplicitDaeFirstOrderMinimize, ImplicitDaeFirstOrderRoot, ImplicitDaeSecondOrderMinimize,
5 ImplicitDaeZerothOrderRoot, IntegrationError, VariableStepExplicit,
6 },
7 optimize::{
8 EqualityConstraint, FirstOrderOptimization, FirstOrderRootFinding, SecondOrderOptimization,
9 ZerothOrderRootFinding,
10 },
11};
12use std::ops::{Mul, Sub};
13
14pub trait ImplicitDaeVariableStepExplicit<Y, U>
16where
17 Self: VariableStepExplicit<Y, U>,
18 Y: Tensor,
19 U: TensorVec<Item = Y>,
20 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
21{
22 fn integrate_implicit_dae_variable_step(
23 &self,
24 mut evolution: impl FnMut(Scalar, &Y, &Y) -> Result<Y, String>,
25 time: &[Scalar],
26 initial_condition: Y,
27 ) -> Result<(Vector, U, U), IntegrationError> {
28 let t_0 = time[0];
29 let t_f = time[time.len() - 1];
30 if time.len() < 2 {
31 return Err(IntegrationError::LengthTimeLessThanTwo);
32 } else if t_0 >= t_f {
33 return Err(IntegrationError::InitialTimeNotLessThanFinalTime);
34 }
35 let mut t = t_0;
36 let mut dt = t_f - t_0;
37 let mut t_sol = Vector::new();
38 t_sol.push(t_0);
39 let mut dydt = &initial_condition * 0.0;
40 let mut y = initial_condition;
41 let mut k = vec![Y::default(); Self::SLOPES];
42 k[0] = evolution(t, &y, &dydt)?;
43 let mut y_sol = U::new();
44 y_sol.push(y.clone());
45 let mut dydt_sol = U::new();
46 dydt_sol.push(k[0].clone());
47 let mut y_trial = Y::default();
48 while t < t_f {
49 match self.slopes_and_error(
50 |t: Scalar, y: &Y| evolution(t, y, &dydt),
51 &y,
52 t,
53 dt,
54 &mut k,
55 &mut y_trial,
56 ) {
57 Ok(e) => {
58 if let Some(error) = self
59 .step(
60 |t: Scalar, y: &Y| evolution(t, y, &dydt),
61 &mut y,
62 &mut t,
63 &mut y_sol,
64 &mut t_sol,
65 &mut dydt_sol,
66 &mut dt,
67 &mut k,
68 &y_trial,
69 e,
70 )
71 .err()
72 {
73 dt *= self.dt_cut();
74 if dt < self.dt_min() {
75 return Err(IntegrationError::MinimumStepSizeUpstream(
76 self.dt_min(),
77 error,
78 format!("{:?}", self),
79 ));
80 }
81 } else {
82 dydt = k[0].clone();
83 dt = dt.min(t_f - t);
84 if dt < self.dt_min() && t < t_f {
85 return Err(IntegrationError::MinimumStepSizeReached(
86 self.dt_min(),
87 format!("{:?}", self),
88 ));
89 }
90 }
91 }
92 Err(error) => {
93 dt *= self.dt_cut();
94 if dt < self.dt_min() {
95 return Err(IntegrationError::MinimumStepSizeUpstream(
96 self.dt_min(),
97 error,
98 format!("{:?}", self),
99 ));
100 }
101 }
102 }
103 }
104 if time.len() > 2 {
105 let t_int = Vector::from(time);
106 let (y_int, dydt_int) = self.interpolate_implicit_dae_variable_step(
107 evolution, &t_int, &t_sol, &y_sol, &dydt_sol,
108 )?;
109 Ok((t_int, y_int, dydt_int))
110 } else {
111 Ok((t_sol, y_sol, dydt_sol))
112 }
113 }
114 fn interpolate_implicit_dae_variable_step(
115 &self,
116 mut evolution: impl FnMut(Scalar, &Y, &Y) -> Result<Y, String>,
117 time: &Vector,
118 tp: &Vector,
119 yp: &U,
120 dydtp: &U,
121 ) -> Result<(U, U), IntegrationError> {
122 let mut dt;
123 let mut i;
124 let mut k = vec![Y::default(); Self::SLOPES];
125 let mut t;
126 let mut y;
127 let mut dydt;
128 let mut y_int = U::new();
129 let mut dydt_int = U::new();
130 let mut y_trial = Y::default();
131 for time_k in time.iter() {
132 i = tp.iter().position(|tp_i| tp_i >= time_k).unwrap();
133 if time_k == &tp[i] {
134 t = tp[i];
135 y_trial = yp[i].clone();
136 dt = 0.0;
137 } else {
138 t = tp[i - 1];
139 y = &yp[i - 1];
140 dydt = &dydtp[i - 1];
141 dt = time_k - t;
142 k[0] = evolution(t, y, dydt)?;
143 Self::slopes(
144 |t: Scalar, y: &Y| evolution(t, y, dydt),
145 y,
146 t,
147 dt,
148 &mut k,
149 &mut y_trial,
150 )?;
151 }
152 dydt_int.push(evolution(t + dt, &y_trial, &k[0])?);
153 y_int.push(y_trial.clone());
154 }
155 Ok((y_int, dydt_int))
156 }
157}
158
159impl<I, Y, U> ImplicitDaeVariableStepExplicit<Y, U> for I
160where
161 Self: VariableStepExplicit<Y, U>,
162 Y: Tensor,
163 U: TensorVec<Item = Y>,
164 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
165{
166}
167
168pub trait ImplicitDaeVariableStepExplicitZerothOrderRoot<Y, U>
170where
171 Self: ImplicitDaeVariableStepExplicit<Y, U>,
172 Y: Tensor,
173 U: TensorVec<Item = Y>,
174 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
175{
176 fn integrate_implicit_dae_variable_step_explicit_root_0(
177 &self,
178 mut function: impl FnMut(Scalar, &Y, &Y) -> Result<Y, String>,
179 solver: impl ZerothOrderRootFinding<Y>,
180 time: &[Scalar],
181 initial_condition: Y,
182 mut equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
183 ) -> Result<(Vector, U, U), IntegrationError> {
184 let evolution = |t: Scalar, y: &Y, dydt_0: &Y| -> Result<Y, String> {
185 Ok(solver.root(
186 |dydt| function(t, y, dydt),
187 dydt_0.clone(),
188 equality_constraint(t),
189 )?)
190 };
191 self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
192 }
193}
194
195impl<I, Y, U> ImplicitDaeVariableStepExplicitZerothOrderRoot<Y, U> for I
196where
197 I: ImplicitDaeVariableStepExplicit<Y, U>,
198 Y: Tensor,
199 U: TensorVec<Item = Y>,
200 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
201{
202}
203
204impl<I, Y, U> ImplicitDaeZerothOrderRoot<Y, U> for I
205where
206 Self: ImplicitDaeVariableStepExplicitZerothOrderRoot<Y, U>,
207 Y: Tensor,
208 U: TensorVec<Item = Y>,
209 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
210{
211 fn integrate(
212 &self,
213 function: impl FnMut(Scalar, &Y, &Y) -> Result<Y, String>,
214 solver: impl ZerothOrderRootFinding<Y>,
215 time: &[Scalar],
216 initial_condition: Y,
217 equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
218 ) -> Result<(Vector, U, U), IntegrationError> {
219 self.integrate_implicit_dae_variable_step_explicit_root_0(
220 function,
221 solver,
222 time,
223 initial_condition,
224 equality_constraint,
225 )
226 }
227}
228
229pub trait ImplicitDaeVariableStepExplicitFirstOrderRoot<F, J, Y, U>
231where
232 Self: ImplicitDaeVariableStepExplicit<Y, U>,
233 Y: Tensor,
234 U: TensorVec<Item = Y>,
235 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
236{
237 fn integrate_implicit_dae_variable_step_explicit_root_1(
238 &self,
239 mut function: impl FnMut(Scalar, &Y, &Y) -> Result<F, String>,
240 mut jacobian: impl FnMut(Scalar, &Y, &Y) -> Result<J, String>,
241 solver: impl FirstOrderRootFinding<F, J, Y>,
242 time: &[Scalar],
243 initial_condition: Y,
244 mut equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
245 ) -> Result<(Vector, U, U), IntegrationError> {
246 let evolution = |t: Scalar, y: &Y, dydt_0: &Y| -> Result<Y, String> {
247 Ok(solver.root(
248 |dydt| function(t, y, dydt),
249 |dydt| jacobian(t, y, dydt),
250 dydt_0.clone(),
251 equality_constraint(t),
252 )?)
253 };
254 self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
255 }
256}
257
258impl<I, F, J, Y, U> ImplicitDaeVariableStepExplicitFirstOrderRoot<F, J, Y, U> for I
259where
260 I: ImplicitDaeVariableStepExplicit<Y, U>,
261 Y: Tensor,
262 U: TensorVec<Item = Y>,
263 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
264{
265}
266
267impl<I, F, J, Y, U> ImplicitDaeFirstOrderRoot<F, J, Y, U> for I
268where
269 Self: ImplicitDaeVariableStepExplicitFirstOrderRoot<F, J, Y, U>,
270 Y: Tensor,
271 U: TensorVec<Item = Y>,
272 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
273{
274 fn integrate(
275 &self,
276 function: impl FnMut(Scalar, &Y, &Y) -> Result<F, String>,
277 jacobian: impl FnMut(Scalar, &Y, &Y) -> Result<J, String>,
278 solver: impl FirstOrderRootFinding<F, J, Y>,
279 time: &[Scalar],
280 initial_condition: Y,
281 equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
282 ) -> Result<(Vector, U, U), IntegrationError> {
283 self.integrate_implicit_dae_variable_step_explicit_root_1(
284 function,
285 jacobian,
286 solver,
287 time,
288 initial_condition,
289 equality_constraint,
290 )
291 }
292}
293
294pub trait ImplicitDaeVariableStepExplicitFirstOrderMinimize<F, Y, U>
296where
297 Self: ImplicitDaeVariableStepExplicit<Y, U>,
298 Y: Tensor,
299 U: TensorVec<Item = Y>,
300 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
301{
302 #[allow(clippy::too_many_arguments)]
303 fn integrate_implicit_dae_variable_step_explicit_minimize_1(
304 &self,
305 mut function: impl FnMut(Scalar, &Y, &Y) -> Result<F, String>,
306 mut jacobian: impl FnMut(Scalar, &Y, &Y) -> Result<Y, String>,
307 solver: impl FirstOrderOptimization<F, Y>,
308 time: &[Scalar],
309 initial_condition: Y,
310 mut equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
311 ) -> Result<(Vector, U, U), IntegrationError> {
312 let evolution = |t: Scalar, y: &Y, dydt_0: &Y| -> Result<Y, String> {
313 Ok(solver.minimize(
314 |dydt| function(t, y, dydt),
315 |dydt| jacobian(t, y, dydt),
316 dydt_0.clone(),
317 equality_constraint(t),
318 )?)
319 };
320 self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
321 }
322}
323
324impl<I, F, Y, U> ImplicitDaeVariableStepExplicitFirstOrderMinimize<F, Y, U> for I
325where
326 I: ImplicitDaeVariableStepExplicit<Y, U>,
327 Y: Tensor,
328 U: TensorVec<Item = Y>,
329 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
330{
331}
332
333impl<I, F, Y, U> ImplicitDaeFirstOrderMinimize<F, Y, U> for I
334where
335 Self: ImplicitDaeVariableStepExplicitFirstOrderMinimize<F, Y, U>,
336 Y: Tensor,
337 U: TensorVec<Item = Y>,
338 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
339{
340 fn integrate(
341 &self,
342 function: impl FnMut(Scalar, &Y, &Y) -> Result<F, String>,
343 jacobian: impl FnMut(Scalar, &Y, &Y) -> Result<Y, String>,
344 solver: impl FirstOrderOptimization<F, Y>,
345 time: &[Scalar],
346 initial_condition: Y,
347 equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
348 ) -> Result<(Vector, U, U), IntegrationError> {
349 self.integrate_implicit_dae_variable_step_explicit_minimize_1(
350 function,
351 jacobian,
352 solver,
353 time,
354 initial_condition,
355 equality_constraint,
356 )
357 }
358}
359
360pub trait ImplicitDaeVariableStepExplicitSecondOrderMinimize<F, J, H, Y, U>
362where
363 Self: ImplicitDaeVariableStepExplicit<Y, U>,
364 Y: Tensor,
365 U: TensorVec<Item = Y>,
366 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
367{
368 #[allow(clippy::too_many_arguments)]
369 fn integrate_implicit_dae_variable_step_explicit_minimize_2(
370 &self,
371 mut function: impl FnMut(Scalar, &Y, &Y) -> Result<F, String>,
372 mut jacobian: impl FnMut(Scalar, &Y, &Y) -> Result<J, String>,
373 mut hessian: impl FnMut(Scalar, &Y, &Y) -> Result<H, String>,
374 solver: impl SecondOrderOptimization<F, J, H, Y>,
375 time: &[Scalar],
376 initial_condition: Y,
377 mut equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
378 banded: Option<Banded>,
379 ) -> Result<(Vector, U, U), IntegrationError> {
380 let evolution = |t: Scalar, y: &Y, dydt_0: &Y| -> Result<Y, String> {
381 Ok(solver.minimize(
382 |dydt| function(t, y, dydt),
383 |dydt| jacobian(t, y, dydt),
384 |dydt| hessian(t, y, dydt),
385 dydt_0.clone(),
386 equality_constraint(t),
387 banded.clone(),
388 )?)
389 };
390 self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
391 }
392}
393
394impl<I, F, J, H, Y, U> ImplicitDaeVariableStepExplicitSecondOrderMinimize<F, J, H, Y, U> for I
395where
396 I: ImplicitDaeVariableStepExplicit<Y, U>,
397 Y: Tensor,
398 U: TensorVec<Item = Y>,
399 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
400{
401}
402
403impl<I, F, J, H, Y, U> ImplicitDaeSecondOrderMinimize<F, J, H, Y, U> for I
404where
405 Self: ImplicitDaeVariableStepExplicitSecondOrderMinimize<F, J, H, Y, U>,
406 Y: Tensor,
407 U: TensorVec<Item = Y>,
408 for<'a> &'a Y: Mul<Scalar, Output = Y> + Sub<&'a Y, Output = Y>,
409{
410 fn integrate(
411 &self,
412 function: impl FnMut(Scalar, &Y, &Y) -> Result<F, String>,
413 jacobian: impl FnMut(Scalar, &Y, &Y) -> Result<J, String>,
414 hessian: impl FnMut(Scalar, &Y, &Y) -> Result<H, String>,
415 solver: impl SecondOrderOptimization<F, J, H, Y>,
416 time: &[Scalar],
417 initial_condition: Y,
418 equality_constraint: impl FnMut(Scalar) -> EqualityConstraint,
419 banded: Option<Banded>,
420 ) -> Result<(Vector, U, U), IntegrationError> {
421 self.integrate_implicit_dae_variable_step_explicit_minimize_2(
422 function,
423 jacobian,
424 hessian,
425 solver,
426 time,
427 initial_condition,
428 equality_constraint,
429 banded,
430 )
431 }
432}