sequential_integration/engine/integrators/
third_integrator.rs

1use core::marker::PhantomData;
2use fehler::throws;
3
4use super::utils as integrator_utils;
5use crate::{
6    engine::{
7        helper_equation_traits::{EquationOfThreeVariable, EquationOfTwoVariable},
8        quadrature::GetQuadratureRange,
9        Bounds, CalculationResult, CalculationStep,
10    },
11    errors::Error,
12};
13
14pub struct ThirdIntegrator<
15    'a,
16    G: GetQuadratureRange,
17    E: EquationOfThreeVariable,
18    F1: Fn(f64, f64) -> f64,
19    F2: Fn(f64, f64) -> f64,
20> {
21    a_equation: F1,
22    b_equation: F2,
23    h: f64,
24    equation: &'a E,
25    _p: PhantomData<G>,
26}
27
28impl<
29        'a,
30        G: GetQuadratureRange,
31        E: EquationOfThreeVariable,
32        F1: Fn(f64, f64) -> f64,
33        F2: Fn(f64, f64) -> f64,
34    > ThirdIntegrator<'a, G, E, F1, F2>
35{
36    #[throws]
37    pub fn new(a_equation: F1, b_equation: F2, h: f64, equation: &'a E) -> Self {
38        Self {
39            a_equation,
40            b_equation,
41            h,
42            equation,
43            _p: PhantomData,
44        }
45    }
46}
47
48impl<
49        'a,
50        G: GetQuadratureRange,
51        E: EquationOfThreeVariable,
52        F1: Fn(f64, f64) -> f64,
53        F2: Fn(f64, f64) -> f64,
54    > EquationOfTwoVariable for ThirdIntegrator<'a, G, E, F1, F2>
55{
56    #[throws]
57    fn calculate(
58        &self,
59        x: CalculationStep,
60        bounds_x: Bounds,
61        y: CalculationStep,
62        bounds_y: Bounds,
63    ) -> CalculationResult {
64        let a = (self.a_equation)(*x, *y);
65        let b = (self.b_equation)(*x, *y);
66        let borders_config = integrator_utils::BoundsConfigurator::configurate(a, b)?;
67
68        let mut result = CalculationResult::new();
69        let mut range = if let Some(range) = G::get_range_generator(borders_config.bounds, self.h)?
70        {
71            range
72        } else {
73            return result;
74        };
75
76        loop {
77            let step = range.next()?;
78            result +=
79                self.equation
80                    .calculate(x, bounds_x, y, bounds_y, step, borders_config.bounds)?
81                    * borders_config.direction_coeff;
82
83            if step.is_last() {
84                break;
85            }
86        }
87
88        result
89    }
90}