Skip to content

Commit f5267e0

Browse files
authored
Cleaning out unused code and adding coverage (#1845)
1 parent a7ba5fa commit f5267e0

File tree

9 files changed

+130
-107
lines changed

9 files changed

+130
-107
lines changed

armi/bookkeeping/db/tests/test_databaseInterface.py

+25-9
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,31 @@ def interactEveryNode(self, cycle, node):
7777
self.action(cycle, node)
7878

7979

80+
class TestDatabaseInterfaceBOL(unittest.TestCase):
81+
"""Test the DatabaseInterface class at the BOL."""
82+
83+
def test_interactBOL(self):
84+
"""This test is in its own class, because of temporary directory issues."""
85+
with directoryChangers.TemporaryDirectoryChanger():
86+
self.o, self.r = loadTestReactor(
87+
TEST_ROOT, inputFileName="smallestTestReactor/armiRunSmallest.yaml"
88+
)
89+
self.dbi = DatabaseInterface(self.r, self.o.cs)
90+
91+
dbName = f"{self._testMethodName}.h5"
92+
self.dbi.initDB(fName=dbName)
93+
self.db: Database3 = self.dbi.database
94+
self.stateRetainer = self.r.retainState().__enter__()
95+
self.assertIsNotNone(self.dbi._db)
96+
self.dbi.interactBOL()
97+
self.dbi.closeDB()
98+
self.dbi._db = None
99+
self.assertIsNone(self.dbi._db)
100+
101+
if os.path.exists(dbName):
102+
os.remove(dbName)
103+
104+
80105
class TestDatabaseInterface(unittest.TestCase):
81106
"""Tests for the DatabaseInterface class."""
82107

@@ -105,15 +130,6 @@ def tearDown(self):
105130
if os.path.exists(dirt):
106131
os.remove(dirt)
107132

108-
def test_interactBOL(self):
109-
self.assertIsNotNone(self.dbi._db)
110-
self.dbi.interactBOL()
111-
112-
self.dbi._db = None
113-
self.assertIsNone(self.dbi._db)
114-
self.dbi.interactBOL()
115-
self.assertIsNotNone(self.dbi._db)
116-
117133
def test_distributable(self):
118134
self.assertEqual(self.dbi.distributable(), 4)
119135
self.dbi.interactDistributeState()

armi/physics/fuelCycle/fuelHandlers.py

+53-81
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,9 @@ class FuelHandler:
5454
"""
5555

5656
def __init__(self, operator):
57-
# we need access to the operator to find the core, get settings, grab
58-
# other interfaces, etc.
57+
# we need access to the operator to find the core, get settings, grab other interfaces, etc.
5958
self.o = operator
6059
self.moved = []
61-
self._handleBackwardsCompatibility()
62-
63-
def _handleBackwardsCompatibility(self):
64-
# prepSearch used to be part of the API but is deprecated. This will
65-
# trigger a warning if it's implemented.
66-
# We have to do this hack until we phase out old inputs.
67-
# This basically asks: "Did the custom subclass override prepSearch?"
68-
if self.prepSearch.__func__ is not FuelHandler.prepSearch:
69-
self.prepSearch()
7060

7161
@property
7262
def cycle(self):
@@ -207,30 +197,28 @@ def prepCore(self):
207197
"""Aux function to run before XS generation (do moderation, etc)."""
208198
pass
209199

210-
def prepSearch(self, *args, **kwargs):
200+
@staticmethod
201+
def _compareAssem(candidate, current):
202+
"""Check whether the candidate assembly should replace the current ideal assembly.
203+
204+
Given a candidate tuple (diff1, a1) and current tuple (diff2, a2), decide whether the
205+
candidate is better than the current ideal. This first compares the diff1 and diff2 values.
206+
If diff1 is sufficiently less than diff2, a1 wins, returning True. Otherwise, False. If
207+
diff1 and diff2 are sufficiently close, the assembly with the lesser assemNum wins. This
208+
should result in a more stable comparison than on floating-point comparisons alone.
211209
"""
212-
Optional method that can be implemented in preparation of shuffling.
210+
if np.isclose(candidate[0], current[0], rtol=1e-8, atol=1e-8):
211+
return candidate[1].p.assemNum < current[1].p.assemNum
212+
else:
213+
return candidate[0] < current[0]
213214

214-
Often used to prepare the scope of a shuffling branch search.
215+
@staticmethod
216+
def _getParamMax(a, paramName, blockLevelMax=True):
217+
"""Get parameter with Block-level maximum."""
218+
if blockLevelMax:
219+
return a.getChildParamValues(paramName).max()
215220

216-
Notes
217-
-----
218-
This was used historically to keep a long-lived fuel handler in sync
219-
with the reactor and can now technically be removed from the API, but
220-
many historical fuel management inputs still expect it to be called
221-
by the framework, so here it remains. New developments should
222-
avoid using it. Most code using it has been refactored to just use
223-
a ``_prepSearch`` private method.
224-
225-
It now should not be used and will trigger a DeprecationWarning
226-
in the constructor. It's still here because old user-input code
227-
calls the parent's prepSearch, which is this.
228-
"""
229-
warnings.warn(
230-
"`FuelHandler.prepSearch` is being deprecated from the framework. Please "
231-
"change your fuel management input to call this method directly.",
232-
DeprecationWarning,
233-
)
221+
return a.p[paramName]
234222

235223
def findAssembly(
236224
self,
@@ -295,24 +283,20 @@ def findAssembly(
295283
296284
maxParam : float or list, optional
297285
a parameter to compare to maxVal for setting upper bounds of acceptable assemblies.
298-
If list,
299-
must correspond to parameters in maxVal in order.
286+
If list, must correspond to parameters in maxVal in order.
300287
301288
minVal : float or list, optional
302289
a value or a (parameter, multiplier) tuple for setting lower bounds
303290
304-
For instance, if minParam = 'timeToLimit' and minVal=10, only assemblies with
305-
timeToLimit higher than 10 will be returned. (Of course, there is also maxParam and
306-
maxVal)
291+
For instance, if minParam='timeToLimit' and minVal=10, only assemblies with timeToLimit
292+
higher than 10 will be returned. (Of course, there is also maxParam and maxVal)
307293
308294
maxVal : float or list, optional
309295
a value or a (parameter, multiplier) tuple for setting upper bounds
310296
311297
mandatoryLocations : list, optional
312-
a list of string-representations of locations in the core for limiting the search to
313-
several places
314-
315-
Any locations also included in `excludedLocations` will be excluded.
298+
A list of string-representations of locations in the core for limiting the search to
299+
several places. Any locations also included in `excludedLocations` will be excluded.
316300
317301
excludedLocations : list, optional
318302
a list of string-representations of locations in the core that will be excluded from
@@ -349,20 +333,19 @@ def findAssembly(
349333
default: false.
350334
351335
findFromSfp : bool, optional
352-
if true, will look in the spent-fuel pool instead of in the core.
336+
If true, will look in the spent-fuel pool instead of in the core.
353337
354338
maxNumAssems : int, optional
355339
The maximum number of assemblies to return. Only relevant if findMany==True
356340
357341
circularRingFlag : bool, optional
358-
A flag to toggle on using rings that are based on distance from the center of the
359-
reactor
342+
Toggle using rings that are based on distance from the center of the reactor
360343
361344
Notes
362345
-----
363-
The call signature on this method may have gotten slightly out of hand as
364-
valuable capabilities were added in fuel management studies. For additional expansion,
365-
it may be worth reconsidering the design of these query operations ;).
346+
The call signature on this method may have gotten slightly out of hand as valuable
347+
capabilities were added in fuel management studies. For additional expansion, it may be
348+
worth reconsidering the design of these query operations.
366349
367350
Returns
368351
-------
@@ -381,29 +364,8 @@ def findAssembly(
381364
typeSpec=Flags.FEED | Flags.FUEL)
382365
383366
"""
384-
385-
def compareAssem(candidate, current):
386-
"""Check whether the candidate assembly should replace the current ideal
387-
assembly.
388-
389-
Given a candidate tuple (diff1, a1) and current tuple (diff2, a2), decide
390-
whether the candidate is better than the current ideal. This first compares
391-
the diff1 and diff2 values. If diff1 is sufficiently less than diff2, a1
392-
wins, returning True. Otherwise, False. If diff1 and diff2 are sufficiently
393-
close, the assembly with the lesser assemNum wins. This should result in a
394-
more stable comparison than on floating-point comparisons alone.
395-
"""
396-
if np.isclose(candidate[0], current[0], rtol=1e-8, atol=1e-8):
397-
return candidate[1].p.assemNum < current[1].p.assemNum
398-
else:
399-
return candidate[0] < current[0]
400-
401-
def getParamWithBlockLevelMax(a, paramName):
402-
if blockLevelMax:
403-
return a.getChildParamValues(paramName).max()
404-
return a.p[paramName]
405-
406-
assemList = [] # list for storing multiple results if findMany is true.
367+
# list for storing multiple results if findMany is true.
368+
assemList = []
407369

408370
# process input arguments
409371
if targetRing is None:
@@ -452,7 +414,7 @@ def getParamWithBlockLevelMax(a, paramName):
452414
compVal = compareTo * mult
453415
elif param:
454416
# assume compareTo is an assembly
455-
compVal = getParamWithBlockLevelMax(compareTo, param) * mult
417+
compVal = FuelHandler._getParamMax(compareTo, param, blockLevelMax) * mult
456418

457419
if coords:
458420
# find the assembly closest to xt,yt if coords are given without considering params.
@@ -501,12 +463,16 @@ def getParamWithBlockLevelMax(a, paramName):
501463
if isinstance(minVal, tuple):
502464
# tuple turned in. it's a multiplier and a param
503465
realMinVal = (
504-
getParamWithBlockLevelMax(a, minVal[0]) * minVal[1]
466+
FuelHandler._getParamMax(a, minVal[0], blockLevelMax)
467+
* minVal[1]
505468
)
506469
else:
507470
realMinVal = minVal
508471

509-
if getParamWithBlockLevelMax(a, minParam) < realMinVal:
472+
if (
473+
FuelHandler._getParamMax(a, minParam, blockLevelMax)
474+
< realMinVal
475+
):
510476
# this assembly does not meet the minVal specifications. Skip it.
511477
innocent = False
512478
break # for speed (not a big deal here)
@@ -521,12 +487,16 @@ def getParamWithBlockLevelMax(a, paramName):
521487
if isinstance(maxVal, tuple):
522488
# tuple turned in. it's a multiplier and a param
523489
realMaxVal = (
524-
getParamWithBlockLevelMax(a, maxVal[0]) * maxVal[1]
490+
FuelHandler._getParamMax(a, maxVal[0], blockLevelMax)
491+
* maxVal[1]
525492
)
526493
else:
527494
realMaxVal = maxVal
528495

529-
if getParamWithBlockLevelMax(a, maxParam) > realMaxVal:
496+
if (
497+
FuelHandler._getParamMax(a, maxParam, blockLevelMax)
498+
> realMaxVal
499+
):
530500
# this assembly has a maxParam that's higher than maxVal and therefore
531501
# doesn't qualify. skip it.
532502
innocent = False
@@ -551,23 +521,25 @@ def getParamWithBlockLevelMax(a, paramName):
551521

552522
# Now find the assembly with the param closest to the target val.
553523
if param:
554-
diff = abs(getParamWithBlockLevelMax(a, param) - compVal)
524+
diff = abs(
525+
FuelHandler._getParamMax(a, param, blockLevelMax) - compVal
526+
)
555527

556528
if (
557529
forceSide == 1
558-
and getParamWithBlockLevelMax(a, param) > compVal
559-
and compareAssem((diff, a), minDiff)
530+
and FuelHandler._getParamMax(a, param, blockLevelMax) > compVal
531+
and FuelHandler._compareAssem((diff, a), minDiff)
560532
):
561533
# forceSide=1, so that means look in rings further out
562534
minDiff = (diff, a)
563535
elif (
564536
forceSide == -1
565-
and getParamWithBlockLevelMax(a, param) < compVal
566-
and compareAssem((diff, a), minDiff)
537+
and FuelHandler._getParamMax(a, param, blockLevelMax) < compVal
538+
and FuelHandler._compareAssem((diff, a), minDiff)
567539
):
568540
# forceSide=-1, so that means look in rings closer in from the targetRing
569541
minDiff = (diff, a)
570-
elif compareAssem((diff, a), minDiff):
542+
elif FuelHandler._compareAssem((diff, a), minDiff):
571543
# no preference of which side, just take the one with the closest param.
572544
minDiff = (diff, a)
573545
else:

armi/physics/fuelCycle/tests/test_fuelHandlers.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ def interactBOC(self, cycle=None):
154154

155155

156156
class TestFuelHandler(FuelHandlerTestHelper):
157+
def test_getParamMax(self):
158+
a = self.assembly
159+
160+
res = fuelHandlers.FuelHandler._getParamMax(a, "kInf", True)
161+
self.assertEqual(res, 0.0)
162+
163+
res = fuelHandlers.FuelHandler._getParamMax(a, "kInf", False)
164+
self.assertEqual(res, 0.0)
165+
157166
def test_interactBOC(self):
158167
# set up mock interface
159168
self.o.addInterface(MockLatticePhysicsInterface(self.r, self.o.cs))
@@ -212,6 +221,18 @@ def test_outage(self, mockChooseSwaps):
212221
fh.outage(factor=1.0)
213222
self.assertEqual(len(fh.moved), 0)
214223

224+
def test_outageEdgeCase(self):
225+
class MockFH(fuelHandlers.FuelHandler):
226+
def chooseSwaps(self, factor=1.0):
227+
self.moved = [None]
228+
229+
# mock up a fuel handler
230+
fh = MockFH(self.o)
231+
232+
# test edge case
233+
with self.assertRaises(AttributeError):
234+
fh.outage(factor=1.0)
235+
215236
def test_isAssemblyInAZone(self):
216237
# build a fuel handler
217238
fh = fuelHandlers.FuelHandler(self.o)
@@ -404,8 +425,7 @@ def test_findWithMinMax(self):
404425
expected = lastB.parent
405426
self.assertIs(assem, expected)
406427

407-
# test the impossible: an block with burnup less than
408-
# 110% of its own burnup
428+
# test the impossible: an block with burnup less than 110% of its own burnup
409429
assem = fh.findAssembly(
410430
param="percentBu",
411431
compareTo=100,

armi/physics/neutronics/latticePhysics/latticePhysicsInterface.py

+5-14
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
import os
2121
import shutil
2222

23+
from armi import interfaces
2324
from armi import nuclearDataIO
24-
from armi import interfaces, runLog
25-
from armi.utils import codeTiming
25+
from armi import runLog
2626
from armi.physics import neutronics
2727
from armi.physics.neutronics.const import CONF_CROSS_SECTION
2828
from armi.physics.neutronics.settings import (
@@ -32,26 +32,20 @@
3232
CONF_XS_KERNEL,
3333
CONF_LATTICE_PHYSICS_FREQUENCY,
3434
)
35-
from armi.utils.customExceptions import important
3635
from armi.physics.neutronics import LatticePhysicsFrequency
37-
36+
from armi.utils import codeTiming
3837

3938
LATTICE_PHYSICS = "latticePhysics"
4039

4140

42-
@important
43-
def SkippingXsGen_BuChangedLessThanTolerance(tolerance):
44-
return "Skipping XS Generation this cycle because median block burnups changes less than {}%".format(
45-
tolerance
46-
)
47-
48-
4941
def setBlockNeutronVelocities(r, neutronVelocities):
5042
"""
5143
Set the ``mgNeutronVelocity`` parameter for each block using the ``neutronVelocities`` dictionary data.
5244
5345
Parameters
5446
----------
47+
r : Reactor
48+
A Reactor object, that we want to modify.
5549
neutronVelocities : dict
5650
Dictionary that is keyed with the ``representativeBlock`` XS IDs with values of multigroup neutron
5751
velocity data computed by MC2.
@@ -504,9 +498,6 @@ def _checkBurnupThresholds(self, blockList):
504498
"Recalculating Cross-sections".format(xsID, buOld, buNow)
505499
)
506500

507-
if not idsChangedBurnup:
508-
SkippingXsGen_BuChangedLessThanTolerance(self._burnupTolerance)
509-
510501
return idsChangedBurnup
511502

512503
def _getProcessesPerNode(self):

armi/physics/neutronics/latticePhysics/tests/test_latticeInterface.py

+3
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ def test_interactAll(self):
209209
self.latticeInterface.interactCoupled(iteration=1)
210210
self.assertIsNone(self.o.r.core.lib)
211211

212+
def test_getSuffix(self):
213+
self.assertEqual(self.latticeInterface._getSuffix(7), "")
214+
212215

213216
class TestLatticePhysicsLibraryCreation(TestLatticePhysicsInterfaceBase):
214217
"""Test variations of _newLibraryShouldBeCreated."""

0 commit comments

Comments
 (0)