use crate::error::{BijliError, Result};
use crate::field::{EPSILON_0, FieldVector, MU_0};
#[inline]
#[must_use]
pub fn gauss_electric_divergence(charge_density: f64) -> f64 {
charge_density / EPSILON_0
}
#[inline]
#[must_use]
pub fn gauss_magnetic_divergence() -> f64 {
0.0
}
#[inline]
#[must_use]
pub fn displacement_current(de_dt: &FieldVector) -> FieldVector {
de_dt.scale(EPSILON_0)
}
#[inline]
pub fn wave_speed(permittivity: f64, permeability: f64) -> Result<f64> {
if permittivity <= 0.0 {
return Err(BijliError::InvalidPermittivity {
value: permittivity,
});
}
if permeability <= 0.0 {
return Err(BijliError::InvalidPermeability {
value: permeability,
});
}
Ok(1.0 / (permittivity * permeability).sqrt())
}
#[inline]
pub fn refractive_index(relative_permittivity: f64, relative_permeability: f64) -> Result<f64> {
if relative_permittivity <= 0.0 {
return Err(BijliError::InvalidPermittivity {
value: relative_permittivity,
});
}
if relative_permeability <= 0.0 {
return Err(BijliError::InvalidPermeability {
value: relative_permeability,
});
}
Ok((relative_permittivity * relative_permeability).sqrt())
}
#[inline]
pub fn impedance(permittivity: f64, permeability: f64) -> Result<f64> {
if permittivity <= 0.0 {
return Err(BijliError::InvalidPermittivity {
value: permittivity,
});
}
if permeability <= 0.0 {
return Err(BijliError::InvalidPermeability {
value: permeability,
});
}
Ok((permeability / permittivity).sqrt())
}
#[inline]
#[must_use]
pub fn free_space_impedance() -> f64 {
(MU_0 / EPSILON_0).sqrt()
}
#[inline]
pub fn wavelength(frequency: f64, velocity: f64) -> Result<f64> {
if frequency <= 0.0 {
return Err(BijliError::InvalidParameter {
reason: format!("frequency must be positive, got {frequency}"),
});
}
if velocity <= 0.0 {
return Err(BijliError::InvalidParameter {
reason: format!("velocity must be positive, got {velocity}"),
});
}
Ok(velocity / frequency)
}
#[inline]
pub fn frequency(wavelength_m: f64, velocity: f64) -> Result<f64> {
if wavelength_m <= 0.0 {
return Err(BijliError::InvalidParameter {
reason: format!("wavelength must be positive, got {wavelength_m}"),
});
}
if velocity <= 0.0 {
return Err(BijliError::InvalidParameter {
reason: format!("velocity must be positive, got {velocity}"),
});
}
Ok(velocity / wavelength_m)
}
#[inline]
pub fn skin_depth(angular_freq: f64, permeability: f64, conductivity: f64) -> Result<f64> {
let denom = angular_freq * permeability * conductivity;
if denom <= 0.0 {
return Err(BijliError::InvalidParameter {
reason: "all parameters must be positive for skin depth".into(),
});
}
Ok((2.0 / denom).sqrt())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::field::SPEED_OF_LIGHT;
#[test]
fn test_gauss_electric() {
let div = gauss_electric_divergence(1e-6);
assert!(div > 1e4);
}
#[test]
fn test_gauss_magnetic() {
assert_eq!(gauss_magnetic_divergence(), 0.0);
}
#[test]
fn test_wave_speed_vacuum() {
let v = wave_speed(EPSILON_0, MU_0).unwrap();
assert!((v - SPEED_OF_LIGHT).abs() / SPEED_OF_LIGHT < 1e-6);
}
#[test]
fn test_refractive_index_vacuum() {
let n = refractive_index(1.0, 1.0).unwrap();
assert!((n - 1.0).abs() < 1e-10);
}
#[test]
fn test_refractive_index_glass() {
let n = refractive_index(2.25, 1.0).unwrap();
assert!((n - 1.5).abs() < 1e-10);
}
#[test]
fn test_refractive_index_negative_permittivity() {
assert!(refractive_index(-1.0, 1.0).is_err());
}
#[test]
fn test_wavelength_zero_velocity() {
assert!(wavelength(5e14, 0.0).is_err());
}
#[test]
fn test_frequency_zero_velocity() {
assert!(frequency(530e-9, 0.0).is_err());
}
#[test]
fn test_free_space_impedance() {
let z0 = free_space_impedance();
assert!((z0 - 376.73).abs() < 0.1);
}
#[test]
fn test_wavelength_visible_light() {
let lambda = wavelength(5.66e14, SPEED_OF_LIGHT).unwrap();
assert!((lambda * 1e9 - 530.0).abs() < 1.0);
}
#[test]
fn test_frequency_from_wavelength() {
let f = frequency(530e-9, SPEED_OF_LIGHT).unwrap();
assert!((f - 5.66e14).abs() / 5.66e14 < 0.01);
}
#[test]
fn test_skin_depth() {
let delta = skin_depth(2.0 * std::f64::consts::PI * 60.0, MU_0, 5.96e7).unwrap();
assert!((delta * 1000.0 - 8.5).abs() < 1.0);
}
#[test]
fn test_displacement_current() {
let de_dt = FieldVector::new(1e6, 0.0, 0.0);
let jd = displacement_current(&de_dt);
assert!((jd.x - EPSILON_0 * 1e6).abs() < 1e-10);
}
#[test]
fn test_invalid_permittivity() {
assert!(wave_speed(-1.0, MU_0).is_err());
}
#[test]
fn test_invalid_permeability() {
assert!(impedance(EPSILON_0, -1.0).is_err());
}
}