use crate::{PhysicsError, Temperature};
use deep_causality_algebra::RealField;
use deep_causality_num::FromPrimitive;
pub fn rankine_hugoniot_temperature_kernel<R>(
t_inf: Temperature<R>,
mach: R,
gamma: R,
) -> Result<Temperature<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
let one = R::one();
if mach < one {
return Err(PhysicsError::PhysicalInvariantBroken(
"Mach number must be >= 1 for a shock".into(),
));
}
if gamma <= one {
return Err(PhysicsError::PhysicalInvariantBroken(
"Ratio of specific heats must be > 1".into(),
));
}
let t1 = t_inf.value();
if t1 <= R::zero() {
return Err(PhysicsError::Singularity(
"Freestream temperature must be positive".into(),
));
}
let two = R::from_f64(2.0)
.ok_or_else(|| PhysicsError::NumericalInstability("R::from_f64(2.0) failed".into()))?;
let m2 = mach * mach;
let num = (two * gamma * m2 - (gamma - one)) * ((gamma - one) * m2 + two);
let den = (gamma + one) * (gamma + one) * m2;
Temperature::new(t1 * num / den)
}
pub fn recovery_temperature_kernel<R>(
t_post: Temperature<R>,
speed: R,
c_p: R,
) -> Result<Temperature<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
if c_p <= R::zero() {
return Err(PhysicsError::Singularity(
"Specific heat c_p must be positive".into(),
));
}
let half = R::from_f64(0.5)
.ok_or_else(|| PhysicsError::NumericalInstability("R::from_f64(0.5) failed".into()))?;
Temperature::new(t_post.value() - half * speed * speed / c_p)
}