Skip to content

Commit

Permalink
Merge branch 'main' into addNewCompAxialLinkMthd
Browse files Browse the repository at this point in the history
  • Loading branch information
albeanth committed Mar 7, 2024
2 parents 0c995d0 + 64351a0 commit 41127a2
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 198 deletions.
2 changes: 1 addition & 1 deletion armi/bookkeeping/db/tests/test_comparedb3.py
Expand Up @@ -94,7 +94,7 @@ def test_diffResultsBasic(self):
self.assertEqual(dr.nDiffs(), 10)

def test_compareDatabaseDuplicate(self):
"""end-to-end test of compareDatabases() on a photocopy database."""
"""End-to-end test of compareDatabases() on a photocopy database."""
# build two super-simple H5 files for testing
o, r = test_reactors.loadTestReactor(
TEST_ROOT, customSettings={"reloadDBName": "reloadingDB.h5"}
Expand Down
8 changes: 5 additions & 3 deletions armi/cases/suite.py
Expand Up @@ -203,9 +203,10 @@ def run(self):
"""
Run each case, one after the other.
.. warning:: Suite running may not work yet if the cases have interdependencies.
We typically run on a HPC but are still working on a platform
independent way of handling HPCs.
Warning
-------
Suite running may not work yet if the cases have interdependencies. We typically run on a
HPC but are still working on a platform independent way of handling HPCs.
"""
for ci, case in enumerate(self):
runLog.important(f"Running case {ci+1}/{len(self)}: {case}")
Expand Down Expand Up @@ -313,6 +314,7 @@ def writeTable(tableResults):
userFile, refFile, caseIssues = tableResults[testName]
data.append((testName, userFile, refFile, caseIssues))
totalDiffs += caseIssues

print(tabulate.tabulate(data, header, tablefmt=fmt))
print(
tabulate.tabulate(
Expand Down
81 changes: 73 additions & 8 deletions armi/cases/tests/test_cases.py
Expand Up @@ -20,16 +20,20 @@
import platform
import unittest

import h5py

from armi import cases
from armi import context
from armi import getApp
from armi import interfaces
from armi import plugins
from armi import runLog
from armi import settings
from armi.bookkeeping.db.databaseInterface import DatabaseInterface
from armi.physics.fuelCycle.settings import CONF_SHUFFLE_LOGIC
from armi.reactor import blueprints
from armi.reactor import systemLayoutInput
from armi.reactor.tests import test_reactors
from armi.tests import ARMI_RUN_PATH
from armi.tests import mockRunLogs
from armi.tests import TEST_ROOT
Expand Down Expand Up @@ -307,16 +311,10 @@ def test_checkInputs(self):
self.c2.checkInputs()

def test_dependenciesWithObscurePaths(self):
"""
Test directory dependence.
.. tip:: This should be updated to use the Python pathlib
so the tests can work in both Linux and Windows identically.
"""
"""Test directory dependence for strangely-written file paths (escape characters)."""
checks = [
("c1.yaml", "c2.yaml", "c1.h5", True),
(r"\\case\1\c1.yaml", r"\\case\2\c2.yaml", "c1.h5", False),
# below doesn't work due to some windows path obscurities
(r"\\case\1\c1.yaml", r"\\case\2\c2.yaml", r"..\1\c1.h5", False),
]
if platform.system() == "Windows":
Expand All @@ -335,7 +333,7 @@ def test_dependenciesWithObscurePaths(self):
r"c2.yaml",
r".\c1.h5",
True,
), # py bug in 3.6.4 and 3.7.1 fails here
),
(
r"\\cas\es\1\c1.yaml",
r"\\cas\es\2\c2.yaml",
Expand Down Expand Up @@ -436,6 +434,73 @@ def test_buildCommand(self):
self.assertEqual(cmd, 'python -u -m armi run "c1.yaml"')


class TestCaseSuiteComparison(unittest.TestCase):
"""CaseSuite.compare() tests."""

def setUp(self):
self.td = directoryChangers.TemporaryDirectoryChanger()
self.td.__enter__()

def tearDown(self):
self.td.__exit__(None, None, None)

def test_compareNoDiffs(self):
"""As a baseline, this test should always reveal zero diffs."""
# build two super-simple H5 files for testing
o, r = test_reactors.loadTestReactor(
TEST_ROOT, customSettings={"reloadDBName": "reloadingDB.h5"}
)

suites = []
for _i in range(2):
# Build the cases
suite = cases.CaseSuite(settings.Settings())

geom = systemLayoutInput.SystemLayoutInput()
geom.readGeomFromStream(io.StringIO(GEOM_INPUT))
bp = blueprints.Blueprints.load(BLUEPRINT_INPUT)

c1 = cases.Case(cs=settings.Settings(), geom=geom, bp=bp)
c1.cs.path = "c1.yaml"
suite.add(c1)

c2 = cases.Case(cs=settings.Settings(), geom=geom, bp=bp)
c2.cs.path = "c2.yaml"
suite.add(c2)

suites.append(suite)

# create two DBs, identical but for file names
tmpDir = os.getcwd()
dbs = []
for i in range(1, 3):
# create the tests DB
dbi = DatabaseInterface(r, o.cs)
dbi.initDB(fName=f"{tmpDir}/c{i}.h5")
db = dbi.database

# validate the file exists, and force it to be readable again
b = h5py.File(db._fullPath, "r")
self.assertEqual(list(b.keys()), ["inputs"])
self.assertEqual(
sorted(b["inputs"].keys()), ["blueprints", "geomFile", "settings"]
)
b.close()

# append to lists
dbs.append(db)

# do a comparison that should have no diffs
diff = c1.compare(c2)
self.assertEqual(diff, 0)

diff = suites[0].compare(suites[1])
self.assertEqual(diff, 0)

diff = suites[1].compare(suites[0])
self.assertEqual(diff, 0)


class TestExtraInputWriting(unittest.TestCase):
"""Make sure extra inputs from interfaces are written."""

Expand Down
16 changes: 8 additions & 8 deletions armi/reactor/assemblies.py
Expand Up @@ -126,8 +126,7 @@ def renameBlocksAccordingToAssemblyNum(self):
Notes
-----
You must run armi.reactor.reactors.Reactor.regenAssemblyLists after calling
this.
You must run armi.reactor.reactors.Reactor.regenAssemblyLists after calling this.
"""
assemNum = self.getNum()
for bi, b in enumerate(self):
Expand Down Expand Up @@ -303,7 +302,9 @@ def getPinPlenumVolumeInCubicMeters(self):
-----
If there is no plenum blocks in the assembly, a plenum volume of 0.0 is returned
.. warning:: This is a bit design-specific for pinned assemblies
Warning
-------
This is a bit design-specific for pinned assemblies
"""
plenumBlocks = self.getBlocks(Flags.PLENUM)

Expand Down Expand Up @@ -342,8 +343,9 @@ def doubleResolution(self):
-----
Used for mesh sensitivity studies.
.. warning:: This is likely destined for a geometry converter rather than
this instance method.
Warning
-------
This is likely destined for a geometry converter rather than this instance method.
"""
newBlockStack = []
topIndex = -1
Expand Down Expand Up @@ -412,6 +414,7 @@ def adjustResolution(self, refA):
newBlocks -= (
1 # subtract one because we eliminated the original b completely.
)

self.removeAll()
self.spatialGrid = grids.axialUnitGrid(len(newBlockStack))
for b in newBlockStack:
Expand Down Expand Up @@ -439,7 +442,6 @@ def getAxialMesh(self, centers=False, zeroAtFuel=False):
armi.reactor.reactors.Reactor.findAllAxialMeshPoints : gets a global list of all
of these, plus finer res.
"""
bottom = 0.0
meshVals = []
Expand Down Expand Up @@ -509,7 +511,6 @@ def getTotalHeight(self, typeSpec=None):
-------
height : float
the height in cm
"""
h = 0.0
for b in self:
Expand Down Expand Up @@ -561,7 +562,6 @@ def getElevationBoundariesByBlockType(self, blockType=None):
elevation : list of floats
Every float in the list is an elevation of a block boundary for the block
type specified (has duplicates)
"""
elevation, elevationsWithBlockBoundaries = 0.0, []

Expand Down
32 changes: 1 addition & 31 deletions armi/reactor/grids/hexagonal.py
Expand Up @@ -25,7 +25,7 @@
BOUNDARY_60_DEGREES,
BOUNDARY_CENTER,
)
from armi.reactor.grids.locations import IndexLocation, IJKType, IJType
from armi.reactor.grids.locations import IJKType, IJType
from armi.reactor.grids.structuredGrid import StructuredGrid

COS30 = sqrt(3) / 2.0
Expand Down Expand Up @@ -469,33 +469,3 @@ def generateSortedHexLocationList(self, nLocs: int):
)

return locList[:nLocs]

# TODO: this is only used by testing and another method that just needs the count of assemblies
# in a ring, not the actual positions
def allPositionsInThird(self, ring, includeEdgeAssems=False):
"""
Returns a list of all the positions in a ring (in the first third).
Parameters
----------
ring : int
The ring to check
includeEdgeAssems : bool, optional
If True, include repeated positions in odd ring numbers. Default: False
Notes
-----
Rings start at 1, positions start at 1
Returns
-------
positions : int
"""
positions = []
for pos in range(1, self.getPositionsInRing(ring) + 1):
i, j = self.getIndicesFromRingAndPos(ring, pos)
loc = IndexLocation(i, j, 0, None)
if self.isInFirstThird(loc, includeEdgeAssems):
positions.append(pos)

return positions
35 changes: 0 additions & 35 deletions armi/reactor/reactors.py
Expand Up @@ -2350,41 +2350,6 @@ def getAvgTemp(self, typeSpec, blockList=None, flux2Weight=False):
else:
raise RuntimeError("no temperature average for {0}".format(typeSpec))

def getAllNuclidesIn(self, mats):
"""
Find all nuclides that are present in these materials anywhere in the core.
Parameters
----------
mats : iterable or Material
List (or single) of materials to scan the full core for, accumulating a nuclide list
Returns
-------
allNucNames : list
All nuclide names in this material anywhere in the reactor
See Also
--------
getDominantMaterial : finds the most prevalent material in a certain type of blocks
Block.adjustDensity : modifies nuclides in a block
Notes
-----
If you need to know the nuclides in a fuel pin, you can't just use the sample returned
from getDominantMaterial, because it may be a fresh fuel material (U and Zr) even though
there are burned materials elsewhere (with U, Zr, Pu, LFP, etc.).
"""
if not isinstance(mats, list):
# single material passed in
mats = [mats]
names = set(m.name for m in mats)
allNucNames = set()
for c in self.iterComponents():
if c.material.name in names:
allNucNames.update(c.getNuclides())
return list(allNucNames)

def growToFullCore(self, cs):
"""Copies symmetric assemblies to build a full core model out of a 1/3 core model.
Expand Down

0 comments on commit 41127a2

Please sign in to comment.