1pub fn mat_number(z: u32, a: u32) -> Option<u32> {
20 ENDF_MAT_TABLE
22 .binary_search_by(|&(tz, ta, _)| (tz, ta).cmp(&(z, a)))
23 .ok()
24 .map(|idx| ENDF_MAT_TABLE[idx].2)
25}
26
27pub fn isotope_from_mat(mat: u32) -> Option<(u32, u32)> {
37 ENDF_MAT_TABLE
39 .iter()
40 .find(|&&(_, _, m)| m == mat)
41 .map(|&(z, a, _)| (z, a))
42}
43
44pub fn known_isotopes(z: u32) -> Vec<u32> {
59 let start = ENDF_MAT_TABLE.partition_point(|&(tz, _, _)| tz < z);
60 ENDF_MAT_TABLE[start..]
61 .iter()
62 .take_while(|&&(tz, _, _)| tz == z)
63 .map(|&(_, a, _)| a)
64 .collect()
65}
66
67pub fn has_endf_evaluation(z: u32, a: u32) -> bool {
75 mat_number(z, a).is_some()
76}
77
78#[rustfmt::skip]
82static ENDF_MAT_TABLE: &[(u32, u32, u32)] = &[
83 (0, 1, 25),
84 (1, 1, 125),
85 (1, 2, 128),
86 (1, 3, 131),
87 (2, 3, 225),
88 (2, 4, 228),
89 (3, 6, 325),
90 (3, 7, 328),
91 (4, 7, 419),
92 (4, 9, 425),
93 (5, 10, 525),
94 (5, 11, 528),
95 (6, 12, 625),
96 (6, 13, 628),
97 (7, 14, 725),
98 (7, 15, 728),
99 (8, 16, 825),
100 (8, 17, 828),
101 (8, 18, 831),
102 (9, 19, 925),
103 (10, 20, 1025),
104 (10, 21, 1028),
105 (10, 22, 1031),
106 (11, 22, 1122),
107 (11, 23, 1125),
108 (12, 24, 1225),
109 (12, 25, 1228),
110 (12, 26, 1231),
111 (13, 27, 1325),
112 (14, 28, 1425),
113 (14, 29, 1428),
114 (14, 30, 1431),
115 (14, 31, 1434),
116 (14, 32, 1437),
117 (15, 31, 1525),
118 (16, 32, 1625),
119 (16, 33, 1628),
120 (16, 34, 1631),
121 (16, 35, 1634),
122 (16, 36, 1637),
123 (17, 35, 1725),
124 (17, 36, 1728),
125 (17, 37, 1731),
126 (18, 36, 1825),
127 (18, 37, 1828),
128 (18, 38, 1831),
129 (18, 39, 1834),
130 (18, 40, 1837),
131 (18, 41, 1840),
132 (19, 39, 1925),
133 (19, 40, 1928),
134 (19, 41, 1931),
135 (20, 40, 2025),
136 (20, 41, 2028),
137 (20, 42, 2031),
138 (20, 43, 2034),
139 (20, 44, 2037),
140 (20, 45, 2040),
141 (20, 46, 2043),
142 (20, 47, 2046),
143 (20, 48, 2049),
144 (21, 45, 2125),
145 (22, 46, 2225),
146 (22, 47, 2228),
147 (22, 48, 2231),
148 (22, 49, 2234),
149 (22, 50, 2237),
150 (23, 49, 2322),
151 (23, 50, 2325),
152 (23, 51, 2328),
153 (24, 50, 2425),
154 (24, 51, 2428),
155 (24, 52, 2431),
156 (24, 53, 2434),
157 (24, 54, 2437),
158 (25, 54, 2522),
159 (25, 55, 2525),
160 (26, 54, 2625),
161 (26, 55, 2628),
162 (26, 56, 2631),
163 (26, 57, 2634),
164 (26, 58, 2637),
165 (27, 58, 2722),
166 (27, 59, 2725),
167 (28, 58, 2825),
168 (28, 59, 2828),
169 (28, 60, 2831),
170 (28, 61, 2834),
171 (28, 62, 2837),
172 (28, 63, 2840),
173 (28, 64, 2843),
174 (29, 63, 2925),
175 (29, 64, 2928),
176 (29, 65, 2931),
177 (30, 64, 3025),
178 (30, 65, 3028),
179 (30, 66, 3031),
180 (30, 67, 3034),
181 (30, 68, 3037),
182 (30, 69, 3040),
183 (30, 70, 3043),
184 (31, 69, 3125),
185 (31, 70, 3128),
186 (31, 71, 3131),
187 (32, 70, 3225),
188 (32, 71, 3228),
189 (32, 72, 3231),
190 (32, 73, 3234),
191 (32, 74, 3237),
192 (32, 75, 3240),
193 (32, 76, 3243),
194 (33, 73, 3319),
195 (33, 74, 3322),
196 (33, 75, 3325),
197 (34, 74, 3425),
198 (34, 75, 3428),
199 (34, 76, 3431),
200 (34, 77, 3434),
201 (34, 78, 3437),
202 (34, 79, 3440),
203 (34, 80, 3443),
204 (34, 81, 3446),
205 (34, 82, 3449),
206 (35, 79, 3525),
207 (35, 80, 3528),
208 (35, 81, 3531),
209 (36, 78, 3625),
210 (36, 79, 3628),
211 (36, 80, 3631),
212 (36, 81, 3634),
213 (36, 82, 3637),
214 (36, 83, 3640),
215 (36, 84, 3643),
216 (36, 85, 3646),
217 (36, 86, 3649),
218 (37, 85, 3725),
219 (37, 86, 3728),
220 (37, 87, 3731),
221 (38, 84, 3825),
222 (38, 85, 3828),
223 (38, 86, 3831),
224 (38, 87, 3834),
225 (38, 88, 3837),
226 (38, 89, 3840),
227 (38, 90, 3843),
228 (39, 89, 3925),
229 (39, 90, 3928),
230 (39, 91, 3931),
231 (40, 90, 4025),
232 (40, 91, 4028),
233 (40, 92, 4031),
234 (40, 93, 4034),
235 (40, 94, 4037),
236 (40, 95, 4040),
237 (40, 96, 4043),
238 (41, 93, 4125),
239 (41, 94, 4128),
240 (41, 95, 4131),
241 (42, 92, 4225),
242 (42, 93, 4228),
243 (42, 94, 4231),
244 (42, 95, 4234),
245 (42, 96, 4237),
246 (42, 97, 4240),
247 (42, 98, 4243),
248 (42, 99, 4246),
249 (42, 100, 4249),
250 (43, 98, 4322),
251 (43, 99, 4325),
252 (44, 96, 4425),
253 (44, 97, 4428),
254 (44, 98, 4431),
255 (44, 99, 4434),
256 (44, 100, 4437),
257 (44, 101, 4440),
258 (44, 102, 4443),
259 (44, 103, 4446),
260 (44, 104, 4449),
261 (44, 105, 4452),
262 (44, 106, 4455),
263 (45, 103, 4525),
264 (45, 104, 4528),
265 (45, 105, 4531),
266 (46, 102, 4625),
267 (46, 103, 4628),
268 (46, 104, 4631),
269 (46, 105, 4634),
270 (46, 106, 4637),
271 (46, 107, 4640),
272 (46, 108, 4643),
273 (46, 109, 4646),
274 (46, 110, 4649),
275 (47, 107, 4725),
276 (47, 108, 4728),
277 (47, 109, 4731),
278 (47, 111, 4737),
279 (47, 112, 4740),
280 (47, 113, 4743),
281 (47, 114, 4746),
282 (47, 115, 4749),
283 (47, 116, 4752),
284 (47, 117, 4755),
285 (48, 106, 4825),
286 (48, 107, 4828),
287 (48, 108, 4831),
288 (48, 109, 4834),
289 (48, 110, 4837),
290 (48, 111, 4840),
291 (48, 112, 4843),
292 (48, 113, 4846),
293 (48, 114, 4849),
294 (48, 116, 4855),
295 (49, 113, 4925),
296 (49, 114, 4928),
297 (49, 115, 4931),
298 (50, 112, 5025),
299 (50, 113, 5028),
300 (50, 114, 5031),
301 (50, 115, 5034),
302 (50, 116, 5037),
303 (50, 117, 5040),
304 (50, 118, 5043),
305 (50, 119, 5046),
306 (50, 120, 5049),
307 (50, 122, 5055),
308 (50, 123, 5058),
309 (50, 124, 5061),
310 (50, 125, 5064),
311 (50, 126, 5067),
312 (51, 121, 5125),
313 (51, 122, 5128),
314 (51, 123, 5131),
315 (51, 124, 5134),
316 (51, 125, 5137),
317 (51, 126, 5140),
318 (52, 120, 5225),
319 (52, 121, 5228),
320 (52, 122, 5231),
321 (52, 123, 5234),
322 (52, 124, 5237),
323 (52, 125, 5240),
324 (52, 126, 5243),
325 (52, 128, 5249),
326 (52, 130, 5255),
327 (52, 131, 5258),
328 (52, 132, 5261),
329 (53, 127, 5325),
330 (53, 128, 5328),
331 (53, 129, 5331),
332 (53, 130, 5334),
333 (53, 131, 5337),
334 (53, 132, 5340),
335 (53, 133, 5343),
336 (53, 134, 5346),
337 (53, 135, 5349),
338 (54, 123, 5422),
339 (54, 124, 5425),
340 (54, 125, 5428),
341 (54, 126, 5431),
342 (54, 127, 5434),
343 (54, 128, 5437),
344 (54, 129, 5440),
345 (54, 130, 5443),
346 (54, 131, 5446),
347 (54, 132, 5449),
348 (54, 133, 5452),
349 (54, 134, 5455),
350 (54, 135, 5458),
351 (54, 136, 5461),
352 (55, 133, 5525),
353 (55, 134, 5528),
354 (55, 135, 5531),
355 (55, 136, 5534),
356 (55, 137, 5537),
357 (56, 130, 5625),
358 (56, 131, 5628),
359 (56, 132, 5631),
360 (56, 133, 5634),
361 (56, 134, 5637),
362 (56, 135, 5640),
363 (56, 136, 5643),
364 (56, 137, 5646),
365 (56, 138, 5649),
366 (56, 139, 5652),
367 (56, 140, 5655),
368 (57, 138, 5725),
369 (57, 139, 5728),
370 (57, 140, 5731),
371 (58, 136, 5825),
372 (58, 137, 5828),
373 (58, 138, 5831),
374 (58, 139, 5834),
375 (58, 140, 5837),
376 (58, 141, 5840),
377 (58, 142, 5843),
378 (58, 143, 5846),
379 (58, 144, 5849),
380 (59, 141, 5925),
381 (59, 142, 5928),
382 (59, 143, 5931),
383 (60, 142, 6025),
384 (60, 143, 6028),
385 (60, 144, 6031),
386 (60, 145, 6034),
387 (60, 146, 6037),
388 (60, 147, 6040),
389 (60, 148, 6043),
390 (60, 149, 6046),
391 (60, 150, 6049),
392 (61, 143, 6137),
393 (61, 144, 6140),
394 (61, 145, 6143),
395 (61, 146, 6146),
396 (61, 147, 6149),
397 (61, 148, 6152),
398 (61, 149, 6155),
399 (61, 150, 6158),
400 (61, 151, 6161),
401 (62, 144, 6225),
402 (62, 145, 6228),
403 (62, 146, 6231),
404 (62, 147, 6234),
405 (62, 148, 6237),
406 (62, 149, 6240),
407 (62, 150, 6243),
408 (62, 151, 6246),
409 (62, 152, 6249),
410 (62, 153, 6252),
411 (62, 154, 6255),
412 (63, 151, 6325),
413 (63, 152, 6328),
414 (63, 153, 6331),
415 (63, 154, 6334),
416 (63, 155, 6337),
417 (63, 156, 6340),
418 (63, 157, 6343),
419 (64, 152, 6425),
420 (64, 153, 6428),
421 (64, 154, 6431),
422 (64, 155, 6434),
423 (64, 156, 6437),
424 (64, 157, 6440),
425 (64, 158, 6443),
426 (64, 159, 6446),
427 (64, 160, 6449),
428 (65, 158, 6522),
429 (65, 159, 6525),
430 (65, 160, 6528),
431 (65, 161, 6531),
432 (66, 154, 6619),
433 (66, 155, 6622),
434 (66, 156, 6625),
435 (66, 157, 6628),
436 (66, 158, 6631),
437 (66, 159, 6634),
438 (66, 160, 6637),
439 (66, 161, 6640),
440 (66, 162, 6643),
441 (66, 163, 6646),
442 (66, 164, 6649),
443 (67, 165, 6725),
444 (68, 162, 6825),
445 (68, 163, 6828),
446 (68, 164, 6831),
447 (68, 165, 6834),
448 (68, 166, 6837),
449 (68, 167, 6840),
450 (68, 168, 6843),
451 (68, 169, 6846),
452 (68, 170, 6849),
453 (69, 168, 6922),
454 (69, 169, 6925),
455 (69, 170, 6928),
456 (69, 171, 6931),
457 (70, 168, 7025),
458 (70, 169, 7028),
459 (70, 170, 7031),
460 (70, 171, 7034),
461 (70, 172, 7037),
462 (70, 173, 7040),
463 (70, 174, 7043),
464 (70, 175, 7046),
465 (70, 176, 7049),
466 (71, 175, 7125),
467 (71, 176, 7128),
468 (72, 174, 7225),
469 (72, 175, 7228),
470 (72, 176, 7231),
471 (72, 177, 7234),
472 (72, 178, 7237),
473 (72, 179, 7240),
474 (72, 180, 7243),
475 (72, 181, 7246),
476 (72, 182, 7249),
477 (73, 180, 7325),
478 (73, 181, 7328),
479 (73, 182, 7331),
480 (74, 180, 7425),
481 (74, 181, 7428),
482 (74, 182, 7431),
483 (74, 183, 7434),
484 (74, 184, 7437),
485 (74, 185, 7440),
486 (74, 186, 7443),
487 (75, 185, 7525),
488 (75, 187, 7531),
489 (76, 184, 7625),
490 (76, 185, 7628),
491 (76, 186, 7631),
492 (76, 187, 7634),
493 (76, 188, 7637),
494 (76, 189, 7640),
495 (76, 190, 7643),
496 (76, 191, 7646),
497 (76, 192, 7649),
498 (77, 191, 7725),
499 (77, 192, 7728),
500 (77, 193, 7731),
501 (78, 190, 7825),
502 (78, 191, 7828),
503 (78, 192, 7831),
504 (78, 193, 7834),
505 (78, 194, 7837),
506 (78, 195, 7840),
507 (78, 196, 7843),
508 (78, 197, 7846),
509 (78, 198, 7849),
510 (79, 197, 7925),
511 (80, 196, 8025),
512 (80, 197, 8028),
513 (80, 198, 8031),
514 (80, 199, 8034),
515 (80, 200, 8037),
516 (80, 201, 8040),
517 (80, 202, 8043),
518 (80, 203, 8046),
519 (80, 204, 8049),
520 (81, 203, 8125),
521 (81, 204, 8128),
522 (81, 205, 8131),
523 (82, 204, 8225),
524 (82, 205, 8228),
525 (82, 206, 8231),
526 (82, 207, 8234),
527 (82, 208, 8237),
528 (83, 209, 8325),
529 (84, 208, 8431),
530 (84, 209, 8434),
531 (84, 210, 8437),
532 (88, 223, 8825),
533 (88, 224, 8828),
534 (88, 225, 8831),
535 (88, 226, 8834),
536 (89, 225, 8925),
537 (89, 226, 8928),
538 (89, 227, 8931),
539 (90, 227, 9025),
540 (90, 228, 9028),
541 (90, 229, 9031),
542 (90, 230, 9034),
543 (90, 231, 9037),
544 (90, 232, 9040),
545 (90, 233, 9043),
546 (90, 234, 9046),
547 (91, 229, 9125),
548 (91, 230, 9128),
549 (91, 231, 9131),
550 (91, 232, 9134),
551 (91, 233, 9137),
552 (92, 230, 9213),
553 (92, 231, 9216),
554 (92, 232, 9219),
555 (92, 233, 9222),
556 (92, 234, 9225),
557 (92, 235, 9228),
558 (92, 236, 9231),
559 (92, 237, 9234),
560 (92, 238, 9237),
561 (92, 239, 9240),
562 (92, 240, 9243),
563 (92, 241, 9246),
564 (93, 234, 9337),
565 (93, 235, 9340),
566 (93, 236, 9343),
567 (93, 237, 9346),
568 (93, 238, 9349),
569 (93, 239, 9352),
570 (94, 236, 9428),
571 (94, 237, 9431),
572 (94, 238, 9434),
573 (94, 239, 9437),
574 (94, 240, 9440),
575 (94, 241, 9443),
576 (94, 242, 9446),
577 (94, 243, 9449),
578 (94, 244, 9452),
579 (94, 245, 9455),
580 (94, 246, 9458),
581 (95, 240, 9540),
582 (95, 241, 9543),
583 (95, 242, 9546),
584 (95, 243, 9549),
585 (95, 244, 9552),
586 (96, 240, 9625),
587 (96, 241, 9628),
588 (96, 242, 9631),
589 (96, 243, 9634),
590 (96, 244, 9637),
591 (96, 245, 9640),
592 (96, 246, 9643),
593 (96, 247, 9646),
594 (96, 248, 9649),
595 (96, 249, 9652),
596 (96, 250, 9655),
597 (97, 245, 9740),
598 (97, 246, 9743),
599 (97, 247, 9746),
600 (97, 248, 9749),
601 (97, 249, 9752),
602 (97, 250, 9755),
603 (98, 246, 9843),
604 (98, 247, 9846),
605 (98, 248, 9849),
606 (98, 249, 9852),
607 (98, 250, 9855),
608 (98, 251, 9858),
609 (98, 252, 9861),
610 (98, 253, 9864),
611 (98, 254, 9867),
612 (99, 251, 9911),
613 (99, 252, 9912),
614 (99, 253, 9913),
615 (99, 254, 9914),
616 (99, 255, 9916),
617 (100, 255, 9936),
618];
619
620#[cfg(test)]
621mod tests {
622 use super::*;
623
624 #[test]
625 fn test_mat_number_known_values() {
626 assert_eq!(mat_number(92, 235), Some(9228));
627 assert_eq!(mat_number(92, 238), Some(9237));
628 assert_eq!(mat_number(26, 56), Some(2631));
629 assert_eq!(mat_number(1, 1), Some(125));
630 assert_eq!(mat_number(0, 1), Some(25)); assert_eq!(mat_number(94, 239), Some(9437));
632 }
633
634 #[test]
635 fn test_mat_number_tungsten() {
636 assert_eq!(mat_number(74, 182), Some(7431));
637 assert_eq!(mat_number(74, 183), Some(7434));
638 assert_eq!(mat_number(74, 184), Some(7437));
639 assert_eq!(mat_number(74, 186), Some(7443));
640 }
641
642 #[test]
643 fn test_mat_number_tin_expansion() {
644 assert_eq!(mat_number(50, 120), Some(5049));
646 assert_eq!(mat_number(50, 116), Some(5037));
647 assert_eq!(mat_number(50, 118), Some(5043));
648 }
649
650 #[test]
651 fn test_mat_number_corrected_regressions() {
652 assert_eq!(mat_number(48, 113), Some(4846));
658 assert_eq!(isotope_from_mat(4846), Some((48, 113)));
659
660 assert_eq!(mat_number(72, 177), Some(7234));
662 assert_eq!(isotope_from_mat(7234), Some((72, 177)));
663
664 assert_eq!(mat_number(72, 178), Some(7237));
666 assert_eq!(isotope_from_mat(7237), Some((72, 178)));
667
668 assert_eq!(mat_number(74, 182), Some(7431));
670 assert_eq!(mat_number(74, 183), Some(7434));
671 assert_eq!(mat_number(74, 184), Some(7437));
672 assert_eq!(mat_number(74, 186), Some(7443));
673 }
674
675 #[test]
676 fn test_mat_number_unknown() {
677 assert_eq!(mat_number(200, 400), None);
678 assert_eq!(mat_number(0, 0), None);
679 }
680
681 #[test]
682 fn test_isotope_from_mat() {
683 assert_eq!(isotope_from_mat(9228), Some((92, 235)));
684 assert_eq!(isotope_from_mat(9237), Some((92, 238)));
685 assert_eq!(isotope_from_mat(2631), Some((26, 56)));
686 assert_eq!(isotope_from_mat(25), Some((0, 1))); }
688
689 #[test]
690 fn test_isotope_from_mat_unknown() {
691 assert_eq!(isotope_from_mat(9999), None);
692 assert_eq!(isotope_from_mat(0), None);
693 }
694
695 #[test]
696 fn test_mat_roundtrip() {
697 for &(z, a, mat) in ENDF_MAT_TABLE.iter() {
698 assert_eq!(
699 mat_number(z, a),
700 Some(mat),
701 "mat_number({}, {}) failed",
702 z,
703 a
704 );
705 assert_eq!(
706 isotope_from_mat(mat),
707 Some((z, a)),
708 "isotope_from_mat({}) failed",
709 mat
710 );
711 }
712 }
713
714 #[test]
715 fn test_table_size() {
716 assert_eq!(ENDF_MAT_TABLE.len(), 535);
717 }
718
719 #[test]
720 fn test_known_isotopes_plutonium() {
721 let pu = known_isotopes(94);
722 assert_eq!(
723 pu,
724 vec![236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246]
725 );
726 }
727
728 #[test]
729 fn test_known_isotopes_technetium() {
730 let tc = known_isotopes(43);
732 assert_eq!(tc, vec![98, 99]);
733 }
734
735 #[test]
736 fn test_known_isotopes_iron() {
737 let fe = known_isotopes(26);
738 assert_eq!(fe, vec![54, 55, 56, 57, 58]);
739 }
740
741 #[test]
742 fn test_known_isotopes_unknown() {
743 assert!(known_isotopes(200).is_empty());
744 assert!(known_isotopes(119).is_empty());
745 }
746
747 #[test]
748 fn test_known_isotopes_superset_of_natural() {
749 use crate::abundances::natural_isotopes;
750 for z in 1..=92 {
751 let natural_a: Vec<u32> = natural_isotopes(z).into_iter().map(|(a, _)| a).collect();
752 let known_a = known_isotopes(z);
753 for a in &natural_a {
754 assert!(
755 known_a.contains(a),
756 "Z={z}, A={a} is natural but not in known_isotopes"
757 );
758 }
759 }
760 }
761
762 #[test]
763 fn test_has_endf_evaluation() {
764 assert!(has_endf_evaluation(94, 239)); assert!(has_endf_evaluation(92, 235)); assert!(!has_endf_evaluation(94, 999)); assert!(!has_endf_evaluation(200, 400));
768 }
769
770 #[test]
771 fn test_table_sorted() {
772 for i in 1..ENDF_MAT_TABLE.len() {
773 let (z1, a1, _) = ENDF_MAT_TABLE[i - 1];
774 let (z2, a2, _) = ENDF_MAT_TABLE[i];
775 assert!(
776 (z1, a1) < (z2, a2),
777 "Table not sorted at index {}: ({}, {}) >= ({}, {})",
778 i,
779 z1,
780 a1,
781 z2,
782 a2
783 );
784 }
785 }
786}