Skip to main content

nereids_core/
constants.rs

1//! Physical constants used throughout NEREIDS.
2//!
3//! Values from CODATA 2018 recommended values.
4//! Reference: <https://physics.nist.gov/cuu/Constants/>
5
6/// Neutron mass in kg.
7pub const NEUTRON_MASS_KG: f64 = 1.674_927_498_04e-27;
8
9/// Neutron mass in atomic mass units (u).
10pub const NEUTRON_MASS_AMU: f64 = 1.008_664_915_95;
11
12/// Neutron mass in MeV/c².
13pub const NEUTRON_MASS_MEV: f64 = 939.565_420_52;
14
15/// Boltzmann constant in eV/K.
16pub const BOLTZMANN_EV_PER_K: f64 = 8.617_333_262e-5;
17
18/// Planck constant (reduced, ħ) in eV·s.
19///
20/// Derived from h = 6.626_070_15e-34 J·s (exact, 2019 SI) and
21/// e = 1.602_176_634e-19 C (exact): ħ = h / (2π·e).
22/// Rounded to 10 significant figures.
23pub const HBAR_EV_S: f64 = 6.582_119_569e-16;
24
25/// Speed of light in m/s.
26pub const SPEED_OF_LIGHT: f64 = 2.997_924_58e8;
27
28/// 1 eV in joules.
29pub const EV_TO_JOULES: f64 = 1.602_176_634e-19;
30
31/// Avogadro's number in mol⁻¹.
32pub const AVOGADRO: f64 = 6.022_140_76e23;
33
34/// Convert neutron energy (eV) to wavelength (Å).
35///
36/// λ = h / √(2·m·E), result in angstroms.
37pub fn energy_to_wavelength_angstrom(energy_ev: f64) -> f64 {
38    // λ(Å) = 0.2860 / √(E in eV)  (standard neutron relation)
39    0.286_014_3 / energy_ev.sqrt()
40}
41
42/// Convert neutron time-of-flight (μs) and flight path (m) to energy (eV).
43///
44/// E = ½·m_n·(L/t)²
45pub fn tof_to_energy(tof_us: f64, flight_path_m: f64) -> f64 {
46    let t_s = tof_us * 1.0e-6;
47    let v = flight_path_m / t_s;
48    0.5 * NEUTRON_MASS_KG * v * v / EV_TO_JOULES
49}
50
51/// Convert neutron energy (eV) to time-of-flight (μs) given flight path (m).
52pub fn energy_to_tof(energy_ev: f64, flight_path_m: f64) -> f64 {
53    let v = (2.0 * energy_ev * EV_TO_JOULES / NEUTRON_MASS_KG).sqrt();
54    (flight_path_m / v) * 1.0e6
55}
56
57// ── Numerical tolerances ─────────────────────────────────────────────
58// Named constants for magic-number epsilons scattered across physics code.
59
60/// Epsilon for floating-point comparison of quantum numbers (J, L, spin).
61pub const QUANTUM_NUMBER_EPS: f64 = 1e-10;
62
63/// Floor for Poisson model values to avoid log(0) in NLL computation.
64pub const POISSON_EPSILON: f64 = 1e-10;
65
66/// Floor for denominators in physics evaluations (penetrability, shift, etc.)
67/// to avoid division by zero.
68pub const DIVISION_FLOOR: f64 = 1e-50;
69
70/// Generic tiny positive floor used as a near-zero tolerance across physics
71/// calculations (e.g., cross-sections in barns, energies in eV, widths,
72/// dimensionless parameters). Values below this are treated as negligible.
73pub const NEAR_ZERO_FLOOR: f64 = 1e-60;
74
75/// Floor for pivot detection and division safety in numerical linear algebra
76/// (LM solver, Gaussian elimination). Values below this indicate a
77/// (near-)singular system.
78pub const PIVOT_FLOOR: f64 = 1e-30;
79
80/// Floor for Levenberg-Marquardt diagonal elements to ensure damping stability.
81/// Intentionally much larger than PIVOT_FLOOR — LM requires a meaningful
82/// minimum curvature for numerical stability of the trust-region step.
83pub const LM_DIAGONAL_FLOOR: f64 = 1e-10;
84
85/// Floor for avoiding log(0) or division by zero in general computations.
86pub const LOG_FLOOR: f64 = 1e-300;
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91
92    #[test]
93    fn test_tof_energy_roundtrip() {
94        let energy = 6.67; // eV (first U-238 resonance)
95        let flight_path = 25.0; // meters (VENUS)
96        let tof = energy_to_tof(energy, flight_path);
97        let energy_back = tof_to_energy(tof, flight_path);
98        assert!((energy - energy_back).abs() < 1e-10);
99    }
100
101    #[test]
102    fn test_wavelength_thermal() {
103        // Thermal neutrons at 0.0253 eV should have λ ≈ 1.8 Å
104        let lambda = energy_to_wavelength_angstrom(0.0253);
105        assert!((lambda - 1.8).abs() < 0.1);
106    }
107}