lindhard/ion/stopping/none.rs
1//! No electronic stopping: the nuclear-only limit.
2//!
3//! [`NoStopping`] returns zero for every ion, target and energy, so a run
4//! loses energy only in nuclear collisions. This is not a physical model of
5//! any target. It is the `k = 0` limit of the classical range theory, where
6//! the electronic stopping coefficient vanishes and only nuclear stopping
7//! remains (J. Lindhard, M. Scharff and H. E. Schiott, Mat. Fys. Medd. Dan.
8//! Vid. Selsk. 33 (14) (1963)), and it serves two purposes here:
9//!
10//! * like-for-like transport comparisons against a code run with its
11//! electronic stopping switched off, and
12//! * nuclear-only checks (range and damage limits) that isolate the
13//! scattering and cascade machinery from any stopping model.
14//!
15//! It has no energy range of its own: [`ElectronicStopping::validity`] is
16//! unbounded, so no out-of-range warning is ever raised for it.
17
18use super::{ElectronicStopping, Ion, StoppingError, ValidityRange};
19
20/// Zero electronic stopping (name `"none"`). Stateless, so bitwise
21/// reproducible across threads like every model in this module.
22#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
23pub struct NoStopping;
24
25impl NoStopping {
26 /// The (only) zero-stopping model.
27 pub fn new() -> Self {
28 Self
29 }
30}
31
32impl ElectronicStopping for NoStopping {
33 fn name(&self) -> &'static str {
34 "none"
35 }
36
37 /// Always `0.0` J m². The arguments are not checked: there is no formula
38 /// to be outside of.
39 fn stopping(&self, _ion: &Ion, _target_z: u8, _energy_ev: f64) -> Result<f64, StoppingError> {
40 Ok(0.0)
41 }
42
43 /// Unbounded: `[0, inf)` eV.
44 fn validity(&self, _ion: &Ion) -> ValidityRange {
45 ValidityRange {
46 min_energy_ev: 0.0,
47 max_energy_ev: f64::INFINITY,
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn zero_everywhere_and_unbounded() {
58 let m = NoStopping::new();
59 for z1 in [1, 5, 14, 33, 92] {
60 let ion = Ion::new(z1).unwrap();
61 for e in [1.0e-3, 1.0, 5.0e3, 1.0e9] {
62 assert_eq!(m.stopping(&ion, 14, e).unwrap().to_bits(), 0.0f64.to_bits());
63 assert!(m.validity(&ion).contains(e));
64 }
65 }
66 assert_eq!(m.name(), "none");
67 }
68}