use crate::PhysicsError;
use crate::kernels::dynamics::quantities::{Length, Speed};
use crate::kernels::fluids::quantities::{Pressure, Velocity3};
use crate::{Density, G};
use deep_causality_num::{FromPrimitive, RealField};
pub fn dynamic_pressure_kernel<R>(
rho: &Density<R>,
u: &Speed<R>,
) -> Result<Pressure<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
let half = R::from_f64(0.5)
.ok_or_else(|| PhysicsError::NumericalInstability("R::from_f64(0.5) failed".into()))?;
let v = u.value();
Pressure::new(half * rho.value() * v * v)
}
pub fn bernoulli_total_head_kernel<R>(
p: &Pressure<R>,
rho: &Density<R>,
u: &Speed<R>,
h: &Length<R>,
) -> Result<Length<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
let r = rho.value();
if r == R::zero() {
return Err(PhysicsError::PhysicalInvariantBroken(
"bernoulli_total_head_kernel: density is zero".into(),
));
}
let g = R::from_f64(G)
.ok_or_else(|| PhysicsError::NumericalInstability("R::from_f64(G) failed".into()))?;
let two = R::one() + R::one();
let v = u.value();
let head = p.value() / (r * g) + (v * v) / (two * g) + h.value();
Length::new(head)
}
pub fn stream_function_2d_kernel<R>(u: R, v: R, dx: R, dy: R) -> R
where
R: RealField,
{
u * dy - v * dx
}
pub fn velocity_potential_2d_kernel<R>(u: R, v: R, dx: R, dy: R) -> R
where
R: RealField,
{
u * dx + v * dy
}
pub fn circulation_kernel<R>(
velocity_at_loop_points: &[Velocity3<R>],
tangents: &[[R; 3]],
) -> Result<R, PhysicsError>
where
R: RealField,
{
if velocity_at_loop_points.len() != tangents.len() {
return Err(PhysicsError::PhysicalInvariantBroken(
"circulation_kernel: velocity and tangent slices must have equal length".into(),
));
}
let mut gamma = R::zero();
for (u_pt, dl) in velocity_at_loop_points.iter().zip(tangents.iter()) {
let u = u_pt.value();
gamma += u[0] * dl[0] + u[1] * dl[1] + u[2] * dl[2];
}
Ok(gamma)
}
pub fn kutta_joukowski_lift_kernel<R>(rho: &Density<R>, u_inf: &Speed<R>, circulation: R) -> R
where
R: RealField,
{
rho.value() * u_inf.value() * circulation
}