use deep_causality_algebra::RealField;
use deep_causality_physics::PhysicsError;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum IntegratorRegime {
PerturbedConformal,
Direct,
}
pub fn aero_gravity_ratio<R: RealField>(
aero_accel: [R; 3],
radius: R,
gm: R,
) -> Result<R, PhysicsError> {
if radius <= R::zero() {
return Err(PhysicsError::Singularity(
"aero/gravity ratio needs a positive radius".into(),
));
}
let a_aero = (aero_accel[0] * aero_accel[0]
+ aero_accel[1] * aero_accel[1]
+ aero_accel[2] * aero_accel[2])
.sqrt();
let a_grav = gm / (radius * radius);
Ok(a_aero / a_grav)
}
#[derive(Clone, Copy, Debug)]
pub struct RegimeSwitch<R> {
exit_direct: R,
enter_direct: R,
regime: IntegratorRegime,
}
impl<R: RealField> RegimeSwitch<R> {
pub fn new(exit_direct: R, enter_direct: R, initial: IntegratorRegime) -> Self {
Self {
exit_direct,
enter_direct,
regime: initial,
}
}
pub fn select(&mut self, epsilon: R) -> IntegratorRegime {
self.regime = match self.regime {
IntegratorRegime::PerturbedConformal => {
if epsilon > self.enter_direct {
IntegratorRegime::Direct
} else {
IntegratorRegime::PerturbedConformal
}
}
IntegratorRegime::Direct => {
if epsilon < self.exit_direct {
IntegratorRegime::PerturbedConformal
} else {
IntegratorRegime::Direct
}
}
};
self.regime
}
pub fn regime(&self) -> IntegratorRegime {
self.regime
}
}