diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 2ee08c7f5d..55289864f2 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -63,7 +63,7 @@ Core Functions atomic_weight combine_distributions decay_constant - decay_photon_source + decay_photon_energy dose_coefficients gnd_name half_life diff --git a/openmc/config.py b/openmc/config.py index 3c031ee7dc..087a8c27e9 100644 --- a/openmc/config.py +++ b/openmc/config.py @@ -4,7 +4,7 @@ from pathlib import Path import warnings from openmc.data import DataLibrary -from openmc.data.decay import _DECAY_PHOTON_SOURCE +from openmc.data.decay import _DECAY_PHOTON_ENERGY __all__ = ["config"] @@ -26,7 +26,7 @@ class _Config(MutableMapping): elif key == 'chain_file': del os.environ['OPENMC_CHAIN_FILE'] # Reset photon source data since it relies on chain file - _DECAY_PHOTON_SOURCE.clear() + _DECAY_PHOTON_ENERGY.clear() def __setitem__(self, key, value): if key == 'cross_sections': @@ -40,7 +40,7 @@ class _Config(MutableMapping): self._set_path(key, value) os.environ['OPENMC_CHAIN_FILE'] = str(value) # Reset photon source data since it relies on chain file - _DECAY_PHOTON_SOURCE.clear() + _DECAY_PHOTON_ENERGY.clear() else: raise KeyError(f'Unrecognized config key: {key}') diff --git a/openmc/data/decay.py b/openmc/data/decay.py index eafa84f66d..6672add3b8 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -576,11 +576,11 @@ class Decay(EqualityMixin): return self._sources -_DECAY_PHOTON_SOURCE = {} +_DECAY_PHOTON_ENERGY = {} -def decay_photon_source(nuclide: str) -> Univariate: - """Get photon source from the decay of a nuclide +def decay_photon_energy(nuclide: str) -> Univariate: + """Get photon energy distribution resulting from the decay of a nuclide This function relies on data stored in a depletion chain. Before calling it for the first time, you need to ensure that a depletion chain has been @@ -598,7 +598,7 @@ def decay_photon_source(nuclide: str) -> Univariate: openmc.stats.Univariate Distribution of energies in [eV] of photons emitted from decay """ - if not _DECAY_PHOTON_SOURCE: + if not _DECAY_PHOTON_ENERGY: chain_file = openmc.config.get('chain_file') if chain_file is None: raise DataError( @@ -610,6 +610,11 @@ def decay_photon_source(nuclide: str) -> Univariate: chain = Chain.from_xml(chain_file) for nuc in chain.nuclides: if 'photon' in nuc.sources: - _DECAY_PHOTON_SOURCE[nuc.name] = nuc.sources['photon'] + _DECAY_PHOTON_ENERGY[nuc.name] = nuc.sources['photon'] - return _DECAY_PHOTON_SOURCE.get(nuclide) + # If the chain file contained no sources at all, warn the user + if not _DECAY_PHOTON_ENERGY: + warn(f"Chain file '{chain_file}' does not have any decay photon " + "sources listed.") + + return _DECAY_PHOTON_ENERGY.get(nuclide) diff --git a/openmc/material.py b/openmc/material.py index 53bf676d5b..52978dbbea 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -92,7 +92,7 @@ class Material(IDManagerMixin): fissionable_mass : float Mass of fissionable nuclides in the material in [g]. Requires that the :attr:`volume` attribute is set. - decay_photon_source : openmc.stats.Univariate + decay_photon_energy : openmc.stats.Univariate Energy distribution of photons emitted from decay of unstable nuclides within the material. The integral of this distribution is the total intensity of the photon source. @@ -264,12 +264,12 @@ class Material(IDManagerMixin): return density*self.volume @property - def decay_photon_source(self) -> Univariate: + def decay_photon_energy(self) -> Univariate: atoms = self.get_nuclide_atoms() dists = [] probs = [] for nuc, num_atoms in atoms.items(): - source_per_atom = openmc.data.decay_photon_source(nuc) + source_per_atom = openmc.data.decay_photon_energy(nuc) if source_per_atom is not None: dists.append(source_per_atom) probs.append(num_atoms) diff --git a/tests/chain_simple.xml b/tests/chain_simple.xml index ba42b55427..28c5739c9f 100644 --- a/tests/chain_simple.xml +++ b/tests/chain_simple.xml @@ -10,8 +10,8 @@ - - 3860.681 4271.629 4683.641 5336.674 30621.8 30978.9 34925.5 34994.3 35237.3 35252.0 35803.0 35817.2 35899.4 35901.8 158197.0 200190.0 249794.0 358390.0 373130.0 407990.0 454200.0 573320.0 608185.0 654432.0 731520.0 812630.0 1062410.0 7.994251137825248e-09 6.327910906791491e-08 5.1272731446173495e-08 7.363690277270275e-09 3.054968676386751e-07 5.64321319541835e-07 5.347473347583344e-08 1.0365225698627538e-07 5.533995748532528e-10 7.536429363113684e-10 1.1251670022820477e-08 2.1931143930358873e-08 1.0789862609689208e-10 1.4667031416354672e-10 6.085892914653786e-08 2.4646918345949914e-09 1.895916795842301e-05 4.644996149813638e-08 3.223058552931912e-09 7.545748847452359e-08 7.583667183369205e-10 1.0048359017964195e-09 6.10485208261221e-07 9.479583979211505e-09 1.1565092454638037e-08 1.478815100756995e-08 8.531625581290355e-10 + + 0.0 10000.0 20000.0 50000.0 100000.0 200000.0 300000.0 400000.0 600000.0 800000.0 1000000.0 1220000.0 1.1612176249914943e-11 0.0 3.1976524142990123e-11 0.0 6.418466676129901e-13 1.894551923065874e-10 5.099949011192198e-13 3.170644340540729e-13 2.756798470867507e-12 6.67627508515641e-14 3.711746246444946e-15 0.0 diff --git a/tests/unit_tests/test_data_decay.py b/tests/unit_tests/test_data_decay.py index e658c16d36..8900e7eace 100644 --- a/tests/unit_tests/test_data_decay.py +++ b/tests/unit_tests/test_data_decay.py @@ -129,18 +129,23 @@ def test_sources(ba137m, nb90): assert len(set(sources.keys()) ^ {'positron', 'electron', 'photon'}) == 0 -def test_decay_photon_source(): +def test_decay_photon_energy(): # If chain file is not set, we should get a data error if 'chain_file' in openmc.config: del openmc.config['chain_file'] with pytest.raises(DataError): - openmc.data.decay_photon_source('135') + openmc.data.decay_photon_energy('I135') # Set chain file to simple chain openmc.config['chain_file'] = Path(__file__).parents[1] / "chain_simple.xml" # Check strength of I135 source and presence of specific spectral line - src = openmc.data.decay_photon_source('I135') + src = openmc.data.decay_photon_energy('I135') assert isinstance(src, openmc.stats.Discrete) assert src.integral() == pytest.approx(3.920996223799345e-05) assert 1260409. in src.x + + # Check Xe135 source, which should be tabular + src = openmc.data.decay_photon_energy('Xe135') + assert isinstance(src, openmc.stats.Tabular) + assert src.integral() == pytest.approx(2.076506258964966e-05) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 352017c8dd..58df246ddd 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -4,7 +4,7 @@ from pathlib import Path import pytest import openmc -from openmc.data import decay_photon_source +from openmc.data import decay_photon_energy import openmc.examples import openmc.model import openmc.stats @@ -545,26 +545,31 @@ def test_get_activity(): assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq] -def test_decay_photon_source(): +def test_decay_photon_energy(): # Set chain file for testing openmc.config['chain_file'] = Path(__file__).parents[1] / 'chain_simple.xml' - # Material representing single atom of I135, Xe135, and Cs135 + # Material representing single atom of I135 and Cs135 m = openmc.Material() m.add_nuclide('I135', 1.0e-24) - m.add_nuclide('Xe135', 1.0e-24) m.add_nuclide('Cs135', 1.0e-24) m.volume = 1.0 # Get decay photon source and make sure it's the right type - src = m.decay_photon_source + src = m.decay_photon_energy assert isinstance(src, openmc.stats.Discrete) + # If we add Xe135 (which has a tabular distribution), the photon source + # should be a mixture distribution + m.add_nuclide('Xe135', 1.0e-24) + src = m.decay_photon_energy + assert isinstance(src, openmc.stats.Mixture) + # With a single atom of each, the intensity of the photon source should be - # equal to sum(I*λ) + # equal to the sum of the intensities for each nuclide def intensity(src): return src.integral() if src is not None else 0.0 assert src.integral() == pytest.approx(sum( - intensity(decay_photon_source(nuc)) for nuc in m.get_nuclides() + intensity(decay_photon_energy(nuc)) for nuc in m.get_nuclides() ))