Skip to content

Commit

Permalink
Expose some skip inspection options for armi.init and `db.loadOpera…
Browse files Browse the repository at this point in the history
…tor` (#2005)
  • Loading branch information
opotowsky authored Nov 26, 2024
1 parent 1c8b1d0 commit dcef81a
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 10 deletions.
8 changes: 6 additions & 2 deletions armi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def isStableReleaseVersion(version=None):
return "-" not in version


def init(choice=None, fName=None, cs=None):
def init(choice=None, fName=None, cs=None, skipInspection=False):
"""
Scan a directory for armi inputs and load one to interact with.
Expand Down Expand Up @@ -144,6 +144,9 @@ def init(choice=None, fName=None, cs=None):
If supplied, this CS object will supercede the other case input methods and use
the object directly.
skipInspection : bool, optional
Whether or not the inputs should be checked for valid settings. Default is False.
Examples
--------
>>> o = armi.init()
Expand All @@ -157,7 +160,8 @@ def init(choice=None, fName=None, cs=None):
cs = settings.Settings(fName)

armiCase = cases.Case(cs=cs)
armiCase.checkInputs()
if not skipInspection:
armiCase.checkInputs()

try:
return armiCase.initializeOperator()
Expand Down
6 changes: 5 additions & 1 deletion armi/bookkeeping/db/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def loadOperator(
loadNode,
statePointName=None,
allowMissing=False,
handleInvalids=True,
):
"""
Return an operator given the path to a database.
Expand All @@ -104,6 +105,8 @@ def loadOperator(
allowMissing : bool
Whether to emit a warning, rather than crash if reading a database
with undefined parameters. Default False.
handleInvalids : bool
Whether to check for invalid settings. Default True.
See Also
--------
Expand Down Expand Up @@ -145,14 +148,15 @@ def loadOperator(
# init Case here as it keeps track of execution time and assigns a reactor
# attribute. This attribute includes the time it takes to initialize the reactor
# so creating a reactor from the database should be included.
cs = db.loadCS()
cs = db.loadCS(handleInvalids=handleInvalids)
thisCase = cases.Case(cs)

r = db.load(
loadCycle,
loadNode,
statePointName=statePointName,
allowMissing=allowMissing,
handleInvalids=handleInvalids,
)

o = thisCase.initializeOperator(r=r)
Expand Down
16 changes: 13 additions & 3 deletions armi/bookkeeping/db/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,9 +393,14 @@ def fileName(self, fName):
raise RuntimeError("Cannot change Database file name while it's opened!")
self._fileName = fName

def loadCS(self):
def loadCS(self, handleInvalids=True):
"""Attempt to load settings from the database file.
Parameters
----------
handleInvalids : bool
Whether to check for invalid settings. Default True.
Notes
-----
There are no guarantees here. If the database was written from a different version of ARMI than you are using,
Expand All @@ -405,7 +410,9 @@ def loadCS(self):
cs = settings.Settings()
cs.caseTitle = os.path.splitext(os.path.basename(self.fileName))[0]
try:
cs.loadFromString(self.h5db["inputs/settings"].asstr()[()])
cs.loadFromString(
self.h5db["inputs/settings"].asstr()[()], handleInvalids=handleInvalids
)
except KeyError:
# not all paths to writing a database require inputs to be written to the
# database. Technically, settings do affect some of the behavior of database
Expand Down Expand Up @@ -708,6 +715,7 @@ def load(
bp=None,
statePointName=None,
allowMissing=False,
handleInvalids=True,
):
"""Load a new reactor from a DB at (cycle, node).
Expand Down Expand Up @@ -743,6 +751,8 @@ def load(
allowMissing : bool, optional
Whether to emit a warning, rather than crash if reading a database
with undefined parameters. Default False.
handleInvalids : bool
Whether to check for invalid settings. Default True.
Returns
-------
Expand All @@ -751,7 +761,7 @@ def load(
"""
runLog.info("Loading reactor state for time node ({}, {})".format(cycle, node))

cs = cs or self.loadCS()
cs = cs or self.loadCS(handleInvalids=handleInvalids)
bp = bp or self.loadBlueprints()

if node < 0:
Expand Down
42 changes: 38 additions & 4 deletions armi/bookkeeping/db/tests/test_database3.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
"""Tests for the Database class."""
from glob import glob
import io
import os
import shutil
import subprocess
Expand All @@ -23,6 +24,7 @@

from armi.bookkeeping.db import _getH5File
from armi.bookkeeping.db import database
from armi.bookkeeping.db import loadOperator
from armi.bookkeeping.db.databaseInterface import DatabaseInterface
from armi.bookkeeping.db.jaggedArray import JaggedArray
from armi.reactor import parameters
Expand All @@ -32,6 +34,7 @@
from armi.reactor.spentFuelPool import SpentFuelPool
from armi.reactor.tests.test_reactors import loadTestReactor, reduceTestReactorRings
from armi.settings.fwSettings.globalSettings import CONF_SORT_REACTOR
from armi.tests import mockRunLogs
from armi.tests import TEST_ROOT
from armi.utils import getPreviousTimeNode
from armi.utils.directoryChangers import TemporaryDirectoryChanger
Expand Down Expand Up @@ -206,10 +209,6 @@ def setUp(self):
self.db: database.Database = self.dbi.database
self.stateRetainer = self.r.retainState().__enter__()

# used to test location-based history. see details below
self.centralAssemSerialNums = []
self.centralTopBlockSerialNums = []

def tearDown(self):
self.db.close()
self.stateRetainer.__exit__()
Expand All @@ -226,6 +225,41 @@ def makeHistory(self):

self.db.writeToDB(self.r)

def test_loadOperator(self):
self.makeHistory()
self.db.close()
# Write a bad setting to the DB
with h5py.File(self.db.fileName, "r+") as hf:
settingz = hf["inputs/settings"].asstr()[()]
settingz += " fakeTerminator: I'll be back"
stream = io.StringIO(settingz)
csString = stream.read()
del hf["inputs/settings"]
hf["inputs/settings"] = csString

# Test with no complaints
with mockRunLogs.BufferLog() as mock:
_o = loadOperator(
self._testMethodName + ".h5",
0,
0,
allowMissing=True,
handleInvalids=False,
)
self.assertNotIn("fakeTerminator", mock.getStdout())

# Test with complaints
with mockRunLogs.BufferLog() as mock:
_o = loadOperator(
self._testMethodName + ".h5",
0,
0,
allowMissing=True,
handleInvalids=True,
)
self.assertIn("Ignoring invalid settings", mock.getStdout())
self.assertIn("fakeTerminator", mock.getStdout())

def _compareArrays(self, ref, src):
"""
Compare two numpy arrays.
Expand Down
1 change: 1 addition & 0 deletions doc/release/0.5.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ New Features
#. Improve efficiency of reaction rate calculations. (`PR#1887 <https://github.com/terrapower/armi/pull/1887>`_)
#. Adding new options for simplifying 1D cross section modeling. (`PR#1949 <https://github.com/terrapower/armi/pull/1949>`_)
#. Adding ``--skip-inspection`` flag to ``CompareCases`` CLI. (`PR#1842 <https://github.com/terrapower/armi/pull/1842>`_)
#. Exposing skip inspection options for ``armi.init`` and ``db.loadOperator``. (`PR#2005 <https://github.com/terrapower/armi/pull/2005>`_)
#. Exposing ``detailedNDens`` to components. (`PR#1954 <https://github.com/terrapower/armi/pull/1954>`_)
#. Adding a method ``getPinMgFluxes`` to get pin-wise multigroup fluxes from a Block. (`PR#1990 <https://github.com/terrapower/armi/pull/1990>`_)

Expand Down

0 comments on commit dcef81a

Please sign in to comment.