Skip to main content

lindhard/electron/inelastic/
bethe.rs

1//! Nonrelativistic Bethe stopping, the high-energy reference for the
2//! dielectric models.
3//!
4//! The Bethe equation as given by the Particle Data Group, S. Navas et al.,
5//! Phys. Rev. D 110, 030001 (2024), review 34 "Passage of particles through
6//! matter" (D. E. Groom and S. R. Klein, rev. August 2023), eq. (34.5):
7//!
8//! ```text
9//! -dE/dx = K z² (Z/A) (1/β²) [ (1/2) ln(2 m_e c² β² γ² W_max / I²) - β² - δ(βγ)/2 ].
10//! ```
11//!
12//! Here it is used **nonrelativistically and for a unit charge** (`z = 1`,
13//! `γ -> 1`, the `-β²` and density-effect terms dropped, `m_e c² β² = m_e v²
14//! = 2E` for an electron of kinetic energy `E`), and as a linear stopping
15//! power for an electron density `n` (the `K (Z/A) ρ` of the mass stopping
16//! power is `4π n r_e² m_e c²`):
17//!
18//! ```text
19//! S(E) = (4π n (e²/4πε₀)² / (m_e v²)) · (1/2) ln(2 m_e v² W_max / I²)
20//!      = (2π n (e²/4πε₀)² / E) · (1/2) ln(4 E W_max / I²).
21//! ```
22//!
23//! `W_max` is the largest energy loss the model allows. The PDG gives eq.
24//! (34.5) for heavy particles, where `W_max` is the kinematic maximum
25//! transfer to a free electron; for an incident electron the recommended
26//! stopping formula differs (identical-particle exchange). The single-pole
27//! Penn model has no exchange and allows losses up to the full kinetic energy
28//! (`W_max = E`), so its high-energy limit is the expression above with
29//! `W_max = E`, `S = (2π n (e²/4πε₀)² / E) ln(2E/I)`. That is the comparison
30//! this module exists for; it is not a recommended electron stopping power.
31
32use crate::constants::{COULOMB_E2, ELEMENTARY_CHARGE};
33
34/// Nonrelativistic Bethe stopping power of a unit-charge particle of
35/// electron mass (see the module docs), eV/m.
36///
37/// `electron_density_per_m3` is the density of the electrons the mean
38/// excitation energy `mean_excitation_ev` refers to, `energy_ev` the kinetic
39/// energy and `max_loss_ev` the largest energy loss `W_max`. Returns `NaN`
40/// unless all four are finite and positive.
41pub fn stopping_power_ev_per_m(
42    electron_density_per_m3: f64,
43    mean_excitation_ev: f64,
44    energy_ev: f64,
45    max_loss_ev: f64,
46) -> f64 {
47    let ok = [
48        electron_density_per_m3,
49        mean_excitation_ev,
50        energy_ev,
51        max_loss_ev,
52    ]
53    .iter()
54    .all(|v| v.is_finite() && *v > 0.0);
55    if !ok {
56        return f64::NAN;
57    }
58    let e_j = energy_ev * ELEMENTARY_CHARGE;
59    let log =
60        0.5 * (4.0 * energy_ev * max_loss_ev / (mean_excitation_ev * mean_excitation_ev)).ln();
61    // J/m -> eV/m
62    2.0 * std::f64::consts::PI * electron_density_per_m3 * COULOMB_E2 * COULOMB_E2 / e_j * log
63        / ELEMENTARY_CHARGE
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69
70    #[test]
71    fn matches_the_atomic_unit_form() {
72        // In Hartree atomic units S = (Ω²/(2E)) ln(2E/I) with Ω² = 4π n,
73        // for W_max = E. Check the SI evaluation against it.
74        let a0 = crate::constants::BOHR_RADIUS;
75        let eh = crate::constants::HARTREE_ENERGY / ELEMENTARY_CHARGE;
76        let (n_au, e_au, i_au) = (0.05, 300.0, 0.9);
77        let want_au = 4.0 * std::f64::consts::PI * n_au / (2.0 * e_au) * (2.0 * e_au / i_au).ln();
78        let got = stopping_power_ev_per_m(n_au / a0.powi(3), i_au * eh, e_au * eh, e_au * eh);
79        let got_au = got * a0 / eh;
80        // e²/(4πε₀) = 1 hartree bohr holds to the CODATA rounding, ~1e-10.
81        assert!(
82            (got_au / want_au - 1.0).abs() < 1e-9,
83            "{got_au} vs {want_au}"
84        );
85        assert!(stopping_power_ev_per_m(1e29, 0.0, 1e3, 1e3).is_nan());
86    }
87}