use crate::PhysicsError;
use crate::kernels::fluids::quantities::{
RotationRateTensor, StrainRateTensor, Velocity3, VelocityGradient, VorticityVector,
};
use deep_causality_num::{FromPrimitive, RealField};
pub fn strain_rate_tensor_kernel<R>(
grad_u: &VelocityGradient<R>,
) -> Result<StrainRateTensor<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 g = grad_u.value();
let mut s = [[R::zero(); 3]; 3];
for i in 0..3 {
for j in 0..3 {
s[i][j] = half * (g[i][j] + g[j][i]);
}
}
Ok(StrainRateTensor::new_unchecked(s))
}
pub fn rotation_rate_tensor_kernel<R>(
grad_u: &VelocityGradient<R>,
) -> Result<RotationRateTensor<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 g = grad_u.value();
let mut omega = [[R::zero(); 3]; 3];
for i in 0..3 {
for j in 0..3 {
omega[i][j] = half * (g[i][j] - g[j][i]);
}
}
Ok(RotationRateTensor::new_unchecked(omega))
}
pub fn vorticity_from_gradient_kernel<R>(grad_u: &VelocityGradient<R>) -> VorticityVector<R>
where
R: RealField,
{
let g = grad_u.value();
VorticityVector::new_unchecked([g[2][1] - g[1][2], g[0][2] - g[2][0], g[1][0] - g[0][1]])
}
pub fn velocity_gradient_invariants_kernel<R>(
grad_u: &VelocityGradient<R>,
) -> Result<(R, R, 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 g = grad_u.value();
let trace_a = g[0][0] + g[1][1] + g[2][2];
let p = -trace_a;
let trace_a_squared = g[0][0] * g[0][0]
+ g[0][1] * g[1][0]
+ g[0][2] * g[2][0]
+ g[1][0] * g[0][1]
+ g[1][1] * g[1][1]
+ g[1][2] * g[2][1]
+ g[2][0] * g[0][2]
+ g[2][1] * g[1][2]
+ g[2][2] * g[2][2];
let q = half * (p * p - trace_a_squared);
let det_a = g[0][0] * (g[1][1] * g[2][2] - g[1][2] * g[2][1])
- g[0][1] * (g[1][0] * g[2][2] - g[1][2] * g[2][0])
+ g[0][2] * (g[1][0] * g[2][1] - g[1][1] * g[2][0]);
let r = -det_a;
Ok((p, q, r))
}
pub fn helicity_density_kernel<R>(u: &Velocity3<R>, omega: &VorticityVector<R>) -> R
where
R: RealField,
{
let u_raw = u.value();
let w_raw = omega.value();
u_raw[0] * w_raw[0] + u_raw[1] * w_raw[1] + u_raw[2] * w_raw[2]
}
pub fn enstrophy_density_kernel<R>(omega: &VorticityVector<R>) -> Result<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 w = omega.value();
Ok(half * (w[0] * w[0] + w[1] * w[1] + w[2] * w[2]))
}