#[must_use]
#[inline]
pub fn joule_heating_power_density(current_density_a_m2: f64, resistivity_ohm_m: f64) -> f64 {
current_density_a_m2 * current_density_a_m2 * resistivity_ohm_m
}
#[must_use]
#[inline]
pub fn em_energy_to_heating_rate(
energy_density_j_m3: f64,
material_density_kg_m3: f64,
specific_heat_j_per_kg_k: f64,
) -> f64 {
let denom = material_density_kg_m3 * specific_heat_j_per_kg_k;
if denom <= 0.0 {
return 0.0;
}
energy_density_j_m3 / denom
}
#[must_use]
pub fn wavelength_to_refractive_index_bk7(wavelength_nm: f64) -> f64 {
if wavelength_nm <= 0.0 {
return 1.0;
}
let l2 = (wavelength_nm * 1e-3) * (wavelength_nm * 1e-3); let b1 = 1.039_612_12;
let b2 = 0.231_792_344;
let b3 = 1.010_469_45;
let c1 = 0.006_000_698_67;
let c2 = 0.020_017_914_4;
let c3 = 103.560_653;
let n2 = 1.0 + b1 * l2 / (l2 - c1) + b2 * l2 / (l2 - c2) + b3 * l2 / (l2 - c3);
if n2 > 0.0 { n2.sqrt() } else { 1.0 }
}
#[must_use]
#[inline]
pub fn e_field_to_optical_intensity(e_amplitude_v_m: f64) -> f64 {
const EPSILON_0: f64 = 8.854_187_817e-12;
const C: f64 = 299_792_458.0;
0.5 * EPSILON_0 * C * e_amplitude_v_m * e_amplitude_v_m
}
#[must_use]
#[inline]
pub fn energy_level_to_wavelength_nm(energy_ev: f64) -> f64 {
if energy_ev <= 0.0 {
return 0.0;
}
1239.842 / energy_ev
}
#[must_use]
#[inline]
pub fn nuclear_charge_potential(atomic_number: u32, distance_m: f64) -> f64 {
if distance_m <= 0.0 {
return 0.0;
}
const K: f64 = 8.987_551_792e9;
const E: f64 = 1.602_176_634e-19;
K * atomic_number as f64 * E / distance_m
}
#[must_use]
#[inline]
pub fn e_field_to_piezo_stress(e_field_v_m: f64, piezo_coeff_c_m2: f64) -> f64 {
e_field_v_m * piezo_coeff_c_m2
}
#[must_use]
#[inline]
pub fn magnetic_flux_to_magnetostrictive_strain(
flux_density_t: f64,
saturation_magnetostriction: f64,
saturation_flux_t: f64,
) -> f64 {
if saturation_flux_t <= 0.0 {
return 0.0;
}
let ratio = flux_density_t / saturation_flux_t;
1.5 * saturation_magnetostriction * ratio * ratio
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn joule_heating_basic() {
let p = joule_heating_power_density(1.0, 1e-7);
assert!((p - 1e-7).abs() < 1e-12);
}
#[test]
fn heating_rate_basic() {
let rate = em_energy_to_heating_rate(1000.0, 1000.0, 4186.0);
assert!((rate - 1000.0 / (1000.0 * 4186.0)).abs() < 1e-10);
}
#[test]
fn heating_rate_zero_density() {
assert_eq!(em_energy_to_heating_rate(1000.0, 0.0, 4186.0), 0.0);
}
#[test]
fn bk7_visible_range() {
let n = wavelength_to_refractive_index_bk7(550.0);
assert!(n > 1.5 && n < 1.55, "BK7 at 550nm: got {n}");
}
#[test]
fn bk7_dispersion() {
let n_blue = wavelength_to_refractive_index_bk7(450.0);
let n_red = wavelength_to_refractive_index_bk7(650.0);
assert!(n_blue > n_red, "blue should have higher n than red");
}
#[test]
fn bk7_zero_wavelength() {
assert_eq!(wavelength_to_refractive_index_bk7(0.0), 1.0);
}
#[test]
fn e_field_intensity_roundtrip() {
let e = 100.0;
let i = e_field_to_optical_intensity(e);
assert!(i > 0.0);
assert!((i - 13.28).abs() < 0.1);
}
#[test]
fn hydrogen_lyman_alpha() {
let nm = energy_level_to_wavelength_nm(10.2);
assert!((nm - 121.6).abs() < 1.0);
}
#[test]
fn energy_zero() {
assert_eq!(energy_level_to_wavelength_nm(0.0), 0.0);
}
#[test]
fn nuclear_potential_hydrogen() {
let v = nuclear_charge_potential(1, 5.29e-11);
assert!((v - 27.2).abs() < 0.5);
}
#[test]
fn nuclear_potential_zero_distance() {
assert_eq!(nuclear_charge_potential(1, 0.0), 0.0);
}
#[test]
fn piezo_stress_basic() {
let s = e_field_to_piezo_stress(1000.0, 15.0);
assert!((s - 15000.0).abs() < 0.1);
}
#[test]
fn magnetostriction_iron() {
let e = magnetic_flux_to_magnetostrictive_strain(1.0, 35e-6, 2.15);
let expected = 1.5 * 35e-6 * (1.0 / 2.15_f64).powi(2);
assert!((e - expected).abs() < 1e-10);
}
#[test]
fn magnetostriction_zero_saturation() {
assert_eq!(
magnetic_flux_to_magnetostrictive_strain(1.0, 35e-6, 0.0),
0.0
);
}
}