Skip to main content

conspire/math/integrate/dae/explicit/variable_step/implicit/
mod.rs

1use crate::{
2    math::{
3        Derivative, Differentiate, Quantity, Scalar, Tensor, TensorVec,
4        integrate::{
5            ImplicitDaeFirstOrderMinimize, ImplicitDaeFirstOrderRoot,
6            ImplicitDaeSecondOrderMinimize, ImplicitDaeZerothOrderRoot, IntegrationError, Times,
7            VariableStepExplicit,
8        },
9        optimize::{
10            EqualityConstraint, FirstOrderOptimization, FirstOrderRootFinding,
11            SecondOrderOptimization, ZerothOrderRootFinding,
12        },
13        sparse::SparseSolver,
14    },
15    units::{Time, UnitInv},
16};
17use std::ops::{Mul, Sub};
18
19/// Variable-step explicit integrators for implicit differential-algebraic equations.
20pub trait ImplicitDaeVariableStepExplicit<Y, U, V, T = Time>
21where
22    Self: VariableStepExplicit<Y, U, V, T>,
23    Y: Differentiate<T> + Tensor,
24    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
25    U: TensorVec<Item = Y>,
26    V: TensorVec<Item = Derivative<Y, T>>,
27    T: UnitInv,
28    for<'a> &'a Y: Mul<Scalar, Output = Y>
29        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
30        + Sub<&'a Y, Output = Y>,
31    for<'a> &'a Derivative<Y, T>:
32        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
33{
34    fn integrate_implicit_dae_variable_step(
35        &self,
36        mut evolution: impl FnMut(
37            Quantity<T>,
38            &Y,
39            &Derivative<Y, T>,
40        ) -> Result<Derivative<Y, T>, String>,
41        time: &[Quantity<T>],
42        initial_condition: Y,
43    ) -> Result<(Times<T>, U, V), IntegrationError> {
44        let t_0 = time[0];
45        let t_f = time[time.len() - 1];
46        if time.len() < 2 {
47            return Err(IntegrationError::LengthTimeLessThanTwo);
48        } else if t_0 >= t_f {
49            return Err(IntegrationError::InitialTimeNotLessThanFinalTime);
50        }
51        let mut t = t_0;
52        let mut dt = t_f - t_0;
53        let mut t_sol = Times::new();
54        t_sol.push(t_0);
55        let mut dydt = &initial_condition * Quantity::<<T as UnitInv>::Output>::default();
56        let mut y = initial_condition;
57        let mut k = vec![Derivative::<Y, T>::default(); Self::SLOPES];
58        k[0] = evolution(t, &y, &dydt)?;
59        let mut y_sol = U::new();
60        y_sol.push(y.clone());
61        let mut dydt_sol = V::new();
62        dydt_sol.push(k[0].clone());
63        let mut k_sol: Vec<V> = Vec::new();
64        let mut y_trial = Y::default();
65        while t < t_f {
66            match self.slopes_and_error(
67                |t: Quantity<T>, y: &Y| evolution(t, y, &dydt),
68                &y,
69                t,
70                dt,
71                &mut k,
72                &mut y_trial,
73            ) {
74                Ok(e) => {
75                    if let Some(error) = self
76                        .step(
77                            |t: Quantity<T>, y: &Y| evolution(t, y, &dydt),
78                            &mut y,
79                            &mut t,
80                            &mut y_sol,
81                            &mut t_sol,
82                            &mut dydt_sol,
83                            &mut k_sol,
84                            &mut dt,
85                            &mut k,
86                            &y_trial,
87                            e,
88                        )
89                        .err()
90                    {
91                        dt *= self.dt_cut();
92                        if dt < self.dt_min() {
93                            return Err(IntegrationError::MinimumStepSizeUpstream(
94                                self.dt_min().value(),
95                                error,
96                                format!("{:?}", self),
97                            ));
98                        }
99                    } else {
100                        dydt = k[0].clone();
101                        dt = dt.min(t_f - t);
102                        if dt < self.dt_min() && t < t_f {
103                            return Err(IntegrationError::MinimumStepSizeReached(
104                                self.dt_min().value(),
105                                format!("{:?}", self),
106                            ));
107                        }
108                    }
109                }
110                Err(error) => {
111                    dt *= self.dt_cut();
112                    if dt < self.dt_min() {
113                        return Err(IntegrationError::MinimumStepSizeUpstream(
114                            self.dt_min().value(),
115                            error,
116                            format!("{:?}", self),
117                        ));
118                    }
119                }
120            }
121        }
122        if time.len() > 2 {
123            let t_int = Times::from(time);
124            let (y_int, dydt_int) = self.interpolate_implicit_dae_variable_step(
125                evolution, &t_int, &t_sol, &y_sol, &dydt_sol,
126            )?;
127            Ok((t_int, y_int, dydt_int))
128        } else {
129            Ok((t_sol, y_sol, dydt_sol))
130        }
131    }
132    fn interpolate_implicit_dae_variable_step(
133        &self,
134        mut evolution: impl FnMut(
135            Quantity<T>,
136            &Y,
137            &Derivative<Y, T>,
138        ) -> Result<Derivative<Y, T>, String>,
139        time: &Times<T>,
140        tp: &Times<T>,
141        yp: &U,
142        dydtp: &V,
143    ) -> Result<(U, V), IntegrationError> {
144        let mut dt;
145        let mut i;
146        let mut k = vec![Derivative::<Y, T>::default(); Self::SLOPES];
147        let mut t;
148        let mut y;
149        let mut dydt;
150        let mut y_int = U::new();
151        let mut dydt_int = V::new();
152        let mut y_trial = Y::default();
153        for time_k in time.iter() {
154            i = tp.iter().position(|tp_i| tp_i >= time_k).unwrap();
155            if time_k == &tp[i] {
156                t = tp[i];
157                y_trial = yp[i].clone();
158                dt = Quantity::default();
159            } else {
160                t = tp[i - 1];
161                y = &yp[i - 1];
162                dydt = &dydtp[i - 1];
163                dt = *time_k - t;
164                k[0] = evolution(t, y, dydt)?;
165                Self::slopes(
166                    |t: Quantity<T>, y: &Y| evolution(t, y, dydt),
167                    y,
168                    t,
169                    dt,
170                    &mut k,
171                    &mut y_trial,
172                )?;
173            }
174            dydt_int.push(evolution(t + dt, &y_trial, &k[0])?);
175            y_int.push(y_trial.clone());
176        }
177        Ok((y_int, dydt_int))
178    }
179}
180
181impl<I, Y, U, V, T> ImplicitDaeVariableStepExplicit<Y, U, V, T> for I
182where
183    Self: VariableStepExplicit<Y, U, V, T>,
184    Y: Differentiate<T> + Tensor,
185    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
186    U: TensorVec<Item = Y>,
187    V: TensorVec<Item = Derivative<Y, T>>,
188    T: UnitInv,
189    for<'a> &'a Y: Mul<Scalar, Output = Y>
190        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
191        + Sub<&'a Y, Output = Y>,
192    for<'a> &'a Derivative<Y, T>:
193        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
194{
195}
196
197/// Variable-step explicit integrators for implicit differential-algebraic equations using zeroth-order root-finding.
198pub trait ImplicitDaeVariableStepExplicitZerothOrderRoot<G, Y, U, V, T = Time>
199where
200    Self: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
201    Y: Differentiate<T> + Tensor,
202    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
203    U: TensorVec<Item = Y>,
204    V: TensorVec<Item = Derivative<Y, T>>,
205    T: UnitInv,
206    for<'a> &'a Y: Mul<Scalar, Output = Y>
207        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
208        + Sub<&'a Y, Output = Y>,
209    for<'a> &'a Derivative<Y, T>:
210        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
211{
212    fn integrate_implicit_dae_variable_step_explicit_root_0(
213        &self,
214        mut function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<G, String>,
215        solver: impl ZerothOrderRootFinding<G, Derivative<Y, T>>,
216        time: &[Quantity<T>],
217        initial_condition: Y,
218        mut equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
219    ) -> Result<(Times<T>, U, V), IntegrationError> {
220        let evolution = |t: Quantity<T>,
221                         y: &Y,
222                         dydt_0: &Derivative<Y, T>|
223         -> Result<Derivative<Y, T>, String> {
224            Ok(solver.root(
225                |dydt| function(t, y, dydt),
226                dydt_0.clone(),
227                equality_constraint(t),
228            )?)
229        };
230        self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
231    }
232}
233
234impl<I, G, Y, U, V, T> ImplicitDaeVariableStepExplicitZerothOrderRoot<G, Y, U, V, T> for I
235where
236    I: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
237    Y: Differentiate<T> + Tensor,
238    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
239    U: TensorVec<Item = Y>,
240    V: TensorVec<Item = Derivative<Y, T>>,
241    T: UnitInv,
242    for<'a> &'a Y: Mul<Scalar, Output = Y>
243        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
244        + Sub<&'a Y, Output = Y>,
245    for<'a> &'a Derivative<Y, T>:
246        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
247{
248}
249
250impl<I, G, Y, U, V, T> ImplicitDaeZerothOrderRoot<G, Y, U, V, T> for I
251where
252    Self: ImplicitDaeVariableStepExplicitZerothOrderRoot<G, Y, U, V, T>,
253    Y: Differentiate<T> + Tensor,
254    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
255    U: TensorVec<Item = Y>,
256    V: TensorVec<Item = Derivative<Y, T>>,
257    T: UnitInv,
258    for<'a> &'a Y: Mul<Scalar, Output = Y>
259        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
260        + Sub<&'a Y, Output = Y>,
261    for<'a> &'a Derivative<Y, T>:
262        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
263{
264    fn integrate(
265        &self,
266        function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<G, String>,
267        solver: impl ZerothOrderRootFinding<G, Derivative<Y, T>>,
268        time: &[Quantity<T>],
269        initial_condition: Y,
270        equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
271    ) -> Result<(Times<T>, U, V), IntegrationError> {
272        self.integrate_implicit_dae_variable_step_explicit_root_0(
273            function,
274            solver,
275            time,
276            initial_condition,
277            equality_constraint,
278        )
279    }
280}
281
282/// Variable-step explicit integrators for implicit differential-algebraic equations using first-order root-finding.
283pub trait ImplicitDaeVariableStepExplicitFirstOrderRoot<F, J, Y, U, V, T = Time>
284where
285    Self: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
286    Y: Differentiate<T> + Tensor,
287    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
288    U: TensorVec<Item = Y>,
289    V: TensorVec<Item = Derivative<Y, T>>,
290    T: UnitInv,
291    for<'a> &'a Y: Mul<Scalar, Output = Y>
292        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
293        + Sub<&'a Y, Output = Y>,
294    for<'a> &'a Derivative<Y, T>:
295        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
296{
297    fn integrate_implicit_dae_variable_step_explicit_root_1(
298        &self,
299        mut function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<F, String>,
300        mut jacobian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<J, String>,
301        solver: impl FirstOrderRootFinding<F, J, Derivative<Y, T>>,
302        time: &[Quantity<T>],
303        initial_condition: Y,
304        mut equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
305    ) -> Result<(Times<T>, U, V), IntegrationError> {
306        let evolution = |t: Quantity<T>,
307                         y: &Y,
308                         dydt_0: &Derivative<Y, T>|
309         -> Result<Derivative<Y, T>, String> {
310            Ok(solver.root(
311                |dydt| function(t, y, dydt),
312                |dydt| jacobian(t, y, dydt),
313                dydt_0.clone(),
314                equality_constraint(t),
315                None,
316            )?)
317        };
318        self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
319    }
320}
321
322impl<I, F, J, Y, U, V, T> ImplicitDaeVariableStepExplicitFirstOrderRoot<F, J, Y, U, V, T> for I
323where
324    I: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
325    Y: Differentiate<T> + Tensor,
326    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
327    U: TensorVec<Item = Y>,
328    V: TensorVec<Item = Derivative<Y, T>>,
329    T: UnitInv,
330    for<'a> &'a Y: Mul<Scalar, Output = Y>
331        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
332        + Sub<&'a Y, Output = Y>,
333    for<'a> &'a Derivative<Y, T>:
334        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
335{
336}
337
338impl<I, F, J, Y, U, V, T> ImplicitDaeFirstOrderRoot<F, J, Y, U, V, T> for I
339where
340    Self: ImplicitDaeVariableStepExplicitFirstOrderRoot<F, J, Y, U, V, T>,
341    Y: Differentiate<T> + Tensor,
342    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
343    U: TensorVec<Item = Y>,
344    V: TensorVec<Item = Derivative<Y, T>>,
345    T: UnitInv,
346    for<'a> &'a Y: Mul<Scalar, Output = Y>
347        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
348        + Sub<&'a Y, Output = Y>,
349    for<'a> &'a Derivative<Y, T>:
350        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
351{
352    fn integrate(
353        &self,
354        function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<F, String>,
355        jacobian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<J, String>,
356        solver: impl FirstOrderRootFinding<F, J, Derivative<Y, T>>,
357        time: &[Quantity<T>],
358        initial_condition: Y,
359        equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
360    ) -> Result<(Times<T>, U, V), IntegrationError> {
361        self.integrate_implicit_dae_variable_step_explicit_root_1(
362            function,
363            jacobian,
364            solver,
365            time,
366            initial_condition,
367            equality_constraint,
368        )
369    }
370}
371
372/// Variable-step explicit integrators for implicit differential-algebraic equations using first-order minimization.
373pub trait ImplicitDaeVariableStepExplicitFirstOrderMinimize<F, G, Y, U, V, T = Time>
374where
375    Self: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
376    Y: Differentiate<T> + Tensor,
377    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
378    U: TensorVec<Item = Y>,
379    V: TensorVec<Item = Derivative<Y, T>>,
380    T: UnitInv,
381    for<'a> &'a Y: Mul<Scalar, Output = Y>
382        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
383        + Sub<&'a Y, Output = Y>,
384    for<'a> &'a Derivative<Y, T>:
385        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
386{
387    #[allow(clippy::too_many_arguments)]
388    fn integrate_implicit_dae_variable_step_explicit_minimize_1(
389        &self,
390        mut function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<F, String>,
391        mut jacobian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<G, String>,
392        solver: impl FirstOrderOptimization<F, G, Derivative<Y, T>>,
393        time: &[Quantity<T>],
394        initial_condition: Y,
395        mut equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
396    ) -> Result<(Times<T>, U, V), IntegrationError> {
397        let evolution = |t: Quantity<T>,
398                         y: &Y,
399                         dydt_0: &Derivative<Y, T>|
400         -> Result<Derivative<Y, T>, String> {
401            Ok(solver.minimize(
402                |dydt| function(t, y, dydt),
403                |dydt| jacobian(t, y, dydt),
404                dydt_0.clone(),
405                equality_constraint(t),
406            )?)
407        };
408        self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
409    }
410}
411
412impl<I, F, G, Y, U, V, T> ImplicitDaeVariableStepExplicitFirstOrderMinimize<F, G, Y, U, V, T> for I
413where
414    I: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
415    Y: Differentiate<T> + Tensor,
416    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
417    U: TensorVec<Item = Y>,
418    V: TensorVec<Item = Derivative<Y, T>>,
419    T: UnitInv,
420    for<'a> &'a Y: Mul<Scalar, Output = Y>
421        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
422        + Sub<&'a Y, Output = Y>,
423    for<'a> &'a Derivative<Y, T>:
424        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
425{
426}
427
428impl<I, F, G, Y, U, V, T> ImplicitDaeFirstOrderMinimize<F, G, Y, U, V, T> for I
429where
430    Self: ImplicitDaeVariableStepExplicitFirstOrderMinimize<F, G, Y, U, V, T>,
431    Y: Differentiate<T> + Tensor,
432    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
433    U: TensorVec<Item = Y>,
434    V: TensorVec<Item = Derivative<Y, T>>,
435    T: UnitInv,
436    for<'a> &'a Y: Mul<Scalar, Output = Y>
437        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
438        + Sub<&'a Y, Output = Y>,
439    for<'a> &'a Derivative<Y, T>:
440        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
441{
442    fn integrate(
443        &self,
444        function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<F, String>,
445        jacobian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<G, String>,
446        solver: impl FirstOrderOptimization<F, G, Derivative<Y, T>>,
447        time: &[Quantity<T>],
448        initial_condition: Y,
449        equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
450    ) -> Result<(Times<T>, U, V), IntegrationError> {
451        self.integrate_implicit_dae_variable_step_explicit_minimize_1(
452            function,
453            jacobian,
454            solver,
455            time,
456            initial_condition,
457            equality_constraint,
458        )
459    }
460}
461
462/// Variable-step explicit integrators for implicit differential-algebraic equations using second-order minimization.
463pub trait ImplicitDaeVariableStepExplicitSecondOrderMinimize<F, J, H, Y, U, V, T = Time>
464where
465    Self: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
466    Y: Differentiate<T> + Tensor,
467    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
468    U: TensorVec<Item = Y>,
469    V: TensorVec<Item = Derivative<Y, T>>,
470    T: UnitInv,
471    for<'a> &'a Y: Mul<Scalar, Output = Y>
472        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
473        + Sub<&'a Y, Output = Y>,
474    for<'a> &'a Derivative<Y, T>:
475        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
476{
477    #[allow(clippy::too_many_arguments)]
478    fn integrate_implicit_dae_variable_step_explicit_minimize_2(
479        &self,
480        mut function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<F, String>,
481        mut jacobian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<J, String>,
482        mut hessian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<H, String>,
483        solver: impl SecondOrderOptimization<F, J, H, Derivative<Y, T>>,
484        time: &[Quantity<T>],
485        initial_condition: Y,
486        mut equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
487        sparse: Option<SparseSolver>,
488    ) -> Result<(Times<T>, U, V), IntegrationError> {
489        let evolution = |t: Quantity<T>,
490                         y: &Y,
491                         dydt_0: &Derivative<Y, T>|
492         -> Result<Derivative<Y, T>, String> {
493            Ok(solver.minimize(
494                |dydt| function(t, y, dydt),
495                |dydt| jacobian(t, y, dydt),
496                |dydt| hessian(t, y, dydt),
497                dydt_0.clone(),
498                equality_constraint(t),
499                sparse.clone(),
500            )?)
501        };
502        self.integrate_implicit_dae_variable_step(evolution, time, initial_condition)
503    }
504}
505
506impl<I, F, J, H, Y, U, V, T> ImplicitDaeVariableStepExplicitSecondOrderMinimize<F, J, H, Y, U, V, T>
507    for I
508where
509    I: ImplicitDaeVariableStepExplicit<Y, U, V, T>,
510    Y: Differentiate<T> + Tensor,
511    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
512    U: TensorVec<Item = Y>,
513    V: TensorVec<Item = Derivative<Y, T>>,
514    T: UnitInv,
515    for<'a> &'a Y: Mul<Scalar, Output = Y>
516        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
517        + Sub<&'a Y, Output = Y>,
518    for<'a> &'a Derivative<Y, T>:
519        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
520{
521}
522
523impl<I, F, J, H, Y, U, V, T> ImplicitDaeSecondOrderMinimize<F, J, H, Y, U, V, T> for I
524where
525    Self: ImplicitDaeVariableStepExplicitSecondOrderMinimize<F, J, H, Y, U, V, T>,
526    Y: Differentiate<T> + Tensor,
527    Derivative<Y, T>: Mul<Quantity<T>, Output = Y>,
528    U: TensorVec<Item = Y>,
529    V: TensorVec<Item = Derivative<Y, T>>,
530    T: UnitInv,
531    for<'a> &'a Y: Mul<Scalar, Output = Y>
532        + Mul<Quantity<<T as UnitInv>::Output>, Output = Derivative<Y, T>>
533        + Sub<&'a Y, Output = Y>,
534    for<'a> &'a Derivative<Y, T>:
535        Mul<Scalar, Output = Derivative<Y, T>> + Mul<Quantity<T>, Output = Y>,
536{
537    fn integrate(
538        &self,
539        function: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<F, String>,
540        jacobian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<J, String>,
541        hessian: impl FnMut(Quantity<T>, &Y, &Derivative<Y, T>) -> Result<H, String>,
542        solver: impl SecondOrderOptimization<F, J, H, Derivative<Y, T>>,
543        time: &[Quantity<T>],
544        initial_condition: Y,
545        equality_constraint: impl FnMut(Quantity<T>) -> EqualityConstraint,
546        sparse: Option<SparseSolver>,
547    ) -> Result<(Times<T>, U, V), IntegrationError> {
548        self.integrate_implicit_dae_variable_step_explicit_minimize_2(
549            function,
550            jacobian,
551            hessian,
552            solver,
553            time,
554            initial_condition,
555            equality_constraint,
556            sparse,
557        )
558    }
559}