Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ENDF/B-VII.1 MC2-3 nuclide IDs #1982

Merged
merged 31 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
3fb09a6
Add ENDF/B-VII.1 isotopes
Oct 10, 2024
04fb9e0
Add ENDF/B-VII.1 MC2-3 ID dictionary
Oct 11, 2024
838015d
Declare some global variables and fix typos
Oct 11, 2024
1ff770e
Add tests for loading VII.0 and VII.1 MC2-3 data
Oct 11, 2024
67be3f2
Have byMcc3Id point to ENDF/B-VII.0 isotopes
Oct 15, 2024
541334b
Revert "Have byMcc3Id point to ENDF/B-VII.0 isotopes"
Oct 17, 2024
3adb1a9
Add getMcc3Id() for LFP
Oct 22, 2024
2c1860b
Assume ENDF/B-VII.1 elemental data by default
Oct 22, 2024
28922f2
Update tests to use isotopic vanadium
Oct 23, 2024
63ee9e8
Update size of expected diff vector
Oct 24, 2024
0c263e6
Merge branch 'main' into add_endfb-VII.1_support
Oct 24, 2024
f809b56
Merge branch 'main' into add_endfb-VII.1_support
Oct 24, 2024
9c1bda0
Merge branch 'main' into add_endfb-VII.1_support
Oct 28, 2024
be3baa4
Correct typos in docstrings
Oct 28, 2024
b1787bb
Add release notes
Oct 28, 2024
50e10b8
Black formatting
Oct 28, 2024
760cab3
Merge branch 'main' into add_endfb-VII.1_support
Oct 28, 2024
bb4167a
Update doc/release/0.4.rst
aaronjamesreynolds Oct 28, 2024
ce2f7f4
Update doc/release/0.4.rst
aaronjamesreynolds Oct 28, 2024
5ff7841
Update impl and test sphinx fields
Oct 29, 2024
9f9c708
Fix typo in docstring
Oct 29, 2024
b6d238f
Format docstring
Oct 29, 2024
11752a6
Merge branch 'main' into add_endfb-VII.1_support
Oct 29, 2024
dd6cc03
Merge branch 'main' into add_endfb-VII.1_support
Oct 30, 2024
65a7273
Merge branch 'main' into add_endfb-VII.1_support
john-science Oct 30, 2024
7729139
Merge branch 'main' into add_endfb-VII.1_support
Oct 31, 2024
41d554b
Merge branch 'main' into add_endfb-VII.1_support
Oct 31, 2024
d5e7205
Merge branch 'main' into add_endfb-VII.1_support
john-science Oct 31, 2024
dd703be
Merge branch 'main' into add_endfb-VII.1_support
Nov 2, 2024
08b30e2
Use ENDF/B-VII.0 elementals with Serpent
Nov 2, 2024
f7664f8
Merge branch 'main' into add_endfb-VII.1_support
Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion armi/bookkeeping/db/tests/test_comparedb3.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def test_compareDatabaseSim(self):
dbs[1]._fullPath,
timestepCompare=[(0, 0), (0, 1)],
)
self.assertEqual(len(diffs.diffs), 477)
self.assertEqual(len(diffs.diffs), 480)
# Cycle length is only diff (x3)
self.assertEqual(diffs.nDiffs(), 3)

Expand Down
126 changes: 103 additions & 23 deletions armi/nucDirectory/nuclideBases.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class which is used to organize and store metadata about each nuclide. The
* ``byLabel`` (keyed by label, e.g., ``U235``)
* ``byMcc2Id`` (keyed by MC\ :sup:`2`-2 ID, e.g., ``U-2355``)
* ``byMcc3Id`` (keyed by MC\ :sup:`2`-3 ID, e.g., ``U235_7``)
* ``byMcc3IdEndfbVII0`` (keyed by MC\ :sup:`2`-3 ID, e.g., ``U235_7``)
* ``byMcc3IdEndfbVII1`` (keyed by MC\ :sup:`2`-3 ID, e.g., ``U235_7``)
* ``byMcnpId`` (keyed by MCNP ID, e.g., ``92235``)
* ``byAAAZZZSId`` (keyed by AAAZZZS, e.g., ``2350920``)

Expand Down Expand Up @@ -78,7 +80,7 @@ class which is used to organize and store metadata about each nuclide. The

Retrieve U-235 by the MC2-3 ID:

>>> nuclideBases.byMcc3Id['U235_7']
>>> nuclideBases.byMcc3IdEndfVII0['U235_7']
<NuclideBase U235: Z:92, A:235, S:0, W:2.350439e+02, Label:U235>, HL:2.22160758861e+16, Abund:7.204000e-03>

Retrieve U-235 by the MCNP ID:
Expand Down Expand Up @@ -120,7 +122,9 @@ class which is used to organize and store metadata about each nuclide. The
byDBName = {}
byLabel = {}
byMcc2Id = {}
byMcc3Id = {}
byMcc3Id = {} # for backwards compatibility. Identical to byMcc3IdEndfbVII1
byMcc3IdEndfbVII0 = {}
byMcc3IdEndfbVII1 = {}
byMcnpId = {}
byAAAZZZSId = {}

Expand Down Expand Up @@ -168,9 +172,17 @@ def getMcc2Id(self):
return NotImplementedError

def getMcc3Id(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return NotImplementedError

def getMcc3IdEndfbVII0(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.0 cross section library."""
return NotImplementedError

def getMcc3IdEndfbVII1(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return NotImplementedError

def getSerpentId(self):
"""Get the Serpent nuclide identification label."""
raise NotImplementedError
Expand Down Expand Up @@ -243,8 +255,16 @@ def getMcc2Id(self):
return self._base.getMcc2Id()

def getMcc3Id(self):
"""Return the MC2-3 nuclide based on the ENDF/B-VII.1 cross section library."""
return self.getMcc3IdEndfbVII1()

def getMcc3IdEndfbVII0(self):
"""Return the MC2-3 nuclide based on the ENDF/B-VII.0 cross section library."""
return self._base.getMcc3Id()
return self._base.getMcc3IdEndfbVII0()

def getMcc3IdEndfbVII1(self):
"""Return the MC2-3 nuclide based on the ENDF/B-VII.1 cross section library."""
return self._base.getMcc3IdEndfbVII1()

def getNaturalIsotopics(self):
"""Return the natural isotopics root :py:class:`~elements.Element`."""
Expand Down Expand Up @@ -312,7 +332,8 @@ def __init__(
name,
label,
mcc2id=None,
mcc3id=None,
mcc3idEndfbVII0=None,
mcc3idEndfbVII1=None,
):
"""
Create an instance of an INuclide.
Expand Down Expand Up @@ -348,7 +369,8 @@ def __init__(
self.label = label
self.nuSF = 0.0
self.mcc2id = mcc2id or ""
self.mcc3id = mcc3id or ""
self.mcc3idEndfbVII0 = mcc3idEndfbVII0 or ""
self.mcc3idEndfbVII1 = mcc3idEndfbVII1 or ""
addGlobalNuclide(self)
self.element.append(self)

Expand Down Expand Up @@ -593,18 +615,36 @@ def getMcc2Id(self):
return self.mcc2id

def getMcc3Id(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return self.getMcc3IdEndfbVII1()

def getMcc3IdEndfbVII0(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.0 cross section library.

.. impl:: Isotopes and isomers can be queried by MC2-3 ID.
.. impl:: Isotopes and isomers can be queried by MC2-3 ENDF/B-VII.0 ID.
:id: I_ARMI_ND_ISOTOPES3
:implements: R_ARMI_ND_ISOTOPES

This method returns the ``mcc3id`` attribute of a
This method returns the ``mcc3idEndfbVII0`` attribute of a
:py:class:`NuclideBase <armi.nucDirectory.nuclideBases.NuclideBase>`
instance. This attribute is initially populated by reading from the
mcc-nuclides.yaml file in the ARMI resources folder.
"""
return self.mcc3id
return self.mcc3idEndfbVII0

def getMcc3IdEndfbVII1(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library.

.. impl:: Isotopes and isomers can be queried by MC2-3 ENDF/B-VII.1 ID.
:id: I_ARMI_ND_ISOTOPES7
:implements: R_ARMI_ND_ISOTOPES

This method returns the ``mcc3idEndfbVII1`` attribute of a
:py:class:`NuclideBase <armi.nucDirectory.nuclideBases.NuclideBase>`
instance. This attribute is initially populated by reading from the
mcc-nuclides.yaml file in the ARMI resources folder.
"""
return self.mcc3idEndfbVII1

def getMcnpId(self):
"""
Expand Down Expand Up @@ -783,8 +823,16 @@ def getMcc2Id(self):
return self.mcc2id

def getMcc3Id(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return self.getMcc3IdEndfbVII1()

def getMcc3IdEndfbVII0(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.0 cross section library."""
return self.mcc3id
return self.mcc3idEndfbVII0

def getMcc3IdEndfbVII1(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return self.mcc3idEndfbVII1

def getSerpentId(self):
"""Gets the SERPENT ID for this natural nuclide.
Expand Down Expand Up @@ -871,8 +919,16 @@ def getMcc2Id(self):
return self.mcc2id

def getMcc3Id(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return self.getMcc3IdEndfbVII1()

def getMcc3IdEndfbVII0(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.0 cross section library."""
return self.mcc3id
return self.mcc3idEndfbVII0

def getMcc3IdEndfbVII1(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return self.mcc3idEndfbVII1


class LumpNuclideBase(INuclide):
Expand Down Expand Up @@ -937,8 +993,16 @@ def getMcc2Id(self):
return self.mcc2id

def getMcc3Id(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return self.getMcc3IdEndfbVII1()

def getMcc3IdEndfbVII0(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.0 cross section library."""
return self.mcc3id
return self.mcc3idEndfbVII0

def getMcc3IdEndfbVII1(self):
"""Return the MC2-3 nuclide identification label based on the ENDF/B-VII.1 cross section library."""
return self.mcc3idEndfbVII1


def initReachableActiveNuclidesThroughBurnChain(numberDensityDict, activeNuclides):
Expand Down Expand Up @@ -1156,15 +1220,15 @@ def factory():
Reads NIST, MC**2 and burn chain data files to instantiate the :py:class:`INuclides <INuclide>`.
Also clears and fills in the
:py:data:`~armi.nucDirectory.nuclideBases.instances`,
:py:data:`byName`, :py:attr:`byLabel`, and
:py:data:`byMcc3Id` module attributes. This method is automatically run upon
:py:data:`byName`, :py:attr:`byLabel`, :py:data:`byMcc3IdEndfbVII0`, and
:py:data:`byMcc3IdEndfbVII1` module attributes. This method is automatically run upon
loading the module, hence it is not usually necessary to re-run it unless there is a
change to the data files, which should not happen during run time, or a *bad*
:py:class`INuclide` is created.

Notes
-----
This may cannot be run more than once. NuclideBase instances are used throughout the ARMI
This cannot be run more than once. NuclideBase instances are used throughout the ARMI
ecosystem and are even class attributes in some cases. Re-instantiating them would orphan
any existing ones and break everything.
"""
Expand Down Expand Up @@ -1269,27 +1333,39 @@ def readMCCNuclideData():

This function reads the mcc-nuclides.yaml file from the ARMI resources
folder. This file contains the MC\ :sup:`2`-2 ID (from ENDF/B-V.2) and MC\ :sup:`2`-3 ID
(from ENDF/B-VII.0) for all nuclides in MC\ :sup:`2`. The ``mcc2id`` and
``mcc3id`` attributes of each :py:class:`NuclideBase
(from ENDF/B-VII.0) for all nuclides in MC\ :sup:`2`. The ``mcc2id``,
``mcc3idEndfVII0``, and ``mcc3idEndfVII1`` attributes of each :py:class:`NuclideBase
<armi.nucDirectory.nuclideBases.NuclideBase>` instance are updated as
the data is read, and the global dictionaries ``byMcc2Id`` and
``byMcc3Id`` are populated with the nuclide bases keyed by their
corresponding ID for each code.
the data is read, and the global dictionaries ``byMcc2Id``
``byMcc3IdEndfVII0`` and ``byMcc3IdEndfVII1`` are populated with the nuclide bases
keyed by their corresponding ID for each code.
"""
global byMcc2Id
global byMcc3Id
global byMcc3IdEndfbVII0
global byMcc3IdEndfbVII1

with open(os.path.join(context.RES, "mcc-nuclides.yaml"), "r") as f:
yaml = YAML(typ="rt")
nuclides = yaml.load(f)

for n in nuclides:
nb = byName[n]
mcc2id = nuclides[n]["ENDF/B-V.2"]
mcc3id = nuclides[n]["ENDF/B-VII.0"]
mcc3idEndfbVII0 = nuclides[n]["ENDF/B-VII.0"]
mcc3idEndfbVII1 = nuclides[n]["ENDF/B-VII.1"]
if mcc2id is not None:
nb.mcc2id = mcc2id
byMcc2Id[nb.getMcc2Id()] = nb
if mcc3id is not None:
nb.mcc3id = mcc3id
byMcc3Id[nb.getMcc3Id()] = nb
if mcc3idEndfbVII0 is not None:
nb.mcc3idEndfbVII0 = mcc3idEndfbVII0
byMcc3IdEndfbVII0[nb.getMcc3IdEndfbVII0()] = nb
if mcc3idEndfbVII1 is not None:
nb.mcc3idEndfbVII1 = mcc3idEndfbVII1
byMcc3IdEndfbVII1[nb.getMcc3IdEndfbVII1()] = nb

# Have the byMcc3Id dictionary be VII.1 IDs.
byMcc3Id = byMcc3IdEndfbVII1


def updateNuclideBasesForSpecialCases():
Expand Down Expand Up @@ -1379,6 +1455,8 @@ def destroyGlobalNuclides():
global byLabel
global byMcc2Id
global byMcc3Id
global byMcc3IdEndfbVII0
global byMcc3IdEndfbVII1
global byMcnpId
global byAAAZZZSId

Expand All @@ -1388,5 +1466,7 @@ def destroyGlobalNuclides():
byLabel.clear()
byMcc2Id.clear()
byMcc3Id.clear()
byMcc3IdEndfbVII1.clear()
byMcc3IdEndfbVII0.clear()
byMcnpId.clear()
byAAAZZZSId.clear()
46 changes: 37 additions & 9 deletions armi/nucDirectory/tests/test_nuclideBases.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,9 +382,9 @@ def test_curieDefinitionWithRa226(self):
self.assertAlmostEqual(activity, 0.9885593, places=6)

def test_loadMcc2Data(self):
"""Tests consistency with the `mcc-nuclides.yaml` input and the nuclides in the data model.
"""Tests consistency with the `mcc-nuclides.yaml` input and the ENDF/B-V.2 nuclides in the data model.

.. test:: Test that MCC v2 IDs can be queried by nuclides.
.. test:: Test that MCC v2 ENDF/B-V.2 IDs can be queried by nuclides.
:id: T_ARMI_ND_ISOTOPES3
:tests: R_ARMI_ND_ISOTOPES
"""
Expand All @@ -402,14 +402,14 @@ def test_loadMcc2Data(self):

self.assertEqual(len(nuclideBases.byMcc2Id), len(expectedNuclides))

def test_loadMcc3Data(self):
"""Tests consistency with the `mcc-nuclides.yaml` input and the nuclides in the data model.
def test_loadMcc3EndfVII0Data(self):
"""Tests consistency with the `mcc-nuclides.yaml` input and the ENDF/B-VII.0 nuclides in the data model.

.. test:: Test that MCC v3 IDs can be queried by nuclides.
.. test:: Test that MCC v3 ENDF/B-VII.0 IDs can be queried by nuclides.
:id: T_ARMI_ND_ISOTOPES4
:tests: R_ARMI_ND_ISOTOPES

.. test:: Test the MCC nuclide data that was read from file instead of code.
.. test:: Test the MCC ENDF/B-VII.0 nuclide data that was read from file instead of code.
:id: T_ARMI_ND_DATA1
:tests: R_ARMI_ND_DATA
"""
Expand All @@ -420,13 +420,41 @@ def test_loadMcc3Data(self):
[nuc for nuc in data.keys() if data[nuc]["ENDF/B-VII.0"] is not None]
)

for nuc, nb in nuclideBases.byMcc3Id.items():
for nuc, nb in nuclideBases.byMcc3IdEndfbVII0.items():
self.assertIn(nb.name, expectedNuclides)
self.assertEqual(nb.getMcc3Id(), nb.mcc3id)
self.assertEqual(nb.getMcc3IdEndfbVII0(), nb.mcc3idEndfbVII0)
self.assertEqual(nb.getMcc3IdEndfbVII0(), nuc)

# Subtract 1 nuclide due to DUMP2.
self.assertEqual(len(nuclideBases.byMcc3IdEndfbVII0), len(expectedNuclides) - 1)

def test_loadMcc3EndfVII1Data(self):
"""Tests consistency with the `mcc-nuclides.yaml` input and the ENDF/B-VII.1 nuclides in the data model.

.. test:: Test that MCC v3 ENDF/B-VII.1 IDs can be queried by nuclides.
:id: T_ARMI_ND_ISOTOPES6
:tests: R_ARMI_ND_ISOTOPES

.. test:: Test the MCC ENDF/B-VII.1 nuclide data that was read from file instead of code.
:id: T_ARMI_ND_DATA2
:tests: R_ARMI_ND_DATA
"""
with open(os.path.join(RES, "mcc-nuclides.yaml")) as f:
yaml = YAML(typ="rt")
data = yaml.load(f)
expectedNuclides = set(
[nuc for nuc in data.keys() if data[nuc]["ENDF/B-VII.1"] is not None]
)

for nuc, nb in nuclideBases.byMcc3IdEndfbVII1.items():
self.assertIn(nb.name, expectedNuclides)
self.assertEqual(nb.getMcc3IdEndfbVII1(), nb.mcc3idEndfbVII1)
self.assertEqual(nb.getMcc3IdEndfbVII1(), nuc)
self.assertEqual(nb.getMcc3Id(), nb.mcc3idEndfbVII1)
self.assertEqual(nb.getMcc3Id(), nuc)

# Subtract 1 nuclide due to DUMP2.
self.assertEqual(len(nuclideBases.byMcc3Id), len(expectedNuclides) - 1)
self.assertEqual(len(nuclideBases.byMcc3IdEndfbVII1), len(expectedNuclides) - 1)


class TestAAAZZZSId(unittest.TestCase):
Expand Down
3 changes: 2 additions & 1 deletion armi/physics/neutronics/tests/test_crossSectionManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,8 @@ def setUp(self):
sodiumDensity = {"NA23": 0.022166571826233578}
steelDensity = {
"C": 0.0007685664978992269,
"V": 0.0002718224847461385,
"V50": 6.795562118653462e-07,
"V51": 0.0002711429285342731,
"SI28": 0.0003789374369638149,
"SI29": 1.924063709833714e-05,
"SI30": 1.268328992580968e-05,
Expand Down
6 changes: 5 additions & 1 deletion armi/reactor/blueprints/isotopicOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,10 +552,14 @@ def eleExpandInfoBasedOnCodeENDF(cs):
)
)

elif cs[CONF_XS_KERNEL] in ["", "SERPENT", "MC2v3", "MC2v3-PARTISN"]:
elif cs[CONF_XS_KERNEL] == "SERPENT":
elementalsToKeep.update(endf70Elementals)
expansionStrings.update(mc2Expansions)

elif cs[CONF_XS_KERNEL] in ["", "MC2v3", "MC2v3-PARTISN"]:
elementalsToKeep.update(endf71Elementals)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like SERPENT can be removed from this list since its not tested here. Additionally, doesn't this remove support of ENDF/B-VII.0 explicitly? It feels like there should be a setting for which library is being selected OR we should ensure that that changelog notes that this removes the backwards capability.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@john-science, any concerns with removing SERPENT from this list? We could also just make another conditional that has SERPENT default to the endf70Elementals .

Having a setting for the library was my original plan, but global nuclides complicates this. John and I have are hoping to implement such a setting once global nuclides are addressed (#473).

Copy link
Member

@jakehader jakehader Nov 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the complications of the mixed library options based on that ticket and I agree that fixing the global nuclides issue would be a reasonable resolution.

@drewejohnson originally made this setting, so I think it should be appropriate to remove at this time since there is no use for it. I am OK with keeping it as an option though and adding endf70Elementals on that branch or removing SERPENT and updating the changelog.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright Jake, I added a conditional so that VII.0 elementals are used with Serpent.

expansionStrings.update(mc2Expansions)

elif cs[CONF_XS_KERNEL] == "DRAGON":
# Users need to use default nuclear lib name. This is documented.
dragLib = cs["dragonDataPath"]
Expand Down
Loading
Loading