use crate::{Frequency, Length, PhysicsError, Speed};
use deep_causality_num::RealField;
pub fn wave_speed_kernel<R>(
frequency: &Frequency<R>,
wavelength: &Length<R>,
) -> Result<Speed<R>, PhysicsError>
where
R: RealField,
{
let v = frequency.value() * wavelength.value();
if v.is_infinite() {
return Err(PhysicsError::NumericalInstability(
"Wave speed calculation resulted in infinity".into(),
));
}
Speed::new(v)
}
pub fn doppler_effect_kernel<R>(
freq_source: &Frequency<R>,
wave_speed: &Speed<R>,
obs_speed: &Speed<R>,
src_speed: &Speed<R>,
) -> Result<Frequency<R>, PhysicsError>
where
R: RealField,
{
let v = wave_speed.value();
let vo = obs_speed.value();
let vs = src_speed.value();
let denominator = v - vs;
let eps = R::epsilon().sqrt() * v.abs();
if denominator <= eps {
return Err(PhysicsError::MetricSingularity(
"Source speed equals or exceeds wave speed - Sonic Singularity".into(),
));
}
let f_obs = freq_source.value() * ((v + vo) / denominator);
Frequency::new(f_obs)
}