diff --git a/openmc/material.py b/openmc/material.py index 913d53d9db..6c23d3319a 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -91,10 +91,6 @@ class Material(IDManagerMixin): fissionable_mass : float Mass of fissionable nuclides in the material in [g]. Requires that the :attr:`volume` attribute is set. - activity : float - Activity of the material in [Bq]. Requires that the :attr:`volume` - attribute is set. - """ next_id = 1 @@ -150,11 +146,6 @@ class Material(IDManagerMixin): return string - @property - def activity(self): - """Returns the total activity of the material in Becquerels.""" - return sum(self.get_nuclide_activity().values()) - @property def name(self): return self._name @@ -908,22 +899,46 @@ class Material(IDManagerMixin): return nuclides - def get_nuclide_activity(self): - """Return activity in [Bq] for each nuclide in the material + def get_activity(self, units: str = 'Bq/cm3', by_nuclide: bool = False): + """Returns the activity of the material or for each nuclide in the + material in units of [Bq], [Bq/g] or [Bq/cm3]. .. versionadded:: 0.13.1 + Parameters + ---------- + units : {'Bq', 'Bq/g', '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]. + by_nuclide : bool + Specifies if the activity should be returned for the material as a + whole or per nuclide. Default is False. + Returns ------- - dict - Dictionary whose keys are nuclide names and values are activity in - [Bq]. + Union[dict, float] + If by_nuclide is True then a dictionary whose keys are nuclide + names and values are activity is returned. Otherwise the activity + of the material is returned as a float. """ + + cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/cm3'}) + cv.check_type('by_nuclide', by_nuclide, bool) + + if units == 'Bq': + multiplier = self.volume + elif units == 'Bq/cm3': + multiplier = 1 + elif units == 'Bq/g': + multiplier = 1.0 / self.get_mass_density() + activity = {} - for nuclide, atoms in self.get_nuclide_atoms().items(): + for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = inv_seconds * atoms - return activity + activity[nuclide] = inv_seconds * 1e24 * atoms_per_bcm * multiplier + + return activity if by_nuclide else sum(activity.values()) def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 2c5cc2874c..451c5308a4 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -471,28 +471,46 @@ def test_mix_materials(): assert m5.density == pytest.approx(dens5) -def test_activity_of_stable(): - """Creates a material with stable isotopes to checks the activity is 0""" +def test_get_activity(): + """Tests the activity of stable, metastable and active materials""" + + # Creates a material with stable isotopes to check the activity is 0 m1 = openmc.Material() - m1.add_element("Fe", 1) - m1.set_density('g/cm3', 1) + m1.add_element("Fe", 0.7) + m1.add_element("Li", 0.3) + m1.set_density('g/cm3', 1.5) + # activity in Bq/cc and Bq/g should not require volume setting + assert m1.get_activity(units='Bq/cm3') == 0 + assert m1.get_activity(units='Bq/g') == 0 m1.volume = 1 - assert m1.activity == 0 + assert m1.get_activity(units='Bq') == 0 + # Checks that 1g of tritium has the correct activity scaling + m2 = openmc.Material() + m2.add_nuclide("H3", 1) + m2.set_density('g/cm3', 1) + m2.volume = 1 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14 + m2.set_density('g/cm3', 2) + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14*2 + m2.volume = 3 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14*2*3 -def test_activity_of_tritium(): - """Checks that 1g of tritium has the correct activity""" - m1 = openmc.Material() - m1.add_nuclide("H3", 1) - m1.set_density('g/cm3', 1) - m1.volume = 1 - assert pytest.approx(m1.activity) == 3.559778e14 + # Checks that 1 mol of a metastable nuclides has the correct activity + m3 = openmc.Material() + m3.add_nuclide("Tc99_m1", 1) + m3.set_density('g/cm3', 1) + m3.volume = 98.9 + assert pytest.approx(m3.get_activity(units='Bq'), rel=0.001) == 1.93e19 - -def test_activity_of_metastable(): - """Checks that 1 mol of a Tc99_m1 nuclides has the correct activity""" - m1 = openmc.Material() - m1.add_nuclide("Tc99_m1", 1) - m1.set_density('g/cm3', 1) - m1.volume = 98.9 - assert pytest.approx(m1.activity, rel=0.001) == 1.93e19 + # Checks that specific and volumetric activity of tritium are correct + m4 = openmc.Material() + 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/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] + # volume is required to calculate total activity + m4.volume = 10. + assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq]