From b4092f77ac2833dbc3192babc8eaf0dac5fe0d31 Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Thu, 10 Oct 2024 20:31:01 +0000 Subject: [PATCH 1/4] Add new plugin hook for reactor init. Then move some code to that new hook impl. --- armi/plugins.py | 9 +++++++++ armi/reactor/__init__.py | 13 +++++++++++++ armi/reactor/reactors.py | 10 ++++------ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/armi/plugins.py b/armi/plugins.py index f772ef43c..c7d459609 100644 --- a/armi/plugins.py +++ b/armi/plugins.py @@ -267,6 +267,15 @@ def onProcessCoreLoading(core, cs, dbLoad) -> None: constructing a Core from Blueprints, or after loading it from a database. """ + @staticmethod + @HOOKSPEC + def beforeReactorConstruction(cs) -> None: + """ + Function to call before the reactor is constructed. + + TODO fill out. Requirement for this? + """ + @staticmethod @HOOKSPEC def defineFlags() -> Dict[str, Union[int, flags.auto]]: diff --git a/armi/reactor/__init__.py b/armi/reactor/__init__.py index 2cd096767..e81283851 100644 --- a/armi/reactor/__init__.py +++ b/armi/reactor/__init__.py @@ -51,6 +51,7 @@ from typing import Dict, Callable, Union, TYPE_CHECKING +from armi import materials from armi import plugins if TYPE_CHECKING: @@ -62,6 +63,18 @@ class ReactorPlugin(plugins.ArmiPlugin): """Plugin exposing built-in reactor components, blocks, assemblies, etc.""" + @staticmethod + @plugins.HOOKIMPL + def beforeReactorConstruction(cs) -> None: + from armi.settings.fwSettings.globalSettings import ( + CONF_MATERIAL_NAMESPACE_ORDER, + ) + + # just before reactor construction, update the material "registry" with user settings, + # if it is set. Often it is set by the application. + if cs[CONF_MATERIAL_NAMESPACE_ORDER]: + materials.setMaterialNamespaceOrder(cs[CONF_MATERIAL_NAMESPACE_ORDER]) + @staticmethod @plugins.HOOKIMPL def defineBlockTypes(): diff --git a/armi/reactor/reactors.py b/armi/reactor/reactors.py index 31eae2bc4..676cd6c58 100644 --- a/armi/reactor/reactors.py +++ b/armi/reactor/reactors.py @@ -19,7 +19,7 @@ from typing import Optional import copy -from armi import materials +from armi import getPluginManagerOrFail from armi import runLog from armi.reactor import composites from armi.reactor import reactorParameters @@ -29,7 +29,6 @@ from armi.reactor.systemLayoutInput import SystemLayoutInput from armi.settings.fwSettings.globalSettings import ( CONF_GEOM_FILE, - CONF_MATERIAL_NAMESPACE_ORDER, CONF_SORT_REACTOR, ) from armi.utils import directoryChangers @@ -180,10 +179,9 @@ def factory(cs, bp, geom: Optional[SystemLayoutInput] = None) -> Reactor: from armi.reactor import blueprints runLog.header("=========== Constructing Reactor and Verifying Inputs ===========") - # just before reactor construction, update the material "registry" with user settings, - # if it is set. Often it is set by the application. - if cs[CONF_MATERIAL_NAMESPACE_ORDER]: - materials.setMaterialNamespaceOrder(cs[CONF_MATERIAL_NAMESPACE_ORDER]) + + getPluginManagerOrFail().hook.beforeReactorConstruction(cs=cs) + r = Reactor(cs.caseTitle, bp) if cs[CONF_GEOM_FILE]: From f0e6191030bc1b5b783ae1dbae7fef93d3d1d067 Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Thu, 10 Oct 2024 20:37:07 +0000 Subject: [PATCH 2/4] release notes --- doc/release/0.4.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst index e427faf9a..5364f5125 100644 --- a/doc/release/0.4.rst +++ b/doc/release/0.4.rst @@ -14,11 +14,12 @@ New Features #. 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 `_) -#. Plugins can provide the ``getAxialExpansionChanger`` hook to customize axial expansion. (`PR#1870 `_) +#. New plugin hook ``beforeReactorConstruction`` added to enable plugins to process case settings before reactor init. (`PR#1945 `_) #. TBD API Changes @@ -32,7 +33,7 @@ API Changes #. Removing ``buildEqRingSchedule``. (`PR#1928 `_) #. Allowing for unknown Flags when opening a DB. (`PR#1844 `_) #. Removing ``assemblyLists.py`` and the ``AssemblyList`` class. (`PR#1891 `_) -#. Removing ``Assembly.rotatePins`` and ``Block.rotatePins``. Prefer ``Assembly.rotate`` and ``Block.rotate``. (`PR#1846 `_) #. Transposing ``pinMgFluxes`` parameters so that leading dimension is pin index (`PR#1937 `) #. TBD From 576d9e3f1a89524200e21907019b364646c6697a Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Fri, 11 Oct 2024 22:59:41 +0000 Subject: [PATCH 3/4] add unit test with impl and test tags as well --- armi/plugins.py | 8 +++++++- armi/tests/test_plugins.py | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/armi/plugins.py b/armi/plugins.py index c7d459609..59b953000 100644 --- a/armi/plugins.py +++ b/armi/plugins.py @@ -273,7 +273,13 @@ def beforeReactorConstruction(cs) -> None: """ Function to call before the reactor is constructed. - TODO fill out. Requirement for this? + .. impl:: Plugins can inject code before reactor initialization. + :id: I_ARMI_PLUGIN_BEFORE_REACTOR_HOOK + :implements: R_ARMI_PLUGIN_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`. """ @staticmethod diff --git a/armi/tests/test_plugins.py b/armi/tests/test_plugins.py index 209fe7336..b56aa4023 100644 --- a/armi/tests/test_plugins.py +++ b/armi/tests/test_plugins.py @@ -56,6 +56,15 @@ def getAxialExpansionChanger() -> type[SillyAxialExpansionChanger]: return SillyAxialExpansionChanger +class BeforeReactorPlugin(plugins.ArmiPlugin): + """Trivial plugin that implements the before reactor construction hook.""" + + @staticmethod + @plugins.HOOKIMPL + def beforeReactorConstruction(cs) -> None: + cs.beforeReactorConstructionFlag = True + + class TestPluginRegistration(unittest.TestCase): def setUp(self): """ @@ -119,6 +128,20 @@ def test_axialExpansionHook(self): # that plugin's axial expander self.assertIs(second, SillyAxialExpansionChanger) + 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 + """ + pm = getPluginManagerOrFail() + pm.register(BeforeReactorPlugin) + o = loadTestReactor( + TEST_ROOT, inputFileName="smallestTestReactor/armiRunSmallest.yaml" + )[0] + self.assertTrue(o.cs.beforeReactorConstructionFlag) + class TestPluginBasics(unittest.TestCase): def test_defineParameters(self): From 553f29fcdf29cfaac50905c2f615346694f05b90 Mon Sep 17 00:00:00 2001 From: Arrielle Opotowsky Date: Mon, 14 Oct 2024 17:28:53 -0500 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: John Stilley <1831479+john-science@users.noreply.github.com> --- armi/reactor/__init__.py | 5 +++-- armi/reactor/reactors.py | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/armi/reactor/__init__.py b/armi/reactor/__init__.py index e81283851..c7c3981d0 100644 --- a/armi/reactor/__init__.py +++ b/armi/reactor/__init__.py @@ -66,12 +66,13 @@ class ReactorPlugin(plugins.ArmiPlugin): @staticmethod @plugins.HOOKIMPL def beforeReactorConstruction(cs) -> None: + """Just before reactor construction, update the material "registry" with user settings, + if it is set. Often it is set by the application. + """ from armi.settings.fwSettings.globalSettings import ( CONF_MATERIAL_NAMESPACE_ORDER, ) - # just before reactor construction, update the material "registry" with user settings, - # if it is set. Often it is set by the application. if cs[CONF_MATERIAL_NAMESPACE_ORDER]: materials.setMaterialNamespaceOrder(cs[CONF_MATERIAL_NAMESPACE_ORDER]) diff --git a/armi/reactor/reactors.py b/armi/reactor/reactors.py index 676cd6c58..1c5b862d5 100644 --- a/armi/reactor/reactors.py +++ b/armi/reactor/reactors.py @@ -179,7 +179,6 @@ def factory(cs, bp, geom: Optional[SystemLayoutInput] = None) -> Reactor: from armi.reactor import blueprints runLog.header("=========== Constructing Reactor and Verifying Inputs ===========") - getPluginManagerOrFail().hook.beforeReactorConstruction(cs=cs) r = Reactor(cs.caseTitle, bp)