1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, strum :: EnumIter)]
3#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
4#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
5pub enum PlutoniumIsotope {
7 Pu228,
9 Pu229,
11 Pu230,
13 Pu231,
15 Pu232,
17 Pu233,
19 Pu234,
21 Pu235,
23 Pu236,
25 Pu237,
27 Pu238,
29 Pu239,
31 Pu240,
33 Pu241,
35 Pu242,
37 Pu243,
39 Pu244,
41 Pu245,
43 Pu246,
45 Pu247,
47}
48impl super::RelativeAtomicMass for PlutoniumIsotope {
49 #[inline]
50 fn relative_atomic_mass(&self) -> f64 {
51 match self {
52 Self::Pu228 => 228.038732f64,
53 Self::Pu229 => 229.040144f64,
54 Self::Pu230 => 230.03965f64,
55 Self::Pu231 => 231.041102f64,
56 Self::Pu232 => 232.041185f64,
57 Self::Pu233 => 233.042998f64,
58 Self::Pu234 => 234.0433174f64,
59 Self::Pu235 => 235.045286f64,
60 Self::Pu236 => 236.0460581f64,
61 Self::Pu237 => 237.0484098f64,
62 Self::Pu238 => 238.0495601f64,
63 Self::Pu239 => 239.0521636f64,
64 Self::Pu240 => 240.0538138f64,
65 Self::Pu241 => 241.0568517f64,
66 Self::Pu242 => 242.0587428f64,
67 Self::Pu243 => 243.0620036f64,
68 Self::Pu244 => 244.0642053f64,
69 Self::Pu245 => 245.067826f64,
70 Self::Pu246 => 246.070205f64,
71 Self::Pu247 => 247.07419f64,
72 }
73 }
74}
75impl super::ElementVariant for PlutoniumIsotope {
76 #[inline]
77 fn element(&self) -> crate::Element {
78 crate::Element::Pu
79 }
80}
81impl super::MassNumber for PlutoniumIsotope {
82 #[inline]
83 fn mass_number(&self) -> u16 {
84 match self {
85 Self::Pu228 => 228u16,
86 Self::Pu229 => 229u16,
87 Self::Pu230 => 230u16,
88 Self::Pu231 => 231u16,
89 Self::Pu232 => 232u16,
90 Self::Pu233 => 233u16,
91 Self::Pu234 => 234u16,
92 Self::Pu235 => 235u16,
93 Self::Pu236 => 236u16,
94 Self::Pu237 => 237u16,
95 Self::Pu238 => 238u16,
96 Self::Pu239 => 239u16,
97 Self::Pu240 => 240u16,
98 Self::Pu241 => 241u16,
99 Self::Pu242 => 242u16,
100 Self::Pu243 => 243u16,
101 Self::Pu244 => 244u16,
102 Self::Pu245 => 245u16,
103 Self::Pu246 => 246u16,
104 Self::Pu247 => 247u16,
105 }
106 }
107}
108impl super::IsotopicComposition for PlutoniumIsotope {
109 #[inline]
110 fn isotopic_composition(&self) -> Option<f64> {
111 None
112 }
113}
114impl super::MostAbundantIsotope for PlutoniumIsotope {
115 fn most_abundant_isotope() -> Self {
116 Self::Pu247
117 }
118}
119impl From<PlutoniumIsotope> for crate::Isotope {
120 fn from(isotope: PlutoniumIsotope) -> Self {
121 crate::Isotope::Pu(isotope)
122 }
123}
124impl From<PlutoniumIsotope> for crate::Element {
125 fn from(_isotope: PlutoniumIsotope) -> Self {
126 crate::Element::Pu
127 }
128}
129impl TryFrom<u64> for PlutoniumIsotope {
130 type Error = crate::errors::Error;
131 fn try_from(value: u64) -> Result<Self, Self::Error> {
132 match value {
133 228u64 => Ok(Self::Pu228),
134 229u64 => Ok(Self::Pu229),
135 230u64 => Ok(Self::Pu230),
136 231u64 => Ok(Self::Pu231),
137 232u64 => Ok(Self::Pu232),
138 233u64 => Ok(Self::Pu233),
139 234u64 => Ok(Self::Pu234),
140 235u64 => Ok(Self::Pu235),
141 236u64 => Ok(Self::Pu236),
142 237u64 => Ok(Self::Pu237),
143 238u64 => Ok(Self::Pu238),
144 239u64 => Ok(Self::Pu239),
145 240u64 => Ok(Self::Pu240),
146 241u64 => Ok(Self::Pu241),
147 242u64 => Ok(Self::Pu242),
148 243u64 => Ok(Self::Pu243),
149 244u64 => Ok(Self::Pu244),
150 245u64 => Ok(Self::Pu245),
151 246u64 => Ok(Self::Pu246),
152 247u64 => Ok(Self::Pu247),
153 _ => Err(crate::errors::Error::Isotope(crate::Element::Pu, value)),
154 }
155 }
156}
157impl TryFrom<u8> for PlutoniumIsotope {
158 type Error = crate::errors::Error;
159 fn try_from(value: u8) -> Result<Self, Self::Error> {
160 Self::try_from(u64::from(value))
161 }
162}
163impl TryFrom<u16> for PlutoniumIsotope {
164 type Error = crate::errors::Error;
165 fn try_from(value: u16) -> Result<Self, Self::Error> {
166 Self::try_from(u64::from(value))
167 }
168}
169impl TryFrom<u32> for PlutoniumIsotope {
170 type Error = crate::errors::Error;
171 fn try_from(value: u32) -> Result<Self, Self::Error> {
172 Self::try_from(u64::from(value))
173 }
174}
175impl core::fmt::Display for PlutoniumIsotope {
176 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177 match self {
178 Self::Pu228 => write!(f, "Pu228"),
179 Self::Pu229 => write!(f, "Pu229"),
180 Self::Pu230 => write!(f, "Pu230"),
181 Self::Pu231 => write!(f, "Pu231"),
182 Self::Pu232 => write!(f, "Pu232"),
183 Self::Pu233 => write!(f, "Pu233"),
184 Self::Pu234 => write!(f, "Pu234"),
185 Self::Pu235 => write!(f, "Pu235"),
186 Self::Pu236 => write!(f, "Pu236"),
187 Self::Pu237 => write!(f, "Pu237"),
188 Self::Pu238 => write!(f, "Pu238"),
189 Self::Pu239 => write!(f, "Pu239"),
190 Self::Pu240 => write!(f, "Pu240"),
191 Self::Pu241 => write!(f, "Pu241"),
192 Self::Pu242 => write!(f, "Pu242"),
193 Self::Pu243 => write!(f, "Pu243"),
194 Self::Pu244 => write!(f, "Pu244"),
195 Self::Pu245 => write!(f, "Pu245"),
196 Self::Pu246 => write!(f, "Pu246"),
197 Self::Pu247 => write!(f, "Pu247"),
198 }
199 }
200}
201#[cfg(test)]
202mod tests {
203 use strum::IntoEnumIterator;
204
205 use super::*;
206 use crate::isotopes::{
207 ElementVariant, IsotopicComposition, MassNumber, MostAbundantIsotope, RelativeAtomicMass,
208 };
209 #[test]
210 fn test_relative_atomic_mass() {
211 for isotope in PlutoniumIsotope::iter() {
212 let mass = isotope.relative_atomic_mass();
213 assert!(mass > 0.0, "Mass should be positive for {isotope:?}");
214 }
215 }
216 #[test]
217 fn test_element() {
218 for isotope in PlutoniumIsotope::iter() {
219 let element = isotope.element();
220 assert_eq!(element, crate::Element::Pu, "Element should be correct for {isotope:?}");
221 }
222 }
223 #[test]
224 fn test_mass_number() {
225 for isotope in PlutoniumIsotope::iter() {
226 let mass_number = isotope.mass_number();
227 assert!(
228 mass_number > 0 && mass_number < 300,
229 "Mass number should be reasonable for {isotope:?}"
230 );
231 }
232 }
233 #[test]
234 fn test_isotopic_composition() {
235 for isotope in PlutoniumIsotope::iter() {
236 let comp = isotope.isotopic_composition();
237 if let Some(c) = comp {
238 assert!(
239 (0.0..=1.0).contains(&c),
240 "Composition should be between 0 and 1 for {isotope:?}"
241 );
242 }
243 }
244 }
245 #[test]
246 fn test_most_abundant() {
247 let most_abundant = PlutoniumIsotope::most_abundant_isotope();
248 let _ = most_abundant.relative_atomic_mass();
249 }
250 #[test]
251 fn test_from_isotope() {
252 for isotope in PlutoniumIsotope::iter() {
253 let iso: crate::Isotope = isotope.into();
254 match iso {
255 crate::Isotope::Pu(i) => assert_eq!(i, isotope),
256 _ => panic!("Wrong isotope type"),
257 }
258 }
259 }
260 #[test]
261 fn test_from_element() {
262 for isotope in PlutoniumIsotope::iter() {
263 let elem: crate::Element = isotope.into();
264 assert_eq!(elem, crate::Element::Pu);
265 }
266 }
267 #[test]
268 fn test_try_from_mass_number() {
269 for isotope in PlutoniumIsotope::iter() {
270 let mass = isotope.mass_number();
271 let iso = PlutoniumIsotope::try_from(mass).unwrap();
272 assert_eq!(iso, isotope);
273 let iso_u32 = PlutoniumIsotope::try_from(u32::from(mass)).unwrap();
274 assert_eq!(iso_u32, isotope);
275 if let Ok(mass_u8) = u8::try_from(mass) {
276 let iso_u8 = PlutoniumIsotope::try_from(mass_u8).unwrap();
277 assert_eq!(iso_u8, isotope);
278 }
279 }
280 assert!(PlutoniumIsotope::try_from(0_u16).is_err());
281 assert!(PlutoniumIsotope::try_from(1000_u16).is_err());
282 assert!(PlutoniumIsotope::try_from(0_u32).is_err());
283 assert!(PlutoniumIsotope::try_from(1000_u32).is_err());
284 assert!(PlutoniumIsotope::try_from(0_u8).is_err());
285 }
286 #[test]
287 fn test_display() {
288 for isotope in PlutoniumIsotope::iter() {
289 let s = alloc::format!("{isotope}");
290 assert!(!s.is_empty(), "Display should not be empty for {isotope:?}");
291 }
292 }
293}