Skip to main content

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}