Skip to content

Commit

Permalink
Merge branch 'main' into betterISOPrints
Browse files Browse the repository at this point in the history
  • Loading branch information
john-science committed Nov 20, 2024
2 parents d5892f2 + e13de1a commit a730ad5
Show file tree
Hide file tree
Showing 51 changed files with 1,565 additions and 500 deletions.
1 change: 1 addition & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ jobs:
mpiexec -n 2 --use-hwthread-cpus coverage run --rcfile=pyproject.toml -m pytest --cov=armi --cov-config=pyproject.toml --cov-report=lcov --cov-append --ignore=venv armi/tests/test_mpiParameters.py || true
mpiexec -n 2 --use-hwthread-cpus coverage run --rcfile=pyproject.toml -m pytest --cov=armi --cov-config=pyproject.toml --cov-report=lcov --cov-append --ignore=venv armi/tests/test_mpiDirectoryChangers.py || true
coverage combine --rcfile=pyproject.toml --keep -a
coverage report --rcfile=pyproject.toml -i --skip-empty --skip-covered --sort=cover --fail-under=90
- name: Publish to coveralls.io
uses: coverallsapp/github-action@v2
with:
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
push:
branches:
- main
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down Expand Up @@ -37,10 +38,18 @@ jobs:
git submodule update
make html
- name: deploy
if: github.ref == 'refs/heads/main'
uses: JamesIves/[email protected]
with:
token: ${{ secrets.ACCESS_TOKEN }}
repository-name: ${{ github.repository_owner }}/terrapower.github.io
branch: main
folder: doc/_build/html
target-folder: armi
- name: Archive Docs from PR
if: github.ref != 'refs/heads/main'
uses: actions/upload-artifact@v4
with:
name: pr-docs
path: doc/_build/html
retention-days: 5
2 changes: 2 additions & 0 deletions .github/workflows/stale.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ permissions:

jobs:
stale:
# This workflow is not designed to make sense on forks
if: github.repository == 'terrapower/armi'
runs-on: ubuntu-24.04
steps:
- uses: actions/stale@v8
Expand Down
13 changes: 7 additions & 6 deletions .github/workflows/unittests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ jobs:
runs-on: ubuntu-24.04
strategy:
matrix:
python: [3.9, '3.10', '3.11', '3.12']
python: [3.9, '3.10', '3.11', '3.12', '3.13']

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
allow-prereleases: true
- name: Update package index
run: sudo apt-get update
- name: Install mpi libs
Expand All @@ -37,6 +38,6 @@ jobs:
run: |
pip install -e .[memprof,mpi,test]
pytest -n 4 armi
mpiexec -n 2 --use-hwthread-cpus coverage run --rcfile=pyproject.toml -m pytest --cov=armi --cov-config=pyproject.toml --ignore=venv armi/tests/test_mpiFeatures.py || true
mpiexec -n 2 --use-hwthread-cpus coverage run --rcfile=pyproject.toml -m pytest --cov=armi --cov-config=pyproject.toml --ignore=venv armi/tests/test_mpiParameters.py || true
mpiexec -n 2 --use-hwthread-cpus coverage run --rcfile=pyproject.toml -m pytest --cov=armi --cov-config=pyproject.toml --ignore=venv armi/utils/tests/test_directoryChangersMpi.py || true
mpiexec -n 2 --use-hwthread-cpus pytest armi/tests/test_mpiFeatures.py
mpiexec -n 2 --use-hwthread-cpus pytest armi/tests/test_mpiParameters.py
mpiexec -n 2 --use-hwthread-cpus pytest armi/utils/tests/test_directoryChangersMpi.py
5 changes: 3 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,9 @@ like ARMI somewhat recently.
ARMI has been written to support specific engineering/design tasks. As such, polish in
the GUIs and output is somewhat lacking.

Most of our code is in the ``camelCase`` style, which is not the normal style for
Python. This started in 2009 and we have stuck with the convention.
The ARMI framework uses the ``camelCase`` style, which is not the standard style for Python. As this
is an issue of style, it is not considered worth the API-breaking cost to our downstream users to
change it.


License
Expand Down
10 changes: 6 additions & 4 deletions 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 Expand Up @@ -228,15 +228,17 @@ def test_diffSpecialData(self):
refData4 = f4.create_dataset("numberDensities", data=a2)
refData4.attrs["shapes"] = "2"
refData4.attrs["numDens"] = a2
refData4.attrs["specialFormatting"] = True
f5 = h5py.File("test_diffSpecialData5.hdf5", "w")
srcData5 = f5.create_dataset("numberDensities", data=a2)
srcData5.attrs["shapes"] = "2"
srcData5.attrs["numDens"] = a2
srcData5.attrs["specialFormatting"] = True

# there should an exception
with self.assertRaises(Exception) as e:
# there should a log message
with mockRunLogs.BufferLog() as mock:
_diffSpecialData(refData4, srcData5, out, dr)
self.assertIn("Unable to unpack special data for paramName", e)
self.assertIn("Unable to unpack special data for", mock.getStdout())

# make an H5 datasets that will add a np.inf diff because keys don't match
f6 = h5py.File("test_diffSpecialData6.hdf5", "w")
Expand Down
2 changes: 1 addition & 1 deletion armi/bookkeeping/historyTracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ def writeAssemHistory(self, a, fName=""):
out.write("\n\n\nAssembly info\n")
out.write("{0} {1}\n".format(a.getName(), a.getType()))
for b in blocks:
out.write('"{}" {} {}\n'.format(b.getType(), b.p.xsType, b.p.buGroup))
out.write('"{}" {} {}\n'.format(b.getType(), b.p.xsType, b.p.envGroup))

def preloadBlockHistoryVals(self, names, keys, timesteps):
"""
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()
Loading

0 comments on commit a730ad5

Please sign in to comment.