nucleide-material 0.15.0

Nuclear material compositions: mixing, conversions, materials XML export
Documentation
#![warn(missing_docs)]
//! Materials: compositions, mixing, and serialization for nuclear engineering.
//!
//! A [`Material`] is a map from [`NuclideId`] to a stored mass in grams,
//! plus an optional mass density (g/cm3 by convention) and free-form JSON
//! metadata. Density lives outside the composition: it is a property of
//! the stream rather than part of the composition itself.
//!
//! Atomic-mass-dependent conversions ([`Material::from_atom_frac`] and
//! [`Material::atom_fractions`]) take a [`MassProvider`] so the material
//! crate stays independent of the nuclear-data tables; wire up
//! `nucleide_nuclei::data` once it lands.
//!
//! ```
//! use nucleide_material::{MassProvider, Material, NoMasses};
//! use nucleide_nuclei::NuclideId;
//!
//! let mut mat = Material::new();
//! mat.add_nuclide(NuclideId::from_name("U235").unwrap(), 19.0);
//! mat.add_nuclide(NuclideId::from_name("U238").unwrap(), 1.0);
//! assert_eq!(mat.mass(), 20.0);
//!
//! // Atom conversions need atomic masses:
//! let atoms = mat.atom_fractions(&NoMasses);
//! assert!(atoms.is_err());
//! ```

mod check;
mod compendium;
mod cusum;
mod expansion;
mod material;
mod xml;

pub use check::{audit, check_labels, AuditIssue, AuditKind, Collision, DEFAULT_WIDTHS};
pub use compendium::{
    CompendiumElement, CompendiumEntry, CompendiumIsotope, Error as CompendiumError,
    MaterialsLibrary,
};
pub use cusum::Cusum;
pub use expansion::{
    parse_formula, AbundanceProvider, FormulaError, FormulaResult, NaturalAbundances, NoAbundances,
};
pub use material::{
    Ame2020, Analytics, AnalyticsError, ChainDecays, DecayEnergies, DecayEnergyProvider,
    DecayProvider, DoseFactors, DosePathway, DoseProvider, DoseSource, MassProvider, Material,
    NoDecay, NoDecayEnergies, NoDoses, NoMasses, AVOGADRO, CI_PER_BQ, GRAMS_PER_U, MEV_TO_JOULES,
    PCI_PER_BQ,
};
pub use xml::MaterialsDoc;

use nucleide_nuclei::NuclideId;
use thiserror::Error;

/// Result alias for the material crate.
pub type Result<T> = std::result::Result<T, Error>;

/// Errors produced by material construction, conversion, and export.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
    /// A nuclide name could not be parsed.
    #[error("invalid nuclide name `{name}`")]
    BadNuclide {
        /// The rejected name.
        name: String,
        /// Underlying parsing error from the nuclei crate.
        #[source]
        source: nucleide_nuclei::Error,
    },
    /// An atomic mass was required but not supplied.
    #[error("no atomic mass available for nuclide `{0}`")]
    MissingMass(NuclideId),
    /// The composition is empty or its masses sum to a non-positive value.
    #[error("material is empty or its masses sum to a non-positive value")]
    Degenerate,
    /// A volume-based operation hit a material without a density.
    #[error("operation requires a mass density but none was set")]
    MissingDensity,
    /// A mixing fraction was negative.
    #[error("negative mixing fraction `{0}`")]
    NegativeFraction(f64),
    /// A separation efficiency was outside `[0, 1]` or non-finite.
    #[error("separation efficiency `{0}` is outside [0, 1]")]
    InvalidEfficiency(f64),
    /// A CUSUM detector parameter was invalid.
    #[error("invalid CUSUM parameter: {0}")]
    InvalidCusum(String),
    /// Writing the XML document failed.
    #[error(transparent)]
    Write(#[from] std::io::Error),
}