use std::sync::Arc;
use anise::almanac::Almanac;
use super::{IntegrationDetails, IntegratorMethod, IntegratorOptions, PropInstance};
use crate::State;
use crate::dynamics::Dynamics;
use crate::linalg::allocator::Allocator;
use crate::linalg::{DefaultAllocator, OVector};
use crate::time::Duration;
#[derive(Clone, Debug)]
pub struct Propagator<D: Dynamics>
where
DefaultAllocator: Allocator<<D::StateType as State>::Size>
+ Allocator<<D::StateType as State>::Size, <D::StateType as State>::Size>
+ Allocator<<D::StateType as State>::Size, <D::StateType as State>::Size>
+ Allocator<<D::StateType as State>::VecLength>,
{
pub dynamics: D, pub opts: IntegratorOptions, pub method: IntegratorMethod,
}
impl<D: Dynamics> Propagator<D>
where
DefaultAllocator: Allocator<<D::StateType as State>::Size>
+ Allocator<<D::StateType as State>::Size, <D::StateType as State>::Size>
+ Allocator<<D::StateType as State>::Size, <D::StateType as State>::Size>
+ Allocator<<D::StateType as State>::VecLength>,
{
pub fn new(dynamics: D, method: IntegratorMethod, opts: IntegratorOptions) -> Self {
Self {
dynamics,
opts,
method,
}
}
pub fn set_tolerance(&mut self, tol: f64) {
self.opts.tolerance = tol;
}
pub fn set_max_step(&mut self, step: Duration) {
self.opts.set_max_step(step);
}
pub fn set_min_step(&mut self, step: Duration) {
self.opts.set_min_step(step);
}
pub fn rk89(dynamics: D, opts: IntegratorOptions) -> Self {
Self::new(dynamics, IntegratorMethod::RungeKutta89, opts)
}
pub fn dp78(dynamics: D, opts: IntegratorOptions) -> Self {
Self::new(dynamics, IntegratorMethod::DormandPrince78, opts)
}
pub fn with(&self, state: D::StateType, almanac: Arc<Almanac>) -> PropInstance<'_, D> {
let mut k = Vec::with_capacity(self.method.stages() + 1);
for _ in 0..self.method.stages() {
k.push(OVector::<f64, <D::StateType as State>::VecLength>::zeros());
}
PropInstance {
state,
prop: self,
details: IntegrationDetails {
step: self.opts.init_step,
error: 0.0,
attempts: 1,
},
log_progress: true,
almanac,
step_size: self.opts.init_step,
fixed_step: self.opts.fixed_step,
k,
}
}
pub fn default(dynamics: D) -> Self {
Self::rk89(dynamics, IntegratorOptions::default())
}
pub fn default_dp78(dynamics: D) -> Self {
Self::dp78(dynamics, IntegratorOptions::default())
}
}