Skip to content

Commit

Permalink
Add more documentation for loading reactors from database
Browse files Browse the repository at this point in the history
  • Loading branch information
youngmit committed May 15, 2020
1 parent c0edb11 commit 1776a1f
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 12 deletions.
9 changes: 9 additions & 0 deletions armi/bookkeeping/db/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@
from .factory import databaseFactory


__all__ = [
"Database3",
"DatabaseInterface",
"XTViewDatabase",
"compareDatabases",
"databaseFactory",
]


def loadOperator(pathToDb, loadCycle, loadNode):
"""
Return an operator given the path to a database.
Expand Down
7 changes: 4 additions & 3 deletions armi/bookkeeping/db/database3.py
Original file line number Diff line number Diff line change
Expand Up @@ -1196,9 +1196,10 @@ def getHistories(
This implementation is unaware of the state of the reactor outside of the
database itself, and is therefore not usually what client code should be calling
directly. It only knows about historical data that actually exists in the
database. Usually one wants to be able to get historical, plus current data, for
which the similar method on the DatabaseInterface is more useful.
directly during normal ARMI operation. It only knows about historical data that
have actually been written to the database. Usually one wants to be able to get
historical, plus current data, for which the similar method on the
DatabaseInterface may be more useful.
Parameters
==========
Expand Down
36 changes: 27 additions & 9 deletions armi/tests/tutorials/data_model.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -455,9 +455,7 @@
"metadata": {},
"source": [
"## Loading from the database\n",
"Once you have a database, you can load an operator object which has access to the reactor and case settings file.\n",
"\n",
"Warning: While the reactor is in the same state as it was when we wrote the database, the operator may not be. This is because ARMI uses the parameter system to load state, and only the reactor and its children have parameters. Furthermore, anything not stored in a paramter is not written to the database."
"Once you have a database, you can use it to load a Reactor object from any of the states that were written to it. First, create a Database3 object, then open it and call its `load()` method."
]
},
{
Expand All @@ -469,9 +467,10 @@
"from armi.bookkeeping import db\n",
"databaseLocation = \"anl-afci-177.h5\"\n",
"cycle, timeNode = 0, 1\n",
"o = db.loadOperator(databaseLocation, cycle, timeNode)\n",
"r = o.r\n",
"cs = o.cs"
"dbo = db.databaseFactory(databaseLocation, \"r\")\n",
"with dbo:\n",
" # Load a new reactor object from the requested cycle and time node\n",
" r = dbo.load(cycle, timeNode)"
]
},
{
Expand All @@ -495,15 +494,34 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"That's just a brief exploration of the data model. Hopefully it helped orient you to the underlying ARMI structure."
"Having Reactor object by itself can be very useful for all sorts of post-processing tasks. However, sometimes we may wish initialize more ARMI components to do more advanced tasks and interactive follow-on analysis. Lucky for us, the database stores the settings that were used to run the case in the first place. We can get them like this:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
"source": [
"with dbo:\n",
" cs = dbo.loadCS()\n",
" print(cs[\"neutronicsKernel\"])\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"With this `CaseSettings` object, we could create a brand new `Case` and `Operator` and do all sorts of magic. This way of interacting with ARMI is rather advanced, and beyond the scope of this tutorial."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"That's just a brief exploration of the data model. Hopefully it helped orient you to the underlying ARMI structure."
]
}
],
"metadata": {
Expand All @@ -523,7 +541,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
"version": "3.7.2"
}
},
"nbformat": 4,
Expand Down
46 changes: 46 additions & 0 deletions doc/user/outputs/database.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,52 @@ the text of the input files that were used to create the case, and for each time
the values of all composite parameters as well as layout information to help fully
reconstruct the structure of the reactor model.

Loading Reactor State
=====================
Among other things, the database file can be used to recover an ARMI reactor model from
any of the time nodes that it contains. This can be useful for performing restart runs,
or for doing custom post-processing tasks. To load a reactor state, you will need to
open the database file into a ``Database`` object. From there, you can call the
:py:meth:`armi.bookkeeping.db.Database3.load()` method to get a recovered
reactor object. For instance, given a database file called ``myDatabase.h5``, we could
load the reactor state at cycle 5, time node 2 with the following::

from armi.bookkeeping.db import databaseFactory

db = databaseFactory("myDatabase.h5", "r")

# The underlying file is not left open when we can help it. Use the handy context
# manager to temporarily open the file and interact with the data:
with db:
r = db.load(5, 2)

Extracting Reactor History
==========================
Not only can the database reproduce reactor state for a given time node, it can also
extract a history of specific parameters for specific objects through the
:py:meth:`armi.bookkeeping.db.Database3.getHistory()` and
:py:meth:`armi.bookkeeping.db.Database3.getHistories()` methods.
For example, given the reactor object, ``r`` from the example above, we could get the
entire history of an assembly's ring, position and areal power density with the
following::

from armi.reactor.flags import Flags

# grab a fuel assembly from the reactor
a = r.core.getAssemblies(Flags.FUEL)

# Don't forget to open the database!
with db:
aHist = db.getHistory(a, ["ring", "pos", "arealPd"])


Extracting Settings and Blueprints
==================================
As well as the reactor states for each time node, the database file also stores the
input files (blueprints and settings files) used to run the case that generated it.
These can be recovered using the `extract-inputs` ARMI entry point. Use `python -m armi
extract-inputs --help` for more information.

File format
===========

Expand Down

0 comments on commit 1776a1f

Please sign in to comment.