use super::rk4;
use traits::*;
pub enum Method {
RK4,
}
pub struct Solver<T> where T: Number {
method: Method,
weights: Vec<T>,
weight_sum: T,
time_begin: T,
time_end: T,
step: T,
initial_conditions: Vec<T>,
}
impl<T> Solver<T> where T: Number {
fn sum_weights(weights: &Vec<T>) -> T {
weights
.iter()
.fold(T::zero(), |sum, i| sum + i.clone())
}
fn get_default_weights_for(method: &Method) -> Vec<T> {
let weights = match method {
&Method::RK4 => vec!["1", "2", "2", "1"],
};
weights
.iter()
.map(|el| T::from_str_radix(el, 10).ok().unwrap())
.collect()
}
pub fn new(time_interval: &[T; 2],
initial_conditions: &Vec<T>) -> Solver<T> {
let weights = Self::get_default_weights_for(&Method::RK4);
let sum_of_weights = Self::sum_weights(&weights);
let default_step = T::from_str_radix("10e-3", 10).ok().unwrap();
Solver {
method: Method::RK4,
weights: weights,
weight_sum: sum_of_weights,
time_begin: time_interval[0].clone(),
time_end: time_interval[1].clone(),
step: default_step,
initial_conditions: initial_conditions.clone(),
}
}
pub fn method(&mut self, new_method: Method) -> &mut Solver<T> {
self.weights = Self::get_default_weights_for(&new_method);
self.method = new_method;
self.weight_sum = Self::sum_weights(&self.weights);
self
}
pub fn weights(&mut self, new_weights: Vec<T>) -> &mut Solver<T> {
self.weights = new_weights.clone();
self.weight_sum = Self::sum_weights(&self.weights);
self
}
pub fn validate(&self) -> bool {
self.weights.len() == match self.method {
Method::RK4 => 4,
}
}
pub fn solve<F>(&self, function: F) -> (Vec<T>, Vec<Vec<T>>)
where F: Function<T> {
assert!(self.validate());
match self.method {
Method::RK4 => rk4::solver(function,
self.initial_conditions.clone(),
&[self.time_begin, self.time_end],
self.step,
&self.weights,
self.weight_sum)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let _ = Solver::new(&[0., 100.],
&vec![0., 0.]);
}
}