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