Repository: terrapower/armi
Pull request #1941 (2024-10-09 20:08:19)

Moving C5G7 into its own test dir
## What is the change?

I moved the test C5G7 benchmark reactor into it's own directory.

## Why is the change being made?

This is progress to do this for all 6 of the test reactors in ARMI: #1867

---

## Checklist

- [x] This PR has only [one purpose or idea](https://terrapower.github.io/armi/developer/tooling.html#one-idea-one-pr).
- [x] [Tests](https://terrapower.github.io/armi/developer/tooling.html#test-it) have been added/updated to verify any new/changed code.

<!-- Check the code quality -->

- [x] The code style follows [good practices](https://terrapower.github.io/armi/developer/standards_and_practices.html).
- [x] The commit message(s) follow [good practices](https://terrapower.github.io/armi/developer/tooling.html).

<!-- Check the project-level cruft -->

- [x] The [release notes](https://terrapower.github.io/armi/developer/tooling.html#add-release-notes) have been updated if necessary.
- [x] The [documentation](https://terrapower.github.io/armi/developer/tooling.html#document-it) is still up-to-date in the `doc` folder.
- [x] The dependencies are still up-to-date in `pyproject.toml`.


Patch:
diff --git a/armi/physics/neutronics/parameters.py b/armi/physics/neutronics/parameters.py
index ef61fd68..78268b8b 100644
--- a/armi/physics/neutronics/parameters.py
+++ b/armi/physics/neutronics/parameters.py
@@ -163,7 +163,7 @@ def _getNeutronicsBlockParams():
             "pinMgFluxes",
             units=f"n/{units.CM}^2/{units.SECONDS}",
             description="""
-            The block-level pin multigroup fluxes. pinMgFluxes[g][i] represents the flux in group g
+            The block-level pin multigroup fluxes. pinMgFluxes[i, g] represents the flux in group g
             for pin i. Flux units are the standard n/cm^2/s. The "ARMI pin ordering" is used, which
             is counter-clockwise from 3 o'clock.
             """,
@@ -175,7 +175,7 @@ def _getNeutronicsBlockParams():
         pb.defParam(
             "pinMgFluxesAdj",
             units=units.UNITLESS,
-            description="should be a blank 3-D array, but re-defined later (ng x nPins x nAxialSegments)",
+            description="should be a blank 3-D array, but re-defined later (nPins x ng x nAxialSegments)",
             categories=[parameters.Category.pinQuantities],
             saveToDB=False,
             default=None,
@@ -184,7 +184,7 @@ def _getNeutronicsBlockParams():
         pb.defParam(
             "pinMgFluxesGamma",
             units=f"#/{units.CM}^2/{units.SECONDS}",
-            description="should be a blank 3-D array, but re-defined later (ng x nPins x nAxialSegments)",
+            description="should be a blank 3-D array, but re-defined later (nPins x ng x nAxialSegments)",
             categories=[parameters.Category.pinQuantities, parameters.Category.gamma],
             saveToDB=False,
             default=None,
diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py
index 7d9f4cb5..918108a5 100644
--- a/armi/reactor/blocks.py
+++ b/armi/reactor/blocks.py
@@ -351,13 +351,10 @@ class Block(composites.Composite):
         """
         Store the pin-detailed multi-group neutron flux.
 
-        The [g][i] indexing is transposed to be a list of lists, one for each pin. This makes it
-        simple to do depletion for each pin, etc.
-
         Parameters
         ----------
-        fluxes : 2-D list of floats
-            The block-level pin multigroup fluxes. fluxes[g][i] represents the flux in group g for
+        fluxes : np.ndarray
+            The block-level pin multigroup fluxes. fluxes[i, g] represents the flux in group g for
             pin i. Flux units are the standard n/cm^2/s.
             The "ARMI pin ordering" is used, which is counter-clockwise from 3 o'clock.
         adjoint : bool, optional
@@ -367,28 +364,16 @@ class Block(composites.Composite):
 
         Outputs
         -------
-        self.p.pinMgFluxes : 2-D array of floats
-            The block-level pin multigroup fluxes. pinMgFluxes[g][i] represents the flux in group g
+        self.p.pinMgFluxes : np.ndarray
+            The block-level pin multigroup fluxes. pinMgFluxes[i, g] represents the flux in group g
             for pin i. Flux units are the standard n/cm^2/s.
             The "ARMI pin ordering" is used, which is counter-clockwise from 3 o'clock.
         """
-        pinFluxes = []
-
-        G, nPins = fluxes.shape
-
-        for pinNum in range(1, nPins + 1):
-            thisPinFlux = []
-
-            if self.hasFlags(Flags.FUEL):
-                pinLoc = self.p.pinLocation[pinNum - 1]
-            else:
-                pinLoc = pinNum
-
-            for g in range(G):
-                thisPinFlux.append(fluxes[g][pinLoc - 1])
-            pinFluxes.append(thisPinFlux)
+        if self.hasFlags(Flags.FUEL):
+            pinFluxes = fluxes[(np.array(self.p.pinLocation) - 1)]
+        else:
+            pinFluxes = fluxes[:]
 
-        pinFluxes = np.array(pinFluxes)
         if gamma:
             if adjoint:
                 raise ValueError("Adjoint gamma flux is currently unsupported.")
diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst
index 73dd3640..e427faf9 100644
--- a/doc/release/0.4.rst
+++ b/doc/release/0.4.rst
@@ -33,6 +33,7 @@ API Changes
 #. Allowing for unknown Flags when opening a DB. (`PR#1844 <https://github.com/terrapower/armi/pull/1835>`_)
 #. Removing ``assemblyLists.py`` and the ``AssemblyList`` class. (`PR#1891 <https://github.com/terrapower/armi/pull/1891>`_)
 #. Removing ``Assembly.rotatePins`` and ``Block.rotatePins``. Prefer ``Assembly.rotate`` and ``Block.rotate``. (`PR#1846 <https://github.com/terrapower/armi/1846`_)
+#. Transposing ``pinMgFluxes`` parameters so that leading dimension is pin index (`PR#1937 <https://github.com/terrapower/armi/pull/1937>`)
 #. TBD
 
 Bug Fixes
diff --git a/doc/tutorials/walkthrough_lwr_inputs.rst b/doc/tutorials/walkthrough_lwr_inputs.rst
index 3afde179..5fdc61df 100644
--- a/doc/tutorials/walkthrough_lwr_inputs.rst
+++ b/doc/tutorials/walkthrough_lwr_inputs.rst
@@ -41,7 +41,7 @@ to specify their composition. The composition details below are documented in Ta
 `NEA/NSC/DOC(96)2 <https://www.oecd-nea.org/upload/docs/application/pdf/2020-01/nsc-doc96-02-rev2.pdf>`_.
 
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: start-custom-isotopics
     :end-before: end-custom-isotopics
@@ -64,7 +64,7 @@ position in the grid that has any of the specifiers in this list.
 You will see the `<<: *guide_tube` notation below. This means use the
 specifications of guide_tube, but make the modifications that apear below.
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-custom-isotopics
     :end-before: end-block-uo2
@@ -79,7 +79,7 @@ The next assembly is very similar. We define three separate fuel pins,
 each with different ``latticeIDs``, and then use YAML anchors to just
 copy the moderator, guide tube, and fission chamber from the previous assembly.
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-block-uo2
     :end-before: end-block-mox
@@ -88,7 +88,7 @@ The moderator block
 -------------------
 The moderator block for the radial and axial reflectors is very simple:
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-block-mox
     :end-before: end-block-mod
@@ -98,7 +98,7 @@ The 3-D Assembly definitions
 Now that the pins are defined, we stack them into assemblies, very similar
 to what we did in the SFR tutorial. There are three distinct assembly definitions.
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-block-mod
     :end-before: end-assemblies
@@ -111,7 +111,7 @@ they would be here alongside the core. We also anchor the core at the global
 coordinates (0,0,0). If we wanted the core at some other elevation, we could
 adjust that here.
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-assemblies
     :end-before: end-systems
@@ -124,7 +124,7 @@ from an XML file. In this tutorial, we define the grid directly with an
 textual ``lattice map`` input section. The core map is particularly simple; it
 only has 9 assemblies.
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-systems
     :end-before: end-grid-core
@@ -134,14 +134,14 @@ Recall that on the ``uo2`` block above we said that we want to apply the grid
 with the name ``UO2 grid``, and wanted to fill any ``U`` position with
 the ``fuel`` component defined up there. Here's where we define that grid.
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-grid-core
     :end-before: end-grid-UO2
 
 Similarly, we define the ``MOX grid`` as follows:
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-grid-UO2
     :end-before: end-grid-MOX
@@ -151,7 +151,7 @@ the assembly.
 
 Nuclide Flags
 -------------
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-blueprints.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-blueprints.yaml
     :language: yaml
     :start-after: end-grid-MOX
     :end-before: end-nucflags
@@ -167,7 +167,7 @@ Really, the only thing the settings file does in this case is point to the bluep
 file. As we turn this case into an actual run, we may add various cross section
 and neutrons options to evaluate the benchmark.
 
-.. literalinclude:: ../../armi/tests/tutorials/c5g7-settings.yaml
+.. literalinclude:: ../../armi/tests/c5g7/c5g7-settings.yaml
     :language: yaml
 
 Defining fuel management
@@ -228,5 +228,5 @@ This should show a simple representation of the block.
 
 Here are the full files used in this example:
 
-* :download:`Blueprints <../../armi/tests/tutorials/c5g7-blueprints.yaml>`
-* :download:`Settings <../../armi/tests/tutorials/c5g7-settings.yaml>`
+* :download:`Blueprints <../../armi/tests/c5g7/c5g7-blueprints.yaml>`
+* :download:`Settings <../../armi/tests/c5g7/c5g7-settings.yaml>`
diff --git a/pyproject.toml b/pyproject.toml
index 069d04d4..0490fe20 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -314,6 +314,9 @@ armi = [
     "tests/1DslabXSByCompTest.yaml",
     "tests/armiRun-SHUFFLES.txt",
     "tests/armiRun.yaml",
+    "tests/c5g7",
+    "tests/c5g7/c5g7-blueprints.yaml",
+    "tests/c5g7/c5g7-settings.yaml",
     "tests/COMPXS.ascii",
     "tests/detailedAxialExpansion/armiRun.yaml",
     "tests/detailedAxialExpansion/refSmallCoreGrid.yaml",


Test patch:
diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py
index d7b7f2a0..d9e1b51a 100644
--- a/armi/reactor/tests/test_blocks.py
+++ b/armi/reactor/tests/test_blocks.py
@@ -1715,13 +1715,29 @@ class Block_TestCase(unittest.TestCase):
 
         .. warning:: This will likely be pushed to the component level.
         """
-        fluxes = np.ones((33, 10))
+        fluxes = np.random.rand(10, 33)
+        p, g = np.random.randint(low=0, high=[10, 33])
+
+        # Test without pinLocation
+        self.block.pinLocation = None
         self.block.setPinMgFluxes(fluxes)
         self.block.setPinMgFluxes(fluxes * 2, adjoint=True)
         self.block.setPinMgFluxes(fluxes * 3, gamma=True)
-        self.assertEqual(self.block.p.pinMgFluxes[0][2], 1.0)
-        self.assertEqual(self.block.p.pinMgFluxesAdj[0][2], 2.0)
-        self.assertEqual(self.block.p.pinMgFluxesGamma[0][2], 3.0)
+        self.assertEqual(self.block.p.pinMgFluxes.shape, (10, 33))
+        self.assertEqual(self.block.p.pinMgFluxes[p, g], fluxes[p, g])
+        self.assertEqual(self.block.p.pinMgFluxesAdj.shape, (10, 33))
+        self.assertEqual(self.block.p.pinMgFluxesAdj[p, g], fluxes[p, g] * 2)
+        self.assertEqual(self.block.p.pinMgFluxesGamma.shape, (10, 33))
+        self.assertEqual(self.block.p.pinMgFluxesGamma[p, g], fluxes[p, g] * 3)
+
+        # Test with pinLocation
+        self.block.setType(self.block.getType(), Flags.FUEL)
+        self.block.p.pinLocation = np.random.choice(10, size=10, replace=False) + 1
+        self.block.setPinMgFluxes(fluxes)
+        self.assertEqual(self.block.p.pinMgFluxes.shape, (10, 33))
+        self.assertEqual(
+            self.block.p.pinMgFluxes[p, g], fluxes[self.block.p.pinLocation[p] - 1, g]
+        )
 
     def test_getComponentsInLinkedOrder(self):
         comps = self.block.getComponentsInLinkedOrder()
diff --git a/armi/tests/tutorials/c5g7-blueprints.yaml b/armi/tests/c5g7/c5g7-blueprints.yaml
similarity index 100%
rename from armi/tests/tutorials/c5g7-blueprints.yaml
rename to armi/tests/c5g7/c5g7-blueprints.yaml
diff --git a/armi/tests/tutorials/c5g7-settings.yaml b/armi/tests/c5g7/c5g7-settings.yaml
similarity index 100%
rename from armi/tests/tutorials/c5g7-settings.yaml
rename to armi/tests/c5g7/c5g7-settings.yaml
diff --git a/armi/tests/test_lwrInputs.py b/armi/tests/test_lwrInputs.py
index a7b4e631..6cc37b81 100644
--- a/armi/tests/test_lwrInputs.py
+++ b/armi/tests/test_lwrInputs.py
@@ -47,7 +47,7 @@ class C5G7ReactorTests(unittest.TestCase):
 
             # load the reactor
             _o, r = test_reactors.loadTestReactor(
-                os.path.join(TEST_ROOT, "tutorials"),
+                os.path.join(TEST_ROOT, "c5g7"),
                 inputFileName=TEST_INPUT_TITLE,
             )
 
diff --git a/armi/utils/tests/test_plotting.py b/armi/utils/tests/test_plotting.py
index 0fdb9e1c..2c3572cd 100644
--- a/armi/utils/tests/test_plotting.py
+++ b/armi/utils/tests/test_plotting.py
@@ -116,7 +116,7 @@ class TestPlotting(unittest.TestCase):
 
         with TemporaryDirectoryChanger():
             cs = settings.Settings(
-                os.path.join(TEST_ROOT, "tutorials", "c5g7-settings.yaml")
+                os.path.join(TEST_ROOT, "c5g7", "c5g7-settings.yaml")
             )
 
             blueprint = blueprints.loadFromCs(cs)