Skip to content

Commit

Permalink
Adding per kg as unit option on material functions (#3329)
Browse files Browse the repository at this point in the history
Co-authored-by: Jon Shimwell <jon@proximafusion.com>
  • Loading branch information
shimwell and jon-proximafusion authored Feb 28, 2025
1 parent e060534 commit c26fde6
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 11 deletions.
28 changes: 17 additions & 11 deletions openmc/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def get_decay_photon_energy(
clip_tolerance : float
Maximum fraction of :math:`\sum_i x_i p_i` for discrete
distributions that will be discarded.
units : {'Bq', 'Bq/g', 'Bq/cm3'}
units : {'Bq', 'Bq/g', 'Bq/kg', 'Bq/cm3'}
Specifies the units on the integral of the distribution.
volume : float, optional
Volume of the material. If not passed, defaults to using the
Expand All @@ -313,7 +313,7 @@ def get_decay_photon_energy(
is the total intensity of the photon source in the requested units.
"""
cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/cm3'})
cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/kg', 'Bq/cm3'})
if units == 'Bq':
multiplier = volume if volume is not None else self.volume
if multiplier is None:
Expand All @@ -322,6 +322,8 @@ def get_decay_photon_energy(
multiplier = 1
elif units == 'Bq/g':
multiplier = 1.0 / self.get_mass_density()
elif units == 'Bq/kg':
multiplier = 1000.0 / self.get_mass_density()

dists = []
probs = []
Expand Down Expand Up @@ -1132,16 +1134,16 @@ def get_element_atom_densities(self, element: str | None = None) -> dict[str, fl
def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False,
volume: float | None = None) -> dict[str, float] | float:
"""Returns the activity of the material or for each nuclide in the
material in units of [Bq], [Bq/g] or [Bq/cm3].
material in units of [Bq], [Bq/g], [Bq/kg] or [Bq/cm3].
.. versionadded:: 0.13.1
Parameters
----------
units : {'Bq', 'Bq/g', 'Bq/cm3'}
units : {'Bq', 'Bq/g', 'Bq/kg', 'Bq/cm3'}
Specifies the type of activity to return, options include total
activity [Bq], specific [Bq/g] or volumetric activity [Bq/cm3].
Default is volumetric activity [Bq/cm3].
activity [Bq], specific [Bq/g, Bq/kg] or volumetric activity
[Bq/cm3]. Default is volumetric activity [Bq/cm3].
by_nuclide : bool
Specifies if the activity should be returned for the material as a
whole or per nuclide. Default is False.
Expand All @@ -1159,7 +1161,7 @@ def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False,
of the material is returned as a float.
"""

cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/cm3'})
cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/kg', 'Bq/cm3'})
cv.check_type('by_nuclide', by_nuclide, bool)

if units == 'Bq':
Expand All @@ -1168,6 +1170,8 @@ def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False,
multiplier = 1
elif units == 'Bq/g':
multiplier = 1.0 / self.get_mass_density()
elif units == 'Bq/kg':
multiplier = 1000.0 / self.get_mass_density()

activity = {}
for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items():
Expand All @@ -1179,15 +1183,15 @@ def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False,
def get_decay_heat(self, units: str = 'W', by_nuclide: bool = False,
volume: float | None = None) -> dict[str, float] | float:
"""Returns the decay heat of the material or for each nuclide in the
material in units of [W], [W/g] or [W/cm3].
material in units of [W], [W/g], [W/kg] or [W/cm3].
.. versionadded:: 0.13.3
Parameters
----------
units : {'W', 'W/g', 'W/cm3'}
units : {'W', 'W/g', 'W/kg', 'W/cm3'}
Specifies the units of decay heat to return. Options include total
heat [W], specific [W/g] or volumetric heat [W/cm3].
heat [W], specific [W/g, W/kg] or volumetric heat [W/cm3].
Default is total heat [W].
by_nuclide : bool
Specifies if the decay heat should be returned for the material as a
Expand All @@ -1206,7 +1210,7 @@ def get_decay_heat(self, units: str = 'W', by_nuclide: bool = False,
of the material is returned as a float.
"""

cv.check_value('units', units, {'W', 'W/g', 'W/cm3'})
cv.check_value('units', units, {'W', 'W/g', 'W/kg', 'W/cm3'})
cv.check_type('by_nuclide', by_nuclide, bool)

if units == 'W':
Expand All @@ -1215,6 +1219,8 @@ def get_decay_heat(self, units: str = 'W', by_nuclide: bool = False,
multiplier = 1
elif units == 'W/g':
multiplier = 1.0 / self.get_mass_density()
elif units == 'W/kg':
multiplier = 1000.0 / self.get_mass_density()

decayheat = {}
for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items():
Expand Down
5 changes: 5 additions & 0 deletions tests/unit_tests/test_material.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ def test_get_activity():
m4.add_nuclide("H3", 1)
m4.set_density('g/cm3', 1.5)
assert pytest.approx(m4.get_activity(units='Bq/g')) == 355978108155965.94 # [Bq/g]
assert pytest.approx(m4.get_activity(units='Bq/kg')) == 355978108155965940 # [Bq/kg]
assert pytest.approx(m4.get_activity(units='Bq/g', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g]
assert pytest.approx(m4.get_activity(units='Bq/cm3')) == 355978108155965.94*3/2 # [Bq/cc]
assert pytest.approx(m4.get_activity(units='Bq/cm3', by_nuclide=True)["H3"]) == 355978108155965.94*3/2 # [Bq/cc]
Expand Down Expand Up @@ -626,6 +627,7 @@ def test_get_decay_heat():
m4.add_nuclide("I135", 1)
m4.set_density('g/cm3', 1.5)
assert pytest.approx(m4.get_decay_heat(units='W/g')) == 40175.15720273193 # [W/g]
assert pytest.approx(m4.get_decay_heat(units='W/kg')) == 40175157.20273193 # [W/kg]
assert pytest.approx(m4.get_decay_heat(units='W/g', by_nuclide=True)["I135"]) == 40175.15720273193 # [W/g]
assert pytest.approx(m4.get_decay_heat(units='W/cm3')) == 40175.15720273193*3/2 # [W/cc]
assert pytest.approx(m4.get_decay_heat(units='W/cm3', by_nuclide=True)["I135"]) == 40175.15720273193*3/2 #[W/cc]
Expand Down Expand Up @@ -656,6 +658,9 @@ def test_decay_photon_energy():
assert src.p * 2.0 == pytest.approx(src_v2.p)
src_per_cm3 = m.get_decay_photon_energy(units='Bq/cm3', volume=100.0)
assert (src.p == src_per_cm3.p).all()
src_per_bqg = m.get_decay_photon_energy(units='Bq/g')
src_per_bqkg = m.get_decay_photon_energy(units='Bq/kg')
assert pytest.approx(src_per_bqg.integral()) == src_per_bqkg.integral() / 1000.

# If we add Xe135 (which has a tabular distribution), the photon source
# should be a mixture distribution
Expand Down

0 comments on commit c26fde6

Please sign in to comment.