nucleide_material/lib.rs
1//! Materials: compositions, mixing, and serialization for nuclear engineering.
2//!
3//! A [`Material`] is a map from [`NuclideId`] to a stored mass in grams,
4//! plus an optional mass density (g/cm3 by convention) and free-form JSON
5//! metadata. Density lives outside the composition: it is a property of
6//! the stream rather than part of the composition itself.
7//!
8//! Atomic-mass-dependent conversions ([`Material::from_atom_frac`] and
9//! [`Material::atom_fractions`]) take a [`MassProvider`] so the material
10//! crate stays independent of the nuclear-data tables; wire up
11//! `nucleide_nuclei::data` once it lands.
12//!
13//! ```
14//! use nucleide_material::{MassProvider, Material, NoMasses};
15//! use nucleide_nuclei::NuclideId;
16//!
17//! let mut mat = Material::new();
18//! mat.add_nuclide(NuclideId::from_name("U235").unwrap(), 19.0);
19//! mat.add_nuclide(NuclideId::from_name("U238").unwrap(), 1.0);
20//! assert_eq!(mat.mass(), 20.0);
21//!
22//! // Atom conversions need atomic masses:
23//! let atoms = mat.atom_fractions(&NoMasses);
24//! assert!(atoms.is_err());
25//! ```
26
27mod check;
28mod compendium;
29mod cusum;
30mod expansion;
31mod material;
32mod xml;
33
34pub use check::{audit, check_labels, AuditIssue, AuditKind, Collision, DEFAULT_WIDTHS};
35pub use compendium::{
36 CompendiumElement, CompendiumEntry, CompendiumIsotope, Error as CompendiumError,
37 MaterialsLibrary,
38};
39pub use cusum::Cusum;
40pub use expansion::{
41 parse_formula, AbundanceProvider, FormulaError, FormulaResult, NaturalAbundances, NoAbundances,
42};
43pub use material::{
44 Ame2020, Analytics, AnalyticsError, ChainDecays, DecayEnergies, DecayEnergyProvider,
45 DecayProvider, DoseFactors, DosePathway, DoseProvider, DoseSource, MassProvider, Material,
46 NoDecay, NoDecayEnergies, NoDoses, NoMasses, AVOGADRO, CI_PER_BQ, GRAMS_PER_U, MEV_TO_JOULES,
47 PCI_PER_BQ,
48};
49pub use xml::MaterialsDoc;
50
51use nucleide_nuclei::NuclideId;
52use thiserror::Error;
53
54/// Result alias for the material crate.
55pub type Result<T> = std::result::Result<T, Error>;
56
57/// Errors produced by material construction, conversion, and export.
58#[derive(Debug, Error)]
59pub enum Error {
60 /// A nuclide name could not be parsed.
61 #[error("invalid nuclide name `{name}`")]
62 BadNuclide {
63 /// The rejected name.
64 name: String,
65 /// Underlying parsing error from the nuclei crate.
66 #[source]
67 source: nucleide_nuclei::Error,
68 },
69 /// An atomic mass was required but not supplied.
70 #[error("no atomic mass available for nuclide `{0}`")]
71 MissingMass(NuclideId),
72 /// The composition is empty or its masses sum to a non-positive value.
73 #[error("material is empty or its masses sum to a non-positive value")]
74 Degenerate,
75 /// A volume-based operation hit a material without a density.
76 #[error("operation requires a mass density but none was set")]
77 MissingDensity,
78 /// A mixing fraction was negative.
79 #[error("negative mixing fraction `{0}`")]
80 NegativeFraction(f64),
81 /// A separation efficiency was outside `[0, 1]` or non-finite.
82 #[error("separation efficiency `{0}` is outside [0, 1]")]
83 InvalidEfficiency(f64),
84 /// A CUSUM detector parameter was invalid.
85 #[error("invalid CUSUM parameter: {0}")]
86 InvalidCusum(String),
87 /// Writing the XML document failed.
88 #[error(transparent)]
89 Write(#[from] std::io::Error),
90}