OpenMC/openmc/data/dose/mass_attenuation.py

153 lines
5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from pathlib import Path
import numpy as np
import h5py
import openmc.checkvalue as cv
from openmc.data import EV_PER_MEV
from ..data import ATOMIC_NUMBER
from ..function import Tabulated1D
# Embedded NIST-126 data
# Air (Dry Near Sea Level) — NIST Standard Reference Database 126 Table 4 (doi: 10.18434/T4D01F)
# Columns: Energy (MeV), μ_en/ρ (cm^2/g)
_NIST126_AIR = np.array([
[1.00000e-03, 3.599e03],
[1.50000e-03, 1.188e03],
[2.00000e-03, 5.262e02],
[3.00000e-03, 1.614e02],
[3.20290e-03, 1.330e02],
[3.20290e-03, 1.460e02],
[4.00000e-03, 7.636e01],
[5.00000e-03, 3.931e01],
[6.00000e-03, 2.270e01],
[8.00000e-03, 9.446e00],
[1.00000e-02, 4.742e00],
[1.50000e-02, 1.334e00],
[2.00000e-02, 5.389e-01],
[3.00000e-02, 1.537e-01],
[4.00000e-02, 6.833e-02],
[5.00000e-02, 4.098e-02],
[6.00000e-02, 3.041e-02],
[8.00000e-02, 2.407e-02],
[1.00000e-01, 2.325e-02],
[1.50000e-01, 2.496e-02],
[2.00000e-01, 2.672e-02],
[3.00000e-01, 2.872e-02],
[4.00000e-01, 2.949e-02],
[5.00000e-01, 2.966e-02],
[6.00000e-01, 2.953e-02],
[8.00000e-01, 2.882e-02],
[1.00000e00, 2.789e-02],
[1.25000e00, 2.666e-02],
[1.50000e00, 2.547e-02],
[2.00000e00, 2.345e-02],
[3.00000e00, 2.057e-02],
[4.00000e00, 1.870e-02],
[5.00000e00, 1.740e-02],
[6.00000e00, 1.647e-02],
[8.00000e00, 1.525e-02],
[1.00000e01, 1.450e-02],
[1.50000e01, 1.353e-02],
[2.00000e01, 1.311e-02],
])
# Registry of embedded tables: (data_source, material) -> ndarray
# Table shape: (N, 2) with columns [Energy (MeV), μen/ρ (cm^2/g)]
_MUEN_TABLES = {
("nist126", "air"): _NIST126_AIR,
}
def mass_energy_absorption_coefficient(
material: str, data_source: str = "nist126"
) -> Tabulated1D:
r"""Return the mass energy-absorption coefficient as a function of energy.
The mass energy-absorption coefficient, :math:`\mu_\text{en}/\rho`, is
defined as the fraction of incident photon energy absorbed in a material per
unit mass less the energy carried away by scattered photons. It is obtained
from `NIST Standard Reference Database 126
<https://doi.org/10.18434/T4D01F>`_: X-Ray Mass Attenuation Coefficients.
Parameters
----------
material : {'air'}
Material compound for which to load coefficients.
data_source : {'nist126'}
Source library.
Returns
-------
Tabulated1D
Mass energy-absorption coefficient [cm^2/g] as a function of photon
energy [eV], using log-log interpolation.
"""
cv.check_value("material", material, {"air"})
cv.check_value("data_source", data_source, {"nist126"})
key = (data_source, material)
if key not in _MUEN_TABLES:
available = sorted({m for (ds, m) in _MUEN_TABLES.keys() if ds == data_source})
raise ValueError(
f"No mass energy-absorption data for '{material}' in data source "
f"'{data_source}'. Available materials: {available}"
)
data = _MUEN_TABLES[key]
energy = data[:, 0].copy() * EV_PER_MEV # MeV -> eV
mu_en_coeffs = data[:, 1].copy()
return Tabulated1D(energy, mu_en_coeffs,
breakpoints=[len(energy)], interpolation=[5])
# Used in mass_attenuation_coefficient function as a cache.
# Maps atomic number Z (int) -> Tabulated1D of (mu/rho) [cm^2/g] vs E [eV]
_MASS_ATTENUATION: dict[int, object] = {}
def mass_attenuation_coefficient(element):
r"""Return the photon mass attenuation coefficient as a function of energy.
The mass energy-absorption coefficient, :math:`\mu_\text{en}/\rho`, is
defined as the fraction of incident photon energy absorbed in a material per
unit mass. Values for each element are obtained from `NIST Standard
Reference Database 8 <https://doi.org/10.18434/T48G6X>`_: XCOM Photon Cross
Sections Database.
Parameters
----------
element : str or int
Element symbol (e.g., 'Fe') or atomic number (e.g., 26).
Returns
-------
Tabulated1D
Mass attenuation coefficient [cm^2/g] as a function of photon energy
[eV], using log-log interpolation.
"""
if not _MASS_ATTENUATION:
data_file = Path(__file__).with_name('mass_attenuation.h5')
with h5py.File(data_file, 'r') as f:
for key, dataset in f.items():
energies, mu_rho = dataset[()] # shape (2, N)
_MASS_ATTENUATION[int(key)] = Tabulated1D(
energies, mu_rho,
breakpoints=[len(energies)],
interpolation=[5] # log-log
)
# Resolve element argument to atomic number
if isinstance(element, str):
if element not in ATOMIC_NUMBER:
raise ValueError(f"'{element}' is not a recognized element symbol")
Z = ATOMIC_NUMBER[element]
else:
Z = int(element)
if Z not in _MASS_ATTENUATION:
raise ValueError(f"No mass attenuation data available for Z={Z}")
return _MASS_ATTENUATION[Z]