From e13de1a0cc1faf0ac23d8bc5a17f26fc14b5a181 Mon Sep 17 00:00:00 2001 From: John Stilley <1831479+john-science@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:22:31 -0800 Subject: [PATCH] Releasing ARMI version 0.5.0 (#2009) --- .github/workflows/stale.yaml | 2 + README.rst | 5 +- armi/plugins.py | 10 ++-- armi/tests/test_plugins.py | 4 +- doc/developer/guide.rst | 82 +++++++++++++--------------- doc/release/0.4.rst | 86 +----------------------------- doc/release/0.5.rst | 100 +++++++++++++++++++++++++++++++++++ doc/user/outputs.rst | 92 ++++++++++++++++++-------------- pyproject.toml | 2 +- 9 files changed, 203 insertions(+), 180 deletions(-) create mode 100644 doc/release/0.5.rst diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml index cc0167388..2adea167e 100644 --- a/.github/workflows/stale.yaml +++ b/.github/workflows/stale.yaml @@ -14,6 +14,8 @@ permissions: jobs: stale: + # This workflow is not designed to make sense on forks + if: github.repository == 'terrapower/armi' runs-on: ubuntu-24.04 steps: - uses: actions/stale@v8 diff --git a/README.rst b/README.rst index 636ba0ae7..e82f2da5e 100644 --- a/README.rst +++ b/README.rst @@ -385,8 +385,9 @@ like ARMI somewhat recently. ARMI has been written to support specific engineering/design tasks. As such, polish in the GUIs and output is somewhat lacking. -Most of our code is in the ``camelCase`` style, which is not the normal style for -Python. This started in 2009 and we have stuck with the convention. +The ARMI framework uses the ``camelCase`` style, which is not the standard style for Python. As this +is an issue of style, it is not considered worth the API-breaking cost to our downstream users to +change it. License diff --git a/armi/plugins.py b/armi/plugins.py index 59b953000..fdeb4cd66 100644 --- a/armi/plugins.py +++ b/armi/plugins.py @@ -274,12 +274,12 @@ def beforeReactorConstruction(cs) -> None: Function to call before the reactor is constructed. .. impl:: Plugins can inject code before reactor initialization. - :id: I_ARMI_PLUGIN_BEFORE_REACTOR_HOOK - :implements: R_ARMI_PLUGIN_BEFORE_REACTOR_HOOK + :id: I_ARMI_SETTINGS_BEFORE_REACTOR_HOOK + :implements: R_ARMI_SETTINGS_BEFORE_REACTOR_HOOK - This method allows for plugin developers to implement code after settings - are loaded but before the reactor is constructed. This hook is called - in :py:func:`armi.reactor.reactors.factory`. + This method allows for plugin developers to implement code after settings are loaded but + before the reactor is constructed. This hook is called in + :py:func:`armi.reactor.reactors.factory`. """ @staticmethod diff --git a/armi/tests/test_plugins.py b/armi/tests/test_plugins.py index 3674f4366..462d7a7ad 100644 --- a/armi/tests/test_plugins.py +++ b/armi/tests/test_plugins.py @@ -154,8 +154,8 @@ def test_beforeReactorConstructionHook(self): """Test that plugin hook successfully injects code before reactor initialization. .. test:: Capture code in the beforeReactorConstruction hook from reactor construction being carried out. - :id: T_ARMI_PLUGIN_BEFORE_REACTOR_HOOK - :tests: R_ARMI_PLUGIN_BEFORE_REACTOR_HOOK + :id: T_ARMI_SETTINGS_BEFORE_REACTOR_HOOK + :tests: R_ARMI_SETTINGS_BEFORE_REACTOR_HOOK """ pm = getPluginManagerOrFail() pm.register(BeforeReactorPlugin) diff --git a/doc/developer/guide.rst b/doc/developer/guide.rst index 86e434bf6..343200f13 100644 --- a/doc/developer/guide.rst +++ b/doc/developer/guide.rst @@ -2,46 +2,41 @@ Framework Architecture ********************** -Here we will discuss some big-picture elements of the ARMI architecture. Throughout, -links to the API docs will lead to additional details. - -The Reactor Model -================= - -The :py:mod:`~armi.reactor` package is the central representation of a nuclear reactor -in ARMI. All modules can be expected to want access to some element of the state data -in a run, and should be enabled to find the data present somewhere in the ``reactor`` -package's code during runtime. - -An approximation of `Composite Design Pattern -`_ is used to represent the **Reactor** -in ARMI. In this hierarchy the **Reactor** object has a child **Core** object, and -potentially many generic **Composite** child objects representing ex-core structures. -The **Core** is made of **Assembly** objects, which are in turn made up as a collection -of **Block** objects. :term:`State ` variables may be stored at any level -of this hierarchy using the :py:mod:`armi.reactor.parameters` system to contain results -(e.g., ``keff``, ``flow rates``, ``power``, ``flux``, etc.). Within each block are -**Components** that define the pin-level geometry. Associated with each Component are -**Material** objects that contain material properties (``density``, ``conductivity``, -``heat capacity``, etc.) and isotopic mass fractions. - -.. note:: Non-core structures (spent fuel pools, core restraint, heat exchangers, etc.) - may be represented analogously to the **Core**, but this feature is new and under - development. Historically, the **Core** and **Reactor** were the same thing, and some - information in the documentation still reflects this. +What follows is a discussion of the high-level elements of the ARMI framework. Throughout, links to +the API docs will be provided for additional details. + +The Reactor Data Model +====================== + +The ARMI framework represents a nuclear reactor via a reactor data model, which is defined in the +:py:mod:`~armi.reactor` package. Each physical piece of the nuclear reactor is defined by a Python +object, called an :py:class:`ArmiObject `. Each ``ArmiObject`` +has associated data like: shape, material, or other physical values. The physical values can be +nearly anything, and are attached to the data model via ARMI's +:py:mod:`Parameter ` system. Example parameters might be: ``keff``, +``flow rates``, ``power``, ``flux``, etc. + +The reactor data model is a hierarchical model, following the `Composite Design Pattern +`_. The top of the data model is the +:py:class:`Reactor `, which contains one +:py:class:`Core ` object and a collection of zero or more +:py:class:`ExcoreStructures `. An example +``ExcoreStructure`` might be a :py:class:`SpentFuelPool `. + +For now, the ``Core`` object in ARMI assumes it contains **Assembly** objects, which are in turn +made up as a collection of **Block** objects. The leaves of the the Composite Model in the ARMI +framework are called :py:class:`Component `. .. figure:: /.static/armi_reactor_objects.png :align: center The primary data containers in ARMI -Each level of the composite pattern hierarchy contains most of its state data in a -collection of parameters detailing considerations of how the reactor has progressed -through time to any given point. This information also constitutes the majority of what -gets written to the database for evaluation and/or follow-on analysis. +Time-evolving the parameters on the reactor composite hierarchy is what most modelers and analysts +will want from the ARMI framework. -Review the data model :ref:`armi-tutorials` section for examples -exploring a populated instance of the **Reactor** model. +Review the data model :ref:`armi-tutorials` section for examples exploring a populated instance of +the ``Reactor`` data model. Finding objects in a model -------------------------- @@ -101,8 +96,7 @@ various physics operations. For example, some lattice physics routines convert the full core to a 2D R-Z model and compute flux with thousands of energy groups to properly capture the spectral-spatial -coupling in a core/reflector interface. The converters are used heavily in these -operations. +coupling in a core/reflector interface. The converters are used heavily in these operations. Blueprints ---------- @@ -160,7 +154,7 @@ configuration (such as Fuel management, and depletion) are disabled. The Interface Stack ------------------- *Interfaces* (:py:class:`armi.interfaces.Interface`) operate upon the Reactor Model to -do analysis. They're designed to allow expansion of the code in a natural and +do analysis. They're designed to allow expansion of the code in a natural and well-organized manner. Interfaces are useful to link external codes to ARMI as well for adding new internal physics into the rest of the system. As a result, very many aspects of ARMI are contained within interfaces. @@ -235,7 +229,7 @@ hooks include: after every node step/flux calculation, if tight physics coupling is active. These interaction points are optional in every interface, and you may override one or -more of them to suit your needs. You should not change the arguments to the hooks, +more of them to suit your needs. You should not change the arguments to the hooks, which are integers. Each interface has a ``enabled`` flag. If this is set to ``False``, then the interface's @@ -252,7 +246,6 @@ When using the Operators that come with ARMI, Interfaces are discovered using th :py:meth:`createInterfaces ` method. - How interfaces get called ------------------------- @@ -269,9 +262,9 @@ To use interfaces in parallel, please refer to :py:mod:`armi.mpiActions`. Plugins ======= -Plugins are higher-level objects that can bring in one or more Interfaces, settings -definitions, parameters, validations, etc. They are documented in -:ref:`armi-app-making` and :py:mod:`armi.plugins`. +Plugins are higher-level objects that can add things to the simulations like Interfaces, settings +definitions, parameters, validations, etc. They are documented in :ref:`armi-app-making` and +:py:mod:`armi.plugins`. Entry Points @@ -282,9 +275,6 @@ invoke ARMI with ``python -m armi run``, the ``__main__.py`` file is loaded and valid Entry Points are dynamically loaded. The proper entry point (in this case, :py:class:`armi.cli.run.RunEntryPoint`) is invoked. As ARMI initializes itself, settings are loaded into a :py:class:`Settings ` -object. From those settings, an :py:class:`Operator ` +object. From those settings, an :py:class:`Operator ` subclass is built by a factory and its ``operate`` method is called. This fires up the -main ARMI analysis loop and its interface stack is looped over as indicated by user -input. - - +main ARMI analysis loop and its interface stack is looped over as indicated by user input. diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst index 866dd3685..413558d6b 100644 --- a/doc/release/0.4.rst +++ b/doc/release/0.4.rst @@ -2,90 +2,6 @@ ARMI v0.4 Release Notes *********************** -ARMI v0.4.1 -=========== -Release Date: TBD - -New Features ------------- -#. Adding data models for ex-core structures in ARMI. (`PR#1891 `_) -#. ARMI now supports Python 3.12. (`PR#1813 `_) -#. Removing the ``tabulate`` dependency by ingesting it to ``armi.utils.tabulate``. (`PR#1811 `_) -#. Adding ``--skip-inspection`` flag to ``CompareCases`` CLI. (`PR#1842 `_) -#. Allow merging a component with zero area into another component. (`PR#1858 `_) -#. Use ``Block.getNumPins()`` in ``HexBlock._rotatePins()``. (`PR#1859 `_) -#. Provide utilities for determining location of a rotated object in a hexagonal lattice (``getIndexOfRotatedCell``). (`PR#1846 `_) -#. Allow merging a component with zero area into another component. (`PR#1858 `_) -#. Provide ``Parameter.hasCategory`` for quickly checking if a parameter is defined with a given category. (`PR#1899 `_) -#. Provide ``ParameterCollection.where`` for efficient iteration over parameters who's definition matches a given condition. (`PR#1899 `_) -#. Flags can now be defined with letters and numbers. (`PR#1966 `_) -#. Plugins can provide the ``getAxialExpansionChanger`` hook to customize axial expansion. (`PR#1870 `_) -#. ``HexBlock.rotate`` updates the spatial locator for children of that block. (`PR#1943 `_) -#. New plugin hook ``beforeReactorConstruction`` added to enable plugins to process case settings before reactor init. (`PR#1945 `_) -#. Provide ``Block.getInputHeight`` for determining the height of a block from blueprints. (`PR#1927 `_) -#. Improve performance by changing the lattice physics interface so that cross sections are not updated on ``everyNode`` calls during coupled calculations (`PR#1963 `_) -#. Improve efficiency of reaction rate calculations. (`PR#1887 `_) -#. Adding support for ENDF/B-VII.1-based MC2-3 libraries. (`PR#1982 `_) -#. Adding new options for simplifying 1D cross section modeling. (`PR#1949 `_) -#. Updating ``copyOrWarn`` and ``getFileSHA1Hash`` to support directories. (`PR#1984 `_) -#. Exposing ``detailedNDens`` to components. (`PR#1954 `_) -#. TBD - -API Changes ------------ -#. Removing flags ``CORE`` and ``REACTOR``. (`PR#1835 `_) -#. Alphabetizing ``Flags.toString()`` results. (`PR#1912 `_) -#. Moving ``settingsValidation`` from ``operators`` to ``settings``. (`PR#1895 `_) -#. Removing deprecated method ``prepSearch``. (`PR#1845 `_) -#. Removing unused function ``SkippingXsGen_BuChangedLessThanTolerance``. (`PR#1845 `_) -#. Renaming ``Reactor.moveList`` to ``Reactor.moves``. (`PR#1881 `_) -#. ``copyInterfaceInputs`` no longer requires a valid setting object. (`PR#1934 `_) -#. Removing ``buildEqRingSchedule``. (`PR#1928 `_) -#. Removing broken plot ``buVsTime``. (`PR#1994 `_) -#. Allowing for unknown Flags when opening a DB. (`PR#1844 `_) -#. Removing ``Assembly.doubleResolution()``. (`PR#1951 `_) -#. Removing ``assemblyLists.py`` and the ``AssemblyList`` class. (`PR#1891 `_) -#. Removing ``Assembly.rotatePins`` and ``Block.rotatePins``. Prefer ``Assembly.rotate`` and ``Block.rotate``. (`PR#1846 `_) -#. Removing unused setting ``autoGenerateBlockGrids``. (`PR#1947 `_) -#. Transposing ``pinMgFluxes`` parameters so that leading dimension is pin index. (`PR#1937 `_) -#. ``Block.getPinCoordinates`` returns an ``(N, 3)`` array, rather than a length ``N`` list of three-length arrays. (`PR#1943 `_) -#. Removing ``globalFluxInterface.DoseResultsMapper`` class. (`PR#1952 `_) -#. Removing setting ``mpiTasksPerNode`` and renaming ``numProcessors`` to ``nTasks``. (`PR#1958 `_) -#. Changing ``synDbAfterWrite`` default to ``True``. (`PR#1968 `_) -#. Removing unused class ``SmartList``. (`PR#1992 `_) -#. `nuclideBases.byMcc3ID` and `getMcc3Id()` return IDs consistent with ENDF/B-VII.1. (`PR#1982 `_) -#. TBD - -Bug Fixes ---------- -#. Fixed spatial grids of pins in Blocks on flats-up grids. (`PR#1947 `_) -#. Fixed ``DerivedShape.getArea`` for ``cold=True``. (`PR#1831 `_) -#. Fixed error parsing command line integers in ``ReportsEntryPoint``. (`PR#1824 `_) -#. Fixed ``PermissionError`` when using ``syncDbAfterWrite``. (`PR#1857 `_) -#. Fixed ``MpiDirectoryChanger``. (`PR#1853 `_) -#. Changed data type of ``thKernel`` setting from ``bool`` to ``str`` in ``ThermalHydraulicsPlugin``. (`PR#1855 `_) -#. Update height of fluid components after axial expansion. (`PR#1828 `_) -#. Rotate hexagonal assembly patches correctly on facemap plots. (`PR#1883 `_) -#. Material theoretical density is serialized to and read from database. (`PR#1852 `_) -#. Removed broken and unused column in ``summarizeMaterialData``. (`PR#1925 `_) -#. Fixed hex block rotation in ``plotBlockDiagram``. (`PR#1926 `_) -#. Fixed edge case in ``assemblyBlueprint._checkParamConsistency()``. (`PR#1928 `_) -#. Fixed wetted perimeter for hex inner ducts. (`PR#1985 `_) -#. TBD - -Quality Work ------------- -#. Removing deprecated code ``axialUnitGrid``. (`PR#1809 `_) -#. Refactoring ``axialExpansionChanger``. (`PR#1861 `_) -#. Raising a ValueError when database load fails. (`PR#1940 `_) -#. Changes to make axial expansion related classes more extensible. (`PR#1920 `_) -#. TBD - -Changes that Affect Requirements --------------------------------- -#. TBD - - ARMI v0.4.0 =========== Release Date: 2024-07-29 @@ -160,6 +76,6 @@ Quality Work Changes that Affect Requirements -------------------------------- -#. Very minor change to ``Block.coords()``, removing unused argument. (`PR#1651 `_) +#. Removing unused argument to ``Block.coords()``. (`PR#1651 `_) #. Touched ``HexGrid`` by adding a "cornersUp" property and fixing two bugs. (`PR#1649 `_) #. Very slightly modified the implementation of ``Assembly.add()``. (`PR#1670 `_) diff --git a/doc/release/0.5.rst b/doc/release/0.5.rst new file mode 100644 index 000000000..6ebbc39ca --- /dev/null +++ b/doc/release/0.5.rst @@ -0,0 +1,100 @@ +*********************** +ARMI v0.5 Release Notes +*********************** + +ARMI v0.5.1 +=========== +Release Date: TBD + +New Features +------------ +#. TBD + +API Changes +----------- +#. TBD + +Bug Fixes +--------- +#. TBD + +Quality Work +------------ +#. TBD + + +ARMI v0.5.0 +=========== +Release Date: 2024-12-14 + +New Features +------------ +#. Supporting Python 3.12. (`PR#1813 `_) +#. Supporting Python 3.13. (`PR#1996 `_) +#. Adding data models for ex-core structures in ARMI. (`PR#1891 `_) +#. Opening some DBs without the ``App`` that created them. (`PR#1917 `_) +#. Adding support for ENDF/B-VII.1-based MC2-3 libraries. (`PR#1982 `_) +#. Removing the ``tabulate`` dependency by ingesting it to ``armi.utils.tabulate``. (`PR#1811 `_) +#. ``HexBlock.rotate`` updates the spatial locator for children of that block. (`PR#1943 `_) +#. Provide ``Block.getInputHeight`` for determining the height of a block from blueprints. (`PR#1927 `_) +#. Provide ``Parameter.hasCategory`` for quickly checking if a parameter is defined with a given category. (`PR#1899 `_) +#. Provide ``ParameterCollection.where`` for efficient iteration over parameters who's definition matches a given condition. (`PR#1899 `_) +#. Flags can now be defined with letters and numbers. (`PR#1966 `_) +#. Provide utilities for determining location of a rotated object in a hexagonal lattice (``getIndexOfRotatedCell``). (`PR#1846 `_) +#. Allow merging a component with zero area into another component. (`PR#1858 `_) +#. New plugin hook ``getAxialExpansionChanger`` to customize axial expansion. (`PR#1870 `_) +#. New plugin hook ``beforeReactorConstruction`` to process settings before reactor init. (`PR#1945 `_) +#. Improving performance in the lattice physics interface by not updating cross sections at ``everyNode`` during coupled calculations. (`PR#1963 `_) +#. Allow merging a component with zero area into another component. (`PR#1858 `_) +#. Updating ``copyOrWarn`` and ``getFileSHA1Hash`` to support directories. (`PR#1984 `_) +#. Improve efficiency of reaction rate calculations. (`PR#1887 `_) +#. Adding new options for simplifying 1D cross section modeling. (`PR#1949 `_) +#. Adding ``--skip-inspection`` flag to ``CompareCases`` CLI. (`PR#1842 `_) +#. Exposing ``detailedNDens`` to components. (`PR#1954 `_) + +API Changes +----------- +#. ``nuclideBases.byMcc3ID`` and ``getMcc3Id()`` return IDs consistent with ENDF/B-VII.1. (`PR#1982 `_) +#. Moving ``settingsValidation`` from ``operators`` to ``settings``. (`PR#1895 `_) +#. Allowing for unknown Flags when opening a DB. (`PR#1844 `_) +#. Renaming ``Reactor.moveList`` to ``Reactor.moves``. (`PR#1881 `_) +#. Transposing ``pinMgFluxes`` parameters so that leading dimension is pin index. (`PR#1937 `_) +#. ``Block.getPinCoordinates`` returns an ``(N, 3)`` array, rather than a list of arrays. (`PR#1943 `_) +#. Alphabetizing ``Flags.toString()`` results. (`PR#1912 `_) +#. ``copyInterfaceInputs`` no longer requires a valid setting object. (`PR#1934 `_) +#. Changing ``synDbAfterWrite`` default to ``True``. (`PR#1968 `_) +#. Removing ``Assembly.rotatePins`` and ``Block.rotatePins``. Prefer ``Assembly.rotate`` and ``Block.rotate``. (`PR#1846 `_) +#. Removing broken plot ``buVsTime``. (`PR#1994 `_) +#. Removing class ``AssemblyList`` and ``assemblyLists.py``. (`PR#1891 `_) +#. Removing class ``globalFluxInterface.DoseResultsMapper``. (`PR#1952 `_) +#. Removing class ``SmartList``. (`PR#1992 `_) +#. Removing flags ``CORE`` and ``REACTOR``. (`PR#1835 `_) +#. Removing method ``Assembly.doubleResolution()``. (`PR#1951 `_) +#. Removing method ``buildEqRingSchedule``. (`PR#1928 `_) +#. Removing method ``prepSearch``. (`PR#1845 `_) +#. Removing method ``SkippingXsGen_BuChangedLessThanTolerance``. (`PR#1845 `_) +#. Removing setting ``autoGenerateBlockGrids``. (`PR#1947 `_) +#. Removing setting ``mpiTasksPerNode`` and renaming ``numProcessors`` to ``nTasks``. (`PR#1958 `_) + +Bug Fixes +--------- +#. Fixed spatial grids of pins in Blocks on flats-up grids. (`PR#1947 `_) +#. Fixed ``DerivedShape.getArea`` for ``cold=True``. (`PR#1831 `_) +#. Fixed error parsing command line integers in ``ReportsEntryPoint``. (`PR#1824 `_) +#. Fixed ``PermissionError`` when using ``syncDbAfterWrite``. (`PR#1857 `_) +#. Fixed ``MpiDirectoryChanger``. (`PR#1853 `_) +#. Changed data type of ``thKernel`` setting from ``bool`` to ``str`` in ``ThermalHydraulicsPlugin``. (`PR#1855 `_) +#. Update height of fluid components after axial expansion. (`PR#1828 `_) +#. Rotate hexagonal assembly patches correctly on facemap plots. (`PR#1883 `_) +#. Material theoretical density is serialized to and read from database. (`PR#1852 `_) +#. Removed broken and unused column in ``summarizeMaterialData``. (`PR#1925 `_) +#. Fixed hex block rotation in ``plotBlockDiagram``. (`PR#1926 `_) +#. Fixed edge case in ``assemblyBlueprint._checkParamConsistency()``. (`PR#1928 `_) +#. Fixed wetted perimeter for hex inner ducts. (`PR#1985 `_) + +Quality Work +------------ +#. Removing deprecated code ``axialUnitGrid``. (`PR#1809 `_) +#. Refactoring ``axialExpansionChanger``. (`PR#1861 `_) +#. Raising a ``ValueError`` when ``Database.load()`` fails. (`PR#1940 `_) +#. Making axial expansion-related classes more extensible. (`PR#1920 `_) diff --git a/doc/user/outputs.rst b/doc/user/outputs.rst index 71152caad..db152f9b4 100644 --- a/doc/user/outputs.rst +++ b/doc/user/outputs.rst @@ -2,8 +2,8 @@ Outputs ******* -ARMI output files are described in this section. Many outputs may be generated during an ARMI run. They fall into -various categories: +ARMI output files are described in this section. Many outputs may be generated during an ARMI run. +They fall into various categories: Framework outputs Files like the **stdout** and the **database** are produced in nearly all runs. @@ -15,10 +15,10 @@ Physics kernel outputs If ARMI executes an external physics kernel during a run, its associated output files are often available in the working directory. These files are typically read by ARMI during the run, and relevant data is transferred onto the reactor model (and ends up in the ARMI **database**). If the user desires to retain all of the inputs and outputs - associated with the physics kernel runs for a given time step, this can be specified with the ``savePhysicsIO`` setting. - For any time step specified in the list under ``savePhysicsIO``, a ``cXnY/`` folder will be created, and ARMI will store all - inputs and outputs associated with each physics kernel executed at this time step in a folder inside of ``cXnY/``. - The format for specifying a state point is 00X00Y for cycle X, step Y. + associated with the physics kernel runs for a given time step, this can be specified with the ``savePhysicsIO`` + setting. For any time step specified in the list under ``savePhysicsIO``, a ``cXnY/`` folder will be created, and + ARMI will store all inputs and outputs associated with each physics kernel executed at this time step in a folder + inside of ``cXnY/``. The format for specifying a state point is 00X00Y for cycle X, step Y. Together the output fully define the analyzed ARMI case. @@ -68,28 +68,26 @@ This provides live information on the progress. The Database File ================= -The **database** file is a self-contained complete (or nearly complete) binary -representation of the ARMI composite model state during a case. The database contains -the text of the input files that were used to create the case, and for each time node, -the values of all composite parameters as well as layout information to help fully -reconstruct the structure of the reactor model. +The **database** file is a self-contained, binary representation of the state of the ARMI composite +model state during a simulation. The database contains full, plain-text of the input files that were +used to create the case. And for each time node, the values of all composite parameters as well as +layout information to help fully reconstruct the reactor data 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.Database.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:: +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 analysis. 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.Database.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: + # The underlying file is not left open unless necessary. Use the handy context manager to + # temporarily open the file and interact with the data: with db: r = db.load(5, 2) @@ -127,28 +125,22 @@ available for viewing, editing, and scripting HDF5 files. The ARMI database uses `h5py` package for interacting with the underlying data and metadata. At a high level there are 3 things to know about HDF5: -1. Groups - groups are named collections of datasets. You might think of a group as a - filesystem folder. -2. Datasets - Datasets are named values. If a group is a folder, a dataset - is a file. Values are - strongly typed (think `int`, `float`, `double`, but also whether it is big endian, - little endian so that the file is portable across different systems). Values can be - scalar, vector, or N-dimensional arrays. -3. Attributes - attributes can exist on a dataset or a group to provide supplemental - information about the group or dataset. We use attributes to indicate the ARMI - database version that was used to create the database, the time the case was - executed, and whether or not the case completed successfully. We also sometimes apply - attributes to datasets to indicate if any special formatting or layout was used to - store Parameter values or the like. - -There are many other features of HDF5, but from a usability standpoint that is enough -information to get started. +1. **Groups** - Groups are named collections of datasets. Think of a group as a filesystem folder. +2. **Datasets** - Datasets are named values. If a group is a folder, a dataset is a file. Values are + strongly typed (think `int`, `float`, `double`, but also whether it is big endian, little endian + so that the file is portable across different systems). Values can be scalar, vector, or + N-dimensional arrays. +3. **Attributes** - Attributes can exist on a dataset or a group to provide supplemental + information about the group or dataset. We use attributes to indicate the ARMI database version + that was used to create the database, the time the case was executed, and whether or not the + case completed successfully. We also sometimes apply attributes to datasets to indicate if any + special formatting or layout was used to store Parameter values or the like. + +There are many other features of HDF5, but this is enough information to get started. Database Structure ------------------ -The database structure is outlined below. This shows the broad strokes of how the -database is put together, but many more details may be gleaned from the in-line -documentation of the database modules. +The broad strokes of the database structure is outlined below. .. list-table:: Database structure :header-rows: 1 @@ -257,3 +249,25 @@ such special data to the HDF5 file and reading it back again is accomplished wit :py:func:`armi.bookkeeping.db.database.packSpecialData` and :py:func:`armi.bookkeeping.db.database.unpackSpecialData`. Refer to their implementations and documentation for more details. + +Loading Reactor State as Read-Only +---------------------------------- +Another option you have, though it will probably come up less often, is to lead a ``Reactor`` object +from a database file in read-only mode. Mostly what this does is set all the parameters loaded into +the reactor data model to a read-only mode. This can be useful to ensure that downstream analysts +do not modify the data they are reading. It looks much like the usual database load:: + + from armi.bookkeeping.db import databaseFactory + + db = databaseFactory("myDatabase.h5", "r") + + with db: + r = db.loadReadOnly(5, 2) + +Another common use for ``Database.loadReadOnly()`` is when you want to build a tool for analysts +that can open an ARMI database file without the ``App`` that created it. Solving such a problem +generically is hard-or-impossible, but assuming you probably know a lot about the ``App`` that +created an ARMI output file, this is usually doable in practice. To do so, you will want to look at +the :py:class:`PassiveDBLoadPlugin `. +This tool allows you to passively load an output database even if there are parameters or blueprint +sections that are unknown. diff --git a/pyproject.toml b/pyproject.toml index bcb14e86b..a1b4c6a2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ build-backend = "setuptools.build_meta" [project] name = "armi" -version = "0.4.0" +version = "0.5.0" description = "An open-source nuclear reactor analysis automation framework that helps design teams increase efficiency and quality." license = {file = "LICENSE.md"} requires-python = ">3.8"