diff --git a/armi/bookkeeping/db/database3.py b/armi/bookkeeping/db/database3.py index a86715a03..f5e01437f 100644 --- a/armi/bookkeeping/db/database3.py +++ b/armi/bookkeeping/db/database3.py @@ -79,6 +79,7 @@ from armi.reactor import grids from armi.bookkeeping.db.typedefs import History, Histories from armi.reactor import systemLayoutInput +from armi.utils import getNodesPerCycle from armi.utils.textProcessors import resolveMarkupInclusions from armi.nucDirectory import nuclideBases @@ -681,19 +682,20 @@ def load( Providing these from the client could be useful when performing snapshot runs or where it is expected to use results from a run using different settings and continue with new settings (or if blueprints are not on the database). - Geom is read from the database itself. + Geometry is read from the database itself. Parameters ---------- cycle : int - cycle number + Cycle number node : int - time node - cs : armi.settings.Settings, optional - if not provided one is read from the database - bp : armi.reactor.Blueprints, optional - if not provided one is read from the database - statePointName : str, optional + Time node. If value is negative, will be indexed from EOC backwards + like a list. + cs : armi.settings.Settings (optional) + If not provided one is read from the database + bp : armi.reactor.Blueprints (optional) + If not provided one is read from the database + statePointName : str Optional arbitrary statepoint name (e.g., "special" for "c00n00-special/") allowMissing : bool, optional Whether to emit a warning, rather than crash if reading a database @@ -720,6 +722,14 @@ def load( settings.setMasterCs(cs) bp = bp or self.loadBlueprints() + if node < 0: + numNodes = getNodesPerCycle(cs)[cycle] + if (node + numNodes) < 0: + raise ValueError( + f"Node {node} specified does not exist for cycle {cycle}" + ) + node = numNodes + node + h5group = self.h5db[getH5GroupName(cycle, node, statePointName)] layout = Layout((self.versionMajor, self.versionMinor), h5group=h5group) diff --git a/armi/bookkeeping/db/tests/test_database3.py b/armi/bookkeeping/db/tests/test_database3.py index 185969bcf..9e6a0d62b 100644 --- a/armi/bookkeeping/db/tests/test_database3.py +++ b/armi/bookkeeping/db/tests/test_database3.py @@ -326,6 +326,15 @@ def test_load(self): _r = self.db.load(0, 0, allowMissing=True) + # show that we can use negative indices to load + r = self.db.load(0, -2, allowMissing=True) + self.assertEqual(r.p.timeNode, 1) + + with self.assertRaises(ValueError): + # makeShuffleHistory only populates 2 nodes, but the case settings + # defines 3, so we must check -4 before getting an error + self.db.load(0, -4, allowMissing=True) + del self.db.h5db["c00n00/Reactor/missingParam"] _r = self.db.load(0, 0, allowMissing=False) diff --git a/doc/release/0.2.rst b/doc/release/0.2.rst index df15308ba..90b3f38c4 100644 --- a/doc/release/0.2.rst +++ b/doc/release/0.2.rst @@ -13,6 +13,7 @@ What's new in ARMI #. Add pinQuantities parameter category for blockParams that have spatial distribution within a block. #. Use r.core.p.axialMesh instead of r.core.refAssem.getAxialMesh() for the uniform mesh converter. (`PR#959 `_) #. Split algorithms specific to hex assemblies out of ``FuelHandler``. (`PR#962 `_) +#. Add ability to load from a db using negative node index Bug fixes ---------