use crate::constants::{EARTH_GRAVITY_ACCELERATION, real_from_f64};
use crate::{Force, Mass, MassFlowRate, PhysicsError, Speed};
use deep_causality_algebra::RealField;
use deep_causality_num::FromPrimitive;
pub fn propellant_mass_flow_kernel<R>(
thrust: Force<R>,
isp_s: R,
) -> Result<MassFlowRate<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
if !isp_s.is_finite() || isp_s <= R::zero() {
return Err(PhysicsError::PhysicalInvariantBroken(
"Specific impulse must be positive".into(),
));
}
let t = thrust.value();
if t < R::zero() {
return Err(PhysicsError::PhysicalInvariantBroken(
"Thrust cannot be negative".into(),
));
}
let g0: R = real_from_f64(EARTH_GRAVITY_ACCELERATION);
MassFlowRate::new(t / (isp_s * g0))
}
pub fn tsiolkovsky_delta_v_kernel<R>(
isp_s: R,
initial_mass: Mass<R>,
final_mass: Mass<R>,
) -> Result<Speed<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
if !isp_s.is_finite() || isp_s <= R::zero() {
return Err(PhysicsError::PhysicalInvariantBroken(
"Specific impulse must be positive".into(),
));
}
let m0 = initial_mass.value();
let m1 = final_mass.value();
if m1 <= R::zero() {
return Err(PhysicsError::Singularity(
"Final mass must be positive".into(),
));
}
if m0 < m1 {
return Err(PhysicsError::PhysicalInvariantBroken(
"A burn cannot end heavier than it began (m0 < m1)".into(),
));
}
let g0: R = real_from_f64(EARTH_GRAVITY_ACCELERATION);
Speed::new(isp_s * g0 * (m0 / m1).ln())
}