From 064426a05fdac019917d613eb2805fb80f5fb5ad Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 13:17:33 +0100 Subject: [PATCH 01/17] added specific_activity --- openmc/material.py | 25 +++++++++++++++++++++++++ tests/unit_tests/test_material.py | 18 ++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/openmc/material.py b/openmc/material.py index 6c26416801..61015f5b05 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -94,6 +94,9 @@ class Material(IDManagerMixin): activity : float Activity of the material in [Bq]. Requires that the :attr:`volume` attribute is set. + specific_activity : float + Activity of the material per unit mass in [Bq/kg]. Requires that the + :attr:`volume` and :attr:`density` attributes are set. """ @@ -155,6 +158,11 @@ class Material(IDManagerMixin): """Returns the total activity of the material in Becquerels.""" return sum(self.get_nuclide_activity().values()) + @property + def specific_activity(self): + """Returns the total specific activity of the material in Becquerels per gram.""" + return sum(self.get_nuclide_specific_activity().values()) + @property def name(self): return self._name @@ -925,6 +933,23 @@ class Material(IDManagerMixin): activity[nuclide] = inv_seconds * atoms return activity + def get_nuclide_specific_activity(self): + """Return specific activity in [Bq/g] for each nuclide in the material + + .. versionadded:: 0.13.1 + + Returns + ------- + dict + Dictionary whose keys are nuclide names and values are specific + activity in [Bq/g]. + """ + activity = {} + for nuclide, atoms in self.get_nuclide_atoms().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = (inv_seconds * atoms) / self.get_mass() + return activity + 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..d70161f485 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -496,3 +496,21 @@ def test_activity_of_metastable(): m1.set_density('g/cm3', 1) m1.volume = 98.9 assert pytest.approx(m1.activity, rel=0.001) == 1.93e19 + + +def test_specific_activity_of_tritium(): + """Checks that specific activity stays the same for all volumes and + densities while activity changes proportionally to mass""" + m1 = openmc.Material() + m1.add_nuclide("H3", 1) + m1.set_density('g/cm3', 1) + m1.volume = 1 + # activity and specific_activity are initially the same as we have 1g + assert pytest.approx(m1.specific_activity) == 3.559778e14 + assert pytest.approx(m1.activity) == 3.559778e14 + m1.set_density('g/cm3', 2) + assert pytest.approx(m1.specific_activity) == 3.559778e14 + assert pytest.approx(m1.activity) == 3.559778e14*2 + m1.volume = 3 + assert pytest.approx(m1.specific_activity) == 3.559778e14 + assert pytest.approx(m1.activity) == 3.559778e14*2*3 From 98c287b83a692beac38eb1617f3f7315a6fa8a20 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 17:24:48 +0100 Subject: [PATCH 02/17] volume not needed when finding specific activity --- openmc/material.py | 4 ++-- tests/unit_tests/test_material.py | 21 ++++++++------------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 61015f5b05..57f9a6f862 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -945,9 +945,9 @@ class Material(IDManagerMixin): activity in [Bq/g]. """ activity = {} - for nuclide, atoms in self.get_nuclide_atoms().items(): + for nuclide, atoms in self.get_nuclide_atom_densities().items(): inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms) / self.get_mass() + activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density return activity def get_nuclide_atoms(self): diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index d70161f485..c959ba2762 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -481,12 +481,16 @@ def test_activity_of_stable(): def test_activity_of_tritium(): - """Checks that 1g of tritium has the correct activity""" + """Checks that 1g of tritium has the correct activity activity scaling""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) m1.volume = 1 assert pytest.approx(m1.activity) == 3.559778e14 + m1.set_density('g/cm3', 2) + assert pytest.approx(m1.activity) == 3.559778e14*2 + m1.volume = 3 + assert pytest.approx(m1.activity) == 3.559778e14*2*3 def test_activity_of_metastable(): @@ -499,18 +503,9 @@ def test_activity_of_metastable(): def test_specific_activity_of_tritium(): - """Checks that specific activity stays the same for all volumes and - densities while activity changes proportionally to mass""" + """Checks that specific activity of tritium is correct""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) - m1.volume = 1 - # activity and specific_activity are initially the same as we have 1g - assert pytest.approx(m1.specific_activity) == 3.559778e14 - assert pytest.approx(m1.activity) == 3.559778e14 - m1.set_density('g/cm3', 2) - assert pytest.approx(m1.specific_activity) == 3.559778e14 - assert pytest.approx(m1.activity) == 3.559778e14*2 - m1.volume = 3 - assert pytest.approx(m1.specific_activity) == 3.559778e14 - assert pytest.approx(m1.activity) == 3.559778e14*2*3 + assert m1.specific_activity == 355978108155965.9 + assert m1.get_nuclide_specific_activity() == {"H3": 355978108155965.9} \ No newline at end of file From 742311fd1bb37b884a633d3464f56504448a6ef5 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Tue, 2 Aug 2022 17:37:17 +0100 Subject: [PATCH 03/17] [skip ci] fixed typo --- tests/unit_tests/test_material.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index c959ba2762..fd9f325f2e 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -481,7 +481,7 @@ def test_activity_of_stable(): def test_activity_of_tritium(): - """Checks that 1g of tritium has the correct activity activity scaling""" + """Checks that 1g of tritium has the correct activity scaling""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) From 98c707ea07736578a7f4080f2bbbbcab3df3b7a6 Mon Sep 17 00:00:00 2001 From: shimwell Date: Wed, 3 Aug 2022 22:46:50 +0100 Subject: [PATCH 04/17] refactor activities to single method --- openmc/material.py | 87 ++++++++++++++++--------------- tests/unit_tests/test_material.py | 25 ++++++--- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 57f9a6f862..05b69287d2 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -91,13 +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. - specific_activity : float - Activity of the material per unit mass in [Bq/kg]. Requires that the - :attr:`volume` and :attr:`density` attributes are set. - """ next_id = 1 @@ -153,16 +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 specific_activity(self): - """Returns the total specific activity of the material in Becquerels per gram.""" - return sum(self.get_nuclide_specific_activity().values()) - @property def name(self): return self._name @@ -916,39 +899,57 @@ class Material(IDManagerMixin): return nuclides - def get_nuclide_activity(self): - """Return activity in [Bq] for each nuclide in the material + def get_activity(self, normalization: str = 'total', 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/cc]. .. versionadded:: 0.13.1 - Returns - ------- - dict - Dictionary whose keys are nuclide names and values are activity in - [Bq]. - """ - activity = {} - for nuclide, atoms in self.get_nuclide_atoms().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = inv_seconds * atoms - return activity - - def get_nuclide_specific_activity(self): - """Return specific activity in [Bq/g] for each nuclide in the material - - .. versionadded:: 0.13.1 + Parameters + ---------- + normalization : {'total', 'mass', 'volume'} + Specifies the type of activity to return, 'total' will return the + material activity in [Bq], 'mass' returns the materials specific + activity in [Bq/g] and 'volume' returns the activity in [Bq/cc]. + by_nuclide : bool + Specifies if the activity should be returned for the material as a + whole or per nuclide. Returns ------- - dict - Dictionary whose keys are nuclide names and values are specific - activity in [Bq/g]. + + 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. """ - activity = {} - for nuclide, atoms in self.get_nuclide_atom_densities().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density - return activity + + cv.check_value('normalization', normalization, {'total', 'mass', 'volume'}) + cv.check_type('by_nuclide', by_nuclide, bool) + + if normalization=='total': + activity = {} + for nuclide, atoms in self.get_nuclide_atoms().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = inv_seconds * atoms + + elif normalization=='mass': + activity = {} + for nuclide, atoms in self.get_nuclide_atom_densities().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density + # normalization must be volume by this stage so else can be used + else: + activity = {} + for nuclide, atoms in self.get_nuclide_atom_densities().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.volume + + if by_nuclide: + return activity + else: + return 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 fd9f325f2e..763325ac90 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -477,7 +477,7 @@ def test_activity_of_stable(): m1.add_element("Fe", 1) m1.set_density('g/cm3', 1) m1.volume = 1 - assert m1.activity == 0 + assert m1.get_activity() == 0 def test_activity_of_tritium(): @@ -486,11 +486,11 @@ def test_activity_of_tritium(): m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) m1.volume = 1 - assert pytest.approx(m1.activity) == 3.559778e14 + assert pytest.approx(m1.get_activity()) == 3.559778e14 m1.set_density('g/cm3', 2) - assert pytest.approx(m1.activity) == 3.559778e14*2 + assert pytest.approx(m1.get_activity()) == 3.559778e14*2 m1.volume = 3 - assert pytest.approx(m1.activity) == 3.559778e14*2*3 + assert pytest.approx(m1.get_activity()) == 3.559778e14*2*3 def test_activity_of_metastable(): @@ -499,13 +499,22 @@ def test_activity_of_metastable(): 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 + assert pytest.approx(m1.get_activity(), rel=0.001) == 1.93e19 def test_specific_activity_of_tritium(): - """Checks that specific activity of tritium is correct""" + """Checks that specific and volumetric activity of tritium are correct""" m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) - assert m1.specific_activity == 355978108155965.9 - assert m1.get_nuclide_specific_activity() == {"H3": 355978108155965.9} \ No newline at end of file + assert m1.get_activity(normalization='mass') == 355978108155965.9 # [Bq/g] + assert m1.get_activity(normalization='mass', by_nuclide=True) == { + "H3": 355978108155965.9 # [Bq/g] + } + # volume is required to calculate total and volumetric activity + m1.volume = 10. + assert m1.get_activity(normalization='total') == 355978108155965.9*10. # [Bq] + assert m1.get_activity(normalization='volume') == 355978108155965.9/10. # [Bq/cc] + assert m1.get_activity(normalization='volume', by_nuclide=True) == { + "H3": 355978108155965.9/10. # [Bq/cc] + } From c900e4784e68b3ea833e3b60fe80d3cc345f33eb Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 07:55:35 +0100 Subject: [PATCH 05/17] Corrections to activity calcs Co-authored-by: Ethan Peterson --- openmc/material.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 05b69287d2..48684ed67f 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -927,23 +927,15 @@ class Material(IDManagerMixin): cv.check_value('normalization', normalization, {'total', 'mass', 'volume'}) cv.check_type('by_nuclide', by_nuclide, bool) - if normalization=='total': - activity = {} - for nuclide, atoms in self.get_nuclide_atoms().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = inv_seconds * atoms - - elif normalization=='mass': - activity = {} - for nuclide, atoms in self.get_nuclide_atom_densities().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.density - # normalization must be volume by this stage so else can be used + if normalization == 'total': + multiplier = self.volume else: - activity = {} - for nuclide, atoms in self.get_nuclide_atom_densities().items(): - inv_seconds = openmc.data.decay_constant(nuclide) - activity[nuclide] = (inv_seconds * atoms * 1.0e24) / self.volume + multiplier = 1 if normalization == 'volume' else 1.0 / self.get_mass_density() + + activity = {} + for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): + inv_seconds = openmc.data.decay_constant(nuclide) + activity[nuclide] = inv_seconds * 1e24 * atoms_per_bcm * multiplier if by_nuclide: return activity From e4d54d49a8f92aa5b90bfd2b814b6bcc751c3541 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 09:39:14 +0100 Subject: [PATCH 06/17] moved volume lower --- tests/unit_tests/test_material.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 763325ac90..24887d8a6b 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -507,14 +507,14 @@ def test_specific_activity_of_tritium(): m1 = openmc.Material() m1.add_nuclide("H3", 1) m1.set_density('g/cm3', 1) - assert m1.get_activity(normalization='mass') == 355978108155965.9 # [Bq/g] + assert m1.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] assert m1.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155965.9 # [Bq/g] + "H3": 355978108155966.0 # [Bq/g] } - # volume is required to calculate total and volumetric activity - m1.volume = 10. - assert m1.get_activity(normalization='total') == 355978108155965.9*10. # [Bq] - assert m1.get_activity(normalization='volume') == 355978108155965.9/10. # [Bq/cc] + assert m1.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] assert m1.get_activity(normalization='volume', by_nuclide=True) == { - "H3": 355978108155965.9/10. # [Bq/cc] + "H3": 355978108155965.94 # [Bq/cc] } + # volume is required to calculate total activity + m1.volume = 10. + assert m1.get_activity(normalization='total') == 3559781081559659.5 # [Bq] From c036403c984067946542e97cbdbe488687b6b706 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 14:55:45 +0100 Subject: [PATCH 07/17] simpler if else statement for normalization Co-authored-by: Patrick Shriwise --- openmc/material.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 48684ed67f..965c9d5c85 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -929,8 +929,10 @@ class Material(IDManagerMixin): if normalization == 'total': multiplier = self.volume - else: - multiplier = 1 if normalization == 'volume' else 1.0 / self.get_mass_density() + elif normalization == 'volume': + multiplier = 1 + elif normalization == 'mass': + multiplier = 1.0 / self.get_mass_density() activity = {} for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): From 8164f309e9d61479fd65759da46c6e8b22715eef Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 15:37:01 +0100 Subject: [PATCH 08/17] added pre volume attribute tests for stable nuclide --- tests/unit_tests/test_material.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 24887d8a6b..ddb1bfcf20 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -471,16 +471,19 @@ def test_mix_materials(): assert m5.density == pytest.approx(dens5) -def test_activity_of_stable(): +def test_get_activity_of_stable_nuclides(): """Creates a material with stable isotopes to checks the activity is 0""" m1 = openmc.Material() m1.add_element("Fe", 1) - m1.set_density('g/cm3', 1) + m1.set_density('g/cm3', 1.5) + # activity in Bq/cc and Bq/g should not require volume setting + assert m1.get_activity(normalization='volume') == 0 + assert m1.get_activity(normalization='mass') == 0 m1.volume = 1 assert m1.get_activity() == 0 -def test_activity_of_tritium(): +def test_get_activity_of_tritium(): """Checks that 1g of tritium has the correct activity scaling""" m1 = openmc.Material() m1.add_nuclide("H3", 1) @@ -493,7 +496,7 @@ def test_activity_of_tritium(): assert pytest.approx(m1.get_activity()) == 3.559778e14*2*3 -def test_activity_of_metastable(): +def test_get_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) @@ -502,7 +505,7 @@ def test_activity_of_metastable(): assert pytest.approx(m1.get_activity(), rel=0.001) == 1.93e19 -def test_specific_activity_of_tritium(): +def test_get_activity_of_tritium_nuclides(): """Checks that specific and volumetric activity of tritium are correct""" m1 = openmc.Material() m1.add_nuclide("H3", 1) From a30f9b88fd79400c8bbc65de3902d3ddce8e838d Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 15:49:11 +0100 Subject: [PATCH 09/17] combined activity unit tests as suggested @eepeterson --- tests/unit_tests/test_material.py | 67 +++++++++++++++---------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index ddb1bfcf20..432cf3a032 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -471,10 +471,13 @@ def test_mix_materials(): assert m5.density == pytest.approx(dens5) -def test_get_activity_of_stable_nuclides(): - """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 checks the activity is 0 m1 = openmc.Material() - m1.add_element("Fe", 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(normalization='volume') == 0 @@ -482,42 +485,36 @@ def test_get_activity_of_stable_nuclides(): m1.volume = 1 assert m1.get_activity() == 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()) == 3.559778e14 + m2.set_density('g/cm3', 2) + assert pytest.approx(m2.get_activity()) == 3.559778e14*2 + m2.volume = 3 + assert pytest.approx(m2.get_activity()) == 3.559778e14*2*3 -def test_get_activity_of_tritium(): - """Checks that 1g of tritium has the correct activity scaling""" - m1 = openmc.Material() - m1.add_nuclide("H3", 1) - m1.set_density('g/cm3', 1) - m1.volume = 1 - assert pytest.approx(m1.get_activity()) == 3.559778e14 - m1.set_density('g/cm3', 2) - assert pytest.approx(m1.get_activity()) == 3.559778e14*2 - m1.volume = 3 - assert pytest.approx(m1.get_activity()) == 3.559778e14*2*3 + # 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(), rel=0.001) == 1.93e19 - -def test_get_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.get_activity(), rel=0.001) == 1.93e19 - - -def test_get_activity_of_tritium_nuclides(): - """Checks that specific and volumetric activity of tritium are correct""" - m1 = openmc.Material() - m1.add_nuclide("H3", 1) - m1.set_density('g/cm3', 1) - assert m1.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] - assert m1.get_activity(normalization='mass', by_nuclide=True) == { + # Checks that specific and volumetric activity of tritium are correct + m4 = openmc.Material() + m4.add_nuclide("H3", 1) + m4.set_density('g/cm3', 1) + assert m4.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] + assert m4.get_activity(normalization='mass', by_nuclide=True) == { "H3": 355978108155966.0 # [Bq/g] } - assert m1.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] - assert m1.get_activity(normalization='volume', by_nuclide=True) == { + assert m4.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] + assert m4.get_activity(normalization='volume', by_nuclide=True) == { "H3": 355978108155965.94 # [Bq/cc] } # volume is required to calculate total activity - m1.volume = 10. - assert m1.get_activity(normalization='total') == 3559781081559659.5 # [Bq] + m4.volume = 10. + assert m4.get_activity(normalization='total') == 3559781081559659.5 # [Bq] From 152a149488ddc9fae4612b828ca49f9cd27cb181 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 16:15:12 +0100 Subject: [PATCH 10/17] density set to 1.5 to test different activities scaling Co-authored-by: Ethan Peterson --- tests/unit_tests/test_material.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 432cf3a032..5f567304bd 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -474,7 +474,7 @@ def test_mix_materials(): def test_get_activity(): """Tests the activity of stable, metastable and active materials""" - # Creates a material with stable isotopes to checks the activity is 0 + # Creates a material with stable isotopes to check the activity is 0 m1 = openmc.Material() m1.add_element("Fe", 0.7) m1.add_element("Li", 0.3) @@ -506,15 +506,15 @@ def test_get_activity(): # Checks that specific and volumetric activity of tritium are correct m4 = openmc.Material() m4.add_nuclide("H3", 1) - m4.set_density('g/cm3', 1) - assert m4.get_activity(normalization='mass') == 355978108155966.0 # [Bq/g] + m4.set_density('g/cm3', 1.5) + assert m4.get_activity(normalization='mass') == 355978108155966.0*2/3 # [Bq/g] assert m4.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155966.0 # [Bq/g] + "H3": 355978108155966.0*2/3 # [Bq/g] } - assert m4.get_activity(normalization='volume') == 355978108155965.94 # [Bq/cc] + assert m4.get_activity(normalization='volume') == 355978108155965.94*3/2 # [Bq/cc] assert m4.get_activity(normalization='volume', by_nuclide=True) == { - "H3": 355978108155965.94 # [Bq/cc] + "H3": 355978108155965.94*3/2 # [Bq/cc] } # volume is required to calculate total activity m4.volume = 10. - assert m4.get_activity(normalization='total') == 3559781081559659.5 # [Bq] + assert m4.get_activity(normalization='total') == 355978108155965.94*3/2*10 # [Bq] From 39eaf9d88752f97ad21170c6b393358f24d4961c Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Thu, 4 Aug 2022 16:50:18 -0400 Subject: [PATCH 11/17] Apply suggestions from code review Co-authored-by: Jonathan Shimwell --- openmc/material.py | 2 +- tests/unit_tests/test_material.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 965c9d5c85..ed1b839771 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -899,7 +899,7 @@ class Material(IDManagerMixin): return nuclides - def get_activity(self, normalization: str = 'total', by_nuclide: bool = False): + def get_activity(self, normalization: str = 'volume', 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/cc]. diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 5f567304bd..eadad5006b 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -483,33 +483,33 @@ def test_get_activity(): assert m1.get_activity(normalization='volume') == 0 assert m1.get_activity(normalization='mass') == 0 m1.volume = 1 - assert m1.get_activity() == 0 + assert m1.get_activity(normalization='total') == 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()) == 3.559778e14 + assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14 m2.set_density('g/cm3', 2) - assert pytest.approx(m2.get_activity()) == 3.559778e14*2 + assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2 m2.volume = 3 - assert pytest.approx(m2.get_activity()) == 3.559778e14*2*3 + assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2*3 # 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(), rel=0.001) == 1.93e19 + assert pytest.approx(m3.get_activity(normalization='total'), 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 m4.get_activity(normalization='mass') == 355978108155966.0*2/3 # [Bq/g] + assert m4.get_activity(normalization='mass') == 355978108155965.94 # [Bq/g] assert m4.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155966.0*2/3 # [Bq/g] + "H3": 355978108155965.94 # [Bq/g] } assert m4.get_activity(normalization='volume') == 355978108155965.94*3/2 # [Bq/cc] assert m4.get_activity(normalization='volume', by_nuclide=True) == { From 75d82a7df72dc1a1e40d7983d4537f412fca703f Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Thu, 4 Aug 2022 23:43:42 +0100 Subject: [PATCH 12/17] reverting to pytest.approx Co-authored-by: Ethan Peterson --- tests/unit_tests/test_material.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index eadad5006b..dbc67fcc27 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -507,14 +507,11 @@ def test_get_activity(): m4 = openmc.Material() m4.add_nuclide("H3", 1) m4.set_density('g/cm3', 1.5) - assert m4.get_activity(normalization='mass') == 355978108155965.94 # [Bq/g] - assert m4.get_activity(normalization='mass', by_nuclide=True) == { - "H3": 355978108155965.94 # [Bq/g] - } - assert m4.get_activity(normalization='volume') == 355978108155965.94*3/2 # [Bq/cc] - assert m4.get_activity(normalization='volume', by_nuclide=True) == { - "H3": 355978108155965.94*3/2 # [Bq/cc] + assert pytest.approx(m4.get_activity(normalization='mass')) == 355978108155965.94 # [Bq/g] + assert pytest.approx(m4.get_activity(normalization='mass', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g] + assert pytest.approx(m4.get_activity(normalization='volume')) == 355978108155965.94*3/2 # [Bq/cc] + assert pytest.approx(m4.get_activity(normalization='volume', by_nuclide=True)["H3"]) == 355978108155965.94*3/2 # [Bq/cc] } # volume is required to calculate total activity m4.volume = 10. - assert m4.get_activity(normalization='total') == 355978108155965.94*3/2*10 # [Bq] + assert pytest.approx(m4.get_activity(normalization='total')) == 355978108155965.94*3/2*10 # [Bq] From 496dda717ce055024993053d9a42af47a961c955 Mon Sep 17 00:00:00 2001 From: shimwell Date: Thu, 4 Aug 2022 23:59:51 +0100 Subject: [PATCH 13/17] removed missing bracket --- tests/unit_tests/test_material.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index dbc67fcc27..7e91216081 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -511,7 +511,6 @@ def test_get_activity(): assert pytest.approx(m4.get_activity(normalization='mass', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g] assert pytest.approx(m4.get_activity(normalization='volume')) == 355978108155965.94*3/2 # [Bq/cc] assert pytest.approx(m4.get_activity(normalization='volume', 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(normalization='total')) == 355978108155965.94*3/2*10 # [Bq] From a94fb43418e15fccf522c2ee1f1271e268c5cba9 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 14:00:25 +0100 Subject: [PATCH 14/17] review comments from @paulromano --- openmc/material.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index ed1b839771..c194a8229c 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -899,18 +899,17 @@ class Material(IDManagerMixin): return nuclides - def get_activity(self, normalization: str = 'volume', by_nuclide: bool = False): + 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/cc]. + material in units of [Bq], [Bq/g] or [Bq/cm3]. .. versionadded:: 0.13.1 Parameters ---------- - normalization : {'total', 'mass', 'volume'} - Specifies the type of activity to return, 'total' will return the - material activity in [Bq], 'mass' returns the materials specific - activity in [Bq/g] and 'volume' returns the activity in [Bq/cc]. + 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]. by_nuclide : bool Specifies if the activity should be returned for the material as a whole or per nuclide. @@ -924,16 +923,16 @@ class Material(IDManagerMixin): of the material is returned as a float. """ - cv.check_value('normalization', normalization, {'total', 'mass', 'volume'}) + cv.check_value('units', units, {'Bq', 'Bq/g', 'Bq/cm3'}) cv.check_type('by_nuclide', by_nuclide, bool) - - if normalization == 'total': + + if units == 'Bq': multiplier = self.volume - elif normalization == 'volume': + elif units == 'Bq/g': multiplier = 1 - elif normalization == 'mass': + elif units == 'Bq/cm3': multiplier = 1.0 / self.get_mass_density() - + activity = {} for nuclide, atoms_per_bcm in self.get_nuclide_atom_densities().items(): inv_seconds = openmc.data.decay_constant(nuclide) @@ -944,7 +943,6 @@ class Material(IDManagerMixin): else: return sum(activity.values()) - def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material From 63b517aebc775fc4c060c18868895960c95100ae Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 14:52:35 +0100 Subject: [PATCH 15/17] updated tests to use units args by @eepeterson Co-authored-by: Ethan Peterson --- openmc/material.py | 3 ++- tests/unit_tests/test_material.py | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index c194a8229c..724b88ab47 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -910,9 +910,10 @@ class Material(IDManagerMixin): 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. + whole or per nuclide. Default is False. Returns ------- diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 7e91216081..451c5308a4 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -480,37 +480,37 @@ def test_get_activity(): 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(normalization='volume') == 0 - assert m1.get_activity(normalization='mass') == 0 + assert m1.get_activity(units='Bq/cm3') == 0 + assert m1.get_activity(units='Bq/g') == 0 m1.volume = 1 - assert m1.get_activity(normalization='total') == 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(normalization='total')) == 3.559778e14 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14 m2.set_density('g/cm3', 2) - assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14*2 m2.volume = 3 - assert pytest.approx(m2.get_activity(normalization='total')) == 3.559778e14*2*3 + assert pytest.approx(m2.get_activity(units='Bq')) == 3.559778e14*2*3 # 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(normalization='total'), rel=0.001) == 1.93e19 + assert pytest.approx(m3.get_activity(units='Bq'), 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(normalization='mass')) == 355978108155965.94 # [Bq/g] - assert pytest.approx(m4.get_activity(normalization='mass', by_nuclide=True)["H3"]) == 355978108155965.94 # [Bq/g] - assert pytest.approx(m4.get_activity(normalization='volume')) == 355978108155965.94*3/2 # [Bq/cc] - assert pytest.approx(m4.get_activity(normalization='volume', by_nuclide=True)["H3"]) == 355978108155965.94*3/2 # [Bq/cc] + 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(normalization='total')) == 355978108155965.94*3/2*10 # [Bq] + assert pytest.approx(m4.get_activity(units='Bq')) == 355978108155965.94*3/2*10 # [Bq] From 3271c08d22d60b21546bbb948cd967a46b2023cd Mon Sep 17 00:00:00 2001 From: Ethan Peterson Date: Mon, 8 Aug 2022 11:34:10 -0400 Subject: [PATCH 16/17] Apply suggestions from @paulromano code review Co-authored-by: Paul Romano --- openmc/material.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 724b88ab47..c89109bfa6 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -917,7 +917,6 @@ class Material(IDManagerMixin): Returns ------- - 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 @@ -939,10 +938,7 @@ class Material(IDManagerMixin): inv_seconds = openmc.data.decay_constant(nuclide) activity[nuclide] = inv_seconds * 1e24 * atoms_per_bcm * multiplier - if by_nuclide: - return activity - else: - return sum(activity.values()) + return activity if by_nuclide else sum(activity.values()) def get_nuclide_atoms(self): """Return number of atoms of each nuclide in the material From 5d5bc53a15ea3e77744285564d4aac26f0c0c731 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Mon, 8 Aug 2022 20:46:57 +0100 Subject: [PATCH 17/17] Fixing the activity tests @eepeterson Co-authored-by: Ethan Peterson --- openmc/material.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index c89109bfa6..54ff0b5129 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -928,9 +928,9 @@ class Material(IDManagerMixin): if units == 'Bq': multiplier = self.volume - elif units == 'Bq/g': - multiplier = 1 elif units == 'Bq/cm3': + multiplier = 1 + elif units == 'Bq/g': multiplier = 1.0 / self.get_mass_density() activity = {}