use crate::constants::{
BOLTZMANN_CONSTANT, ELECTRON_MASS, ELEMENTARY_CHARGE, VACUUM_ELECTRIC_PERMITTIVITY,
};
use crate::{DebyeLength, ElectronDensity, LarmorRadius, PlasmaFrequency};
use crate::{Mass, PhysicalField, PhysicsError, Speed, Temperature};
use deep_causality_algebra::RealField;
use deep_causality_multivector::MultiVector;
use deep_causality_num::FromPrimitive;
pub fn debye_length_kernel<R>(
temp: Temperature<R>,
density_n: R,
epsilon_0: R,
elementary_charge: R,
) -> Result<DebyeLength<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
if density_n <= R::zero() {
return Err(PhysicsError::Singularity("Density must be positive".into()));
}
if epsilon_0 <= R::zero() {
return Err(PhysicsError::PhysicalInvariantBroken(
"Permittivity must be positive".into(),
));
}
let kb = R::from_f64(BOLTZMANN_CONSTANT).ok_or_else(|| {
PhysicsError::NumericalInstability("R::from_f64(BOLTZMANN_CONSTANT) failed".into())
})?;
let num = epsilon_0 * kb * temp.value();
let den = density_n * (elementary_charge * elementary_charge);
let lambda = (num / den).sqrt();
DebyeLength::new(lambda)
}
pub fn larmor_radius_kernel<R>(
mass: Mass<R>,
velocity_perp: Speed<R>,
charge: R,
b_field: &PhysicalField<R>,
) -> Result<LarmorRadius<R>, PhysicsError>
where
R: RealField,
{
let b_mag = b_field.inner().squared_magnitude().sqrt();
if b_mag == R::zero() {
return Err(PhysicsError::Singularity(
"Zero magnetic field leads to infinite Larmor radius".into(),
));
}
if charge == R::zero() {
return Err(PhysicsError::Singularity(
"Zero charge particle moves in straight line (infinite radius)".into(),
));
}
let num = mass.value() * velocity_perp.value();
let den = charge.abs() * b_mag;
LarmorRadius::new(num / den)
}
pub fn plasma_frequency_kernel<R>(
electron_density: ElectronDensity<R>,
) -> Result<PlasmaFrequency<R>, PhysicsError>
where
R: RealField + FromPrimitive,
{
let n_e = electron_density.value();
let eps0 = R::from_f64(VACUUM_ELECTRIC_PERMITTIVITY).ok_or_else(|| {
PhysicsError::NumericalInstability(
"R::from_f64(VACUUM_ELECTRIC_PERMITTIVITY) failed".into(),
)
})?;
let m_e = R::from_f64(ELECTRON_MASS).ok_or_else(|| {
PhysicsError::NumericalInstability("R::from_f64(ELECTRON_MASS) failed".into())
})?;
let e = R::from_f64(ELEMENTARY_CHARGE).ok_or_else(|| {
PhysicsError::NumericalInstability("R::from_f64(ELEMENTARY_CHARGE) failed".into())
})?;
let omega_p = (n_e * e * e / (eps0 * m_e)).sqrt();
PlasmaFrequency::new(omega_p)
}