dzahui/solvers/euler/
mod.rs

1// FIRST EXCERCISE
2/// Euler's method for ordinary differential equations.
3/// The form of the equation is assumed to be "y'(n) = f(t,y,y',..,y'(n-1))".
4///
5/// # Parameters
6/// - initial_val: Vec<f32>
7///   The previous values of every variable. The derivatives go in descending order: [y'(n),y'(n-1),...,t]
8/// - step: f32
9///   The step used to calculate the approximation.
10/// - f: T where T: Fn(Vec<f32>) -> f32
11///   Reffers to the function on the left side of the above equation.
12///
13/// # Returns
14/// - Vec<f32>
15///   A vector of values corresponding to the new approximation. The derivatives are delivered as in 'initial_val'
16///
17pub trait FunctionArguments: Into<Vec<f64>> + Clone + std::convert::TryFrom<Vec<f64>> {}
18
19impl FunctionArguments for [f64; 2] {}
20impl FunctionArguments for [f64; 3] {}
21impl FunctionArguments for [f64; 4] {}
22impl FunctionArguments for [f64; 5] {}
23
24pub struct EulerSolver<A, F> {
25    derivative_function: F,
26    phantom: std::marker::PhantomData<A>,
27}
28
29impl<A: FunctionArguments, F: Fn(&A) -> f64> EulerSolver<A, F> {
30    pub fn new(derivative_function: F) -> EulerSolver<A, F> {
31        EulerSolver {
32            derivative_function,
33            phantom: std::marker::PhantomData,
34        }
35    }
36
37    pub fn do_step(&self, values: A, step: f64) -> A {
38        let f_eval: f64 = (self.derivative_function)(&values);
39        let as_vec: Vec<f64> = values.into();
40
41        let mut next_values: Vec<f64> = vec![];
42
43        let mut value: f64 = as_vec.get(0).unwrap() + step * f_eval;
44        let t_new: f64 = as_vec.get(as_vec.len() - 1).unwrap() + step;
45
46        next_values.push(value);
47
48        as_vec[1..as_vec.len() - 1].into_iter().for_each(|x| {
49            let new_val: f64 = x + step * value;
50            value = new_val;
51            next_values.push(new_val);
52        });
53        next_values.push(t_new);
54
55        match A::try_from(next_values) {
56            Ok(v) => v,
57            Err(_) => panic!("Nooo"),
58        }
59    }
60}