pub mod dop853;
pub mod dopri5;
pub mod rk4;
pub use dop853::{dop853_propagate, dop853_step, Dop853, Dop853Step};
pub use dopri5::{dopri5_propagate, dopri5_step, Dopri5};
#[cfg(any(feature = "alloc", feature = "std"))]
pub use rk4::rk4_propagate_series;
pub use rk4::{rk4_propagate, rk4_step, Rk4};
use affn::centers::ReferenceCenter;
use affn::frames::ReferenceFrame;
use tempoch::ContinuousScale;
use crate::error::PrincipiaError;
use crate::models::AccelerationModel;
use crate::state::{DynamicsState, StateDerivative};
use qtty::Second;
pub trait Stepper<Ctx, S, C, F>
where
S: ContinuousScale,
C: ReferenceCenter,
F: ReferenceFrame,
{
fn step<M: AccelerationModel<Ctx, S, C, F>>(
&self,
model: &M,
state: &DynamicsState<S, C, F>,
h: Second,
ctx: &Ctx,
) -> Result<DynamicsState<S, C, F>, PrincipiaError>;
}
pub trait AdaptiveStepper<Ctx, S, C, F>
where
S: ContinuousScale,
C: ReferenceCenter,
F: ReferenceFrame,
{
#[allow(clippy::type_complexity)]
fn step<M: AccelerationModel<Ctx, S, C, F>>(
&self,
model: &M,
state: &DynamicsState<S, C, F>,
h_try: Second,
ctx: &Ctx,
) -> Result<(DynamicsState<S, C, F>, Second, Second, u32), PrincipiaError>;
}
#[inline]
pub(super) fn state_component<S, C, F>(s: &DynamicsState<S, C, F>, i: usize) -> f64
where
S: ContinuousScale,
C: ReferenceCenter,
F: ReferenceFrame,
{
match i {
0 => s.position.x().value(),
1 => s.position.y().value(),
2 => s.position.z().value(),
3 => s.velocity.x().value(),
4 => s.velocity.y().value(),
5 => s.velocity.z().value(),
_ => panic!("index {i} out of range [0,5]"),
}
}
#[inline]
pub(super) fn deriv_component<F: ReferenceFrame>(d: &StateDerivative<F>, i: usize) -> f64 {
match i {
0 => d.vel.x().value(),
1 => d.vel.y().value(),
2 => d.vel.z().value(),
3 => d.acc.x().value(),
4 => d.acc.y().value(),
5 => d.acc.z().value(),
_ => panic!("index {i} out of range [0,5]"),
}
}
#[inline]
pub(super) fn rhs<M, Ctx, S, C, F>(
model: &M,
s: &DynamicsState<S, C, F>,
ctx: &Ctx,
) -> Result<StateDerivative<F>, PrincipiaError>
where
M: AccelerationModel<Ctx, S, C, F>,
S: ContinuousScale,
C: ReferenceCenter,
F: ReferenceFrame,
{
Ok(StateDerivative::new(
s.velocity,
model.acceleration(s, ctx)?,
))
}
#[inline]
pub(super) fn state_at<S, C, F>(
s: &DynamicsState<S, C, F>,
d: &StateDerivative<F>,
h: f64,
dt: f64,
) -> DynamicsState<S, C, F>
where
S: ContinuousScale,
C: ReferenceCenter,
F: ReferenceFrame,
{
let mut next = s.advance(d, Second::new(h));
next.epoch = s.epoch + Second::new(dt);
next
}
pub use qtty::IntegratorTolerances;