elements_rs/isotopes/
argon.rs

1//! Isotopes of the element Argon
2#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4/// Isotopes of the element Argon
5pub enum ArgonIsotope {
6    /// Isotope Ar30 of Argon
7    Ar30,
8    /// Isotope Ar31 of Argon
9    Ar31,
10    /// Isotope Ar32 of Argon
11    Ar32,
12    /// Isotope Ar33 of Argon
13    Ar33,
14    /// Isotope Ar34 of Argon
15    Ar34,
16    /// Isotope Ar35 of Argon
17    Ar35,
18    /// Isotope Ar36 of Argon
19    Ar36,
20    /// Isotope Ar37 of Argon
21    Ar37,
22    /// Isotope Ar38 of Argon
23    Ar38,
24    /// Isotope Ar39 of Argon
25    Ar39,
26    /// Isotope Ar40 of Argon
27    Ar40,
28    /// Isotope Ar41 of Argon
29    Ar41,
30    /// Isotope Ar42 of Argon
31    Ar42,
32    /// Isotope Ar43 of Argon
33    Ar43,
34    /// Isotope Ar44 of Argon
35    Ar44,
36    /// Isotope Ar45 of Argon
37    Ar45,
38    /// Isotope Ar46 of Argon
39    Ar46,
40    /// Isotope Ar47 of Argon
41    Ar47,
42    /// Isotope Ar48 of Argon
43    Ar48,
44    /// Isotope Ar49 of Argon
45    Ar49,
46    /// Isotope Ar50 of Argon
47    Ar50,
48    /// Isotope Ar51 of Argon
49    Ar51,
50    /// Isotope Ar52 of Argon
51    Ar52,
52    /// Isotope Ar53 of Argon
53    Ar53,
54}
55impl super::RelativeAtomicMass for ArgonIsotope {
56    #[inline]
57    fn relative_atomic_mass(&self) -> f64 {
58        match self {
59            Self::Ar30 => 30.02307f64,
60            Self::Ar31 => 31.01212f64,
61            Self::Ar32 => 31.9976378f64,
62            Self::Ar33 => 32.98992555f64,
63            Self::Ar34 => 33.98027009f64,
64            Self::Ar35 => 34.97525759f64,
65            Self::Ar36 => 35.967545105f64,
66            Self::Ar37 => 36.96677633f64,
67            Self::Ar38 => 37.96273211f64,
68            Self::Ar39 => 38.964313f64,
69            Self::Ar40 => 39.9623831237f64,
70            Self::Ar41 => 40.96450057f64,
71            Self::Ar42 => 41.9630457f64,
72            Self::Ar43 => 42.9656361f64,
73            Self::Ar44 => 43.9649238f64,
74            Self::Ar45 => 44.96803973f64,
75            Self::Ar46 => 45.968083f64,
76            Self::Ar47 => 46.972935f64,
77            Self::Ar48 => 47.97591f64,
78            Self::Ar49 => 48.9819f64,
79            Self::Ar50 => 49.98613f64,
80            Self::Ar51 => 50.9937f64,
81            Self::Ar52 => 51.99896f64,
82            Self::Ar53 => 53.00729f64,
83        }
84    }
85}
86impl super::ElementVariant for ArgonIsotope {
87    #[inline]
88    fn element(&self) -> crate::Element {
89        crate::Element::Ar
90    }
91}
92impl super::MassNumber for ArgonIsotope {
93    #[inline]
94    fn mass_number(&self) -> u16 {
95        match self {
96            Self::Ar30 => 30u16,
97            Self::Ar31 => 31u16,
98            Self::Ar32 => 32u16,
99            Self::Ar33 => 33u16,
100            Self::Ar34 => 34u16,
101            Self::Ar35 => 35u16,
102            Self::Ar36 => 36u16,
103            Self::Ar37 => 37u16,
104            Self::Ar38 => 38u16,
105            Self::Ar39 => 39u16,
106            Self::Ar40 => 40u16,
107            Self::Ar41 => 41u16,
108            Self::Ar42 => 42u16,
109            Self::Ar43 => 43u16,
110            Self::Ar44 => 44u16,
111            Self::Ar45 => 45u16,
112            Self::Ar46 => 46u16,
113            Self::Ar47 => 47u16,
114            Self::Ar48 => 48u16,
115            Self::Ar49 => 49u16,
116            Self::Ar50 => 50u16,
117            Self::Ar51 => 51u16,
118            Self::Ar52 => 52u16,
119            Self::Ar53 => 53u16,
120        }
121    }
122}
123impl super::IsotopicComposition for ArgonIsotope {
124    #[inline]
125    fn isotopic_composition(&self) -> Option<f64> {
126        match self {
127            Self::Ar36 => Some(0.003336f64),
128            Self::Ar38 => Some(0.000629f64),
129            Self::Ar40 => Some(0.996035f64),
130            _ => None,
131        }
132    }
133}
134impl super::MostAbundantIsotope for ArgonIsotope {
135    fn most_abundant_isotope() -> Self {
136        Self::Ar40
137    }
138}
139impl From<ArgonIsotope> for crate::Isotope {
140    fn from(isotope: ArgonIsotope) -> Self {
141        crate::Isotope::Ar(isotope)
142    }
143}
144impl From<ArgonIsotope> for crate::Element {
145    fn from(_isotope: ArgonIsotope) -> Self {
146        crate::Element::Ar
147    }
148}
149impl TryFrom<u64> for ArgonIsotope {
150    type Error = crate::errors::Error;
151    fn try_from(value: u64) -> Result<Self, Self::Error> {
152        match value {
153            30u64 => Ok(Self::Ar30),
154            31u64 => Ok(Self::Ar31),
155            32u64 => Ok(Self::Ar32),
156            33u64 => Ok(Self::Ar33),
157            34u64 => Ok(Self::Ar34),
158            35u64 => Ok(Self::Ar35),
159            36u64 => Ok(Self::Ar36),
160            37u64 => Ok(Self::Ar37),
161            38u64 => Ok(Self::Ar38),
162            39u64 => Ok(Self::Ar39),
163            40u64 => Ok(Self::Ar40),
164            41u64 => Ok(Self::Ar41),
165            42u64 => Ok(Self::Ar42),
166            43u64 => Ok(Self::Ar43),
167            44u64 => Ok(Self::Ar44),
168            45u64 => Ok(Self::Ar45),
169            46u64 => Ok(Self::Ar46),
170            47u64 => Ok(Self::Ar47),
171            48u64 => Ok(Self::Ar48),
172            49u64 => Ok(Self::Ar49),
173            50u64 => Ok(Self::Ar50),
174            51u64 => Ok(Self::Ar51),
175            52u64 => Ok(Self::Ar52),
176            53u64 => Ok(Self::Ar53),
177            _ => Err(crate::errors::Error::Isotope(crate::Element::Ar, value)),
178        }
179    }
180}
181impl TryFrom<u8> for ArgonIsotope {
182    type Error = crate::errors::Error;
183    fn try_from(value: u8) -> Result<Self, Self::Error> {
184        Self::try_from(u64::from(value))
185    }
186}
187impl TryFrom<u16> for ArgonIsotope {
188    type Error = crate::errors::Error;
189    fn try_from(value: u16) -> Result<Self, Self::Error> {
190        Self::try_from(u64::from(value))
191    }
192}
193impl TryFrom<u32> for ArgonIsotope {
194    type Error = crate::errors::Error;
195    fn try_from(value: u32) -> Result<Self, Self::Error> {
196        Self::try_from(u64::from(value))
197    }
198}
199impl core::fmt::Display for ArgonIsotope {
200    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
201        match self {
202            Self::Ar30 => write!(f, "Ar30"),
203            Self::Ar31 => write!(f, "Ar31"),
204            Self::Ar32 => write!(f, "Ar32"),
205            Self::Ar33 => write!(f, "Ar33"),
206            Self::Ar34 => write!(f, "Ar34"),
207            Self::Ar35 => write!(f, "Ar35"),
208            Self::Ar36 => write!(f, "Ar36"),
209            Self::Ar37 => write!(f, "Ar37"),
210            Self::Ar38 => write!(f, "Ar38"),
211            Self::Ar39 => write!(f, "Ar39"),
212            Self::Ar40 => write!(f, "Ar40"),
213            Self::Ar41 => write!(f, "Ar41"),
214            Self::Ar42 => write!(f, "Ar42"),
215            Self::Ar43 => write!(f, "Ar43"),
216            Self::Ar44 => write!(f, "Ar44"),
217            Self::Ar45 => write!(f, "Ar45"),
218            Self::Ar46 => write!(f, "Ar46"),
219            Self::Ar47 => write!(f, "Ar47"),
220            Self::Ar48 => write!(f, "Ar48"),
221            Self::Ar49 => write!(f, "Ar49"),
222            Self::Ar50 => write!(f, "Ar50"),
223            Self::Ar51 => write!(f, "Ar51"),
224            Self::Ar52 => write!(f, "Ar52"),
225            Self::Ar53 => write!(f, "Ar53"),
226        }
227    }
228}
229#[cfg(test)]
230mod tests {
231    use strum::IntoEnumIterator;
232
233    use super::*;
234    use crate::isotopes::{
235        ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
236    };
237    #[test]
238    fn test_relative_atomic_mass() {
239        for isotope in ArgonIsotope::iter() {
240            let mass = isotope.relative_atomic_mass();
241            assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
242        }
243    }
244    #[test]
245    fn test_element() {
246        for isotope in ArgonIsotope::iter() {
247            let element = isotope.element();
248            assert_eq!(element, crate::Element::Ar, "Element should be correct for {isotope:?}");
249        }
250    }
251    #[test]
252    fn test_mass_number() {
253        for isotope in ArgonIsotope::iter() {
254            let mass_number = isotope.mass_number();
255            assert!(
256                mass_number > 0 && mass_number < 300,
257                "Mass number should be reasonable for {isotope:?}"
258            );
259        }
260    }
261    #[test]
262    fn test_isotopic_composition() {
263        for isotope in ArgonIsotope::iter() {
264            let comp = isotope.isotopic_composition();
265            if let Some(c) = comp {
266                assert!(
267                    (0.0..=1.0).contains(&c),
268                    "Composition should be between 0 and 1 for {isotope:?}"
269                );
270            }
271        }
272    }
273    #[test]
274    fn test_most_abundant() {
275        let most_abundant = ArgonIsotope::most_abundant_isotope();
276        let _ = most_abundant.relative_atomic_mass();
277    }
278    #[test]
279    fn test_from_isotope() {
280        for isotope in ArgonIsotope::iter() {
281            let iso: crate::Isotope = isotope.into();
282            match iso {
283                crate::Isotope::Ar(i) => assert_eq!(i, isotope),
284                _ => panic!("Wrong isotope type"),
285            }
286        }
287    }
288    #[test]
289    fn test_from_element() {
290        for isotope in ArgonIsotope::iter() {
291            let elem: crate::Element = isotope.into();
292            assert_eq!(elem, crate::Element::Ar);
293        }
294    }
295    #[test]
296    fn test_try_from_mass_number() {
297        for isotope in ArgonIsotope::iter() {
298            let mass = isotope.mass_number();
299            let iso = ArgonIsotope::try_from(mass).unwrap();
300            assert_eq!(iso, isotope);
301            let iso_u32 = ArgonIsotope::try_from(u32::from(mass)).unwrap();
302            assert_eq!(iso_u32, isotope);
303            if let Ok(mass_u8) = u8::try_from(mass) {
304                let iso_u8 = ArgonIsotope::try_from(mass_u8).unwrap();
305                assert_eq!(iso_u8, isotope);
306            }
307        }
308        assert!(ArgonIsotope::try_from(0_u16).is_err());
309        assert!(ArgonIsotope::try_from(1000_u16).is_err());
310        assert!(ArgonIsotope::try_from(0_u32).is_err());
311        assert!(ArgonIsotope::try_from(1000_u32).is_err());
312        assert!(ArgonIsotope::try_from(0_u8).is_err());
313    }
314    #[test]
315    fn test_display() {
316        for isotope in ArgonIsotope::iter() {
317            let s = alloc::format!("{isotope}");
318            assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
319        }
320    }
321}