Repository: terrapower/armi
Pull request #1828 (2024-08-21 00:27:12)

Update fluid volumes after prescribed axial expansion
## What is the change?

Clear the cached volume for fluid components in order for them to be updated post axial expansion. Ensures consistency with the parent block height and that total assembly fluid mass is conserved

## Why is the change being made?

<!-- MANDATORY: Explain why the change is necessary -->
<!-- Optional: Link to any related GitHub Issues -->

After prescribed axial expansion is applied to a block, the cache should be cleared from all components so that the component volume can be recalculated based on the new block height. It was only being done for solid components, which left fluid components in a state where their volume was not consistent with their parent block's height.

---

## Checklist

<!--
    You (the pull requester) should put an `x` in the boxes below you have completed.

    (If a checkbox doesn't apply to your PR, check it anyway.)
-->

- [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`.

albeanth: Converting this to draft until it's ready to be merged -- we have downstream testing that we need to do before this can be merged. Once said testing is done, we will crack this back open for merging! 

Patch:
diff --git a/armi/reactor/converters/axialExpansionChanger/axialExpansionChanger.py b/armi/reactor/converters/axialExpansionChanger/axialExpansionChanger.py
index 2800925b..390305be 100644
--- a/armi/reactor/converters/axialExpansionChanger/axialExpansionChanger.py
+++ b/armi/reactor/converters/axialExpansionChanger/axialExpansionChanger.py
@@ -19,8 +19,8 @@ from armi import runLog
 from armi.reactor.converters.axialExpansionChanger.assemblyAxialLinkage import (
     AssemblyAxialLinkage,
 )
-from armi.reactor.converters.axialExpansionChanger.expansionData import ExpansionData
 from armi.reactor.converters.axialExpansionChanger.expansionData import (
+    ExpansionData,
     getSolidComponents,
 )
 from armi.reactor.flags import Flags
@@ -359,8 +359,8 @@ class AxialExpansionChanger:
 
             _checkBlockHeight(b)
             # Call Component.clearCache to update the Component volume, and therefore the masses,
-            # of all solid components.
-            for c in getSolidComponents(b):
+            # of all components.
+            for c in b:
                 c.clearCache()
             # redo mesh -- functionality based on assembly.calculateZCoords()
             mesh.append(b.p.ztop)
diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst
index 700d90bd..2515ce43 100644
--- a/doc/release/0.4.rst
+++ b/doc/release/0.4.rst
@@ -35,6 +35,7 @@ Bug Fixes
 #. Fixed ``PermissionError`` when using ``syncDbAfterWrite``. (`PR#1857 <https://github.com/terrapower/armi/pull/1857>`_)
 #. Fixed ``MpiDirectoryChanger``. (`PR#1853 <https://github.com/terrapower/armi/pull/1853>`_)
 #. Changed data type of ``thKernel`` setting from ``bool`` to ``str`` in ``ThermalHydraulicsPlugin``. (`PR#1855 <https://github.com/terrapower/armi/pull/1855>`_)
+#. Update height of fluid components after axial expansion (`PR#1828 <https://github.com/terrapower/armi/pull/1828>`_)
 #. TBD
 
 Quality Work


Test patch:
diff --git a/armi/reactor/converters/tests/test_axialExpansionChanger.py b/armi/reactor/converters/tests/test_axialExpansionChanger.py
index 9906952e..bf69ac64 100644
--- a/armi/reactor/converters/tests/test_axialExpansionChanger.py
+++ b/armi/reactor/converters/tests/test_axialExpansionChanger.py
@@ -451,6 +451,10 @@ class TestConservation(AxialExpansionTestBase, unittest.TestCase):
         .. test:: Ensure the ACLP does not move during fuel-only expansion.
             :id: T_ARMI_AXIAL_EXP_PRESC1
             :tests: R_ARMI_AXIAL_EXP_PRESC
+
+        .. test:: Ensure the component volumes are correctly updated during prescribed expansion.
+            :id: T_ARMI_AXIAL_EXP_PRESC2
+            :tests: R_ARMI_AXIAL_EXP_PRESC
         """
         # build test assembly with ACLP
         assembly = HexAssembly("testAssemblyType")
@@ -473,6 +477,9 @@ class TestConservation(AxialExpansionTestBase, unittest.TestCase):
         aclpZTop = aclp.p.ztop
         aclpZBottom = aclp.p.zbottom
 
+        # get total assembly fluid mass pre-expansion
+        preExpAssemFluidMass = self._getTotalAssemblyFluidMass(assembly)
+
         # expand fuel
         # get fuel components
         cList = [c for b in assembly for c in b if c.hasFlags(Flags.FUEL)]
@@ -481,6 +488,9 @@ class TestConservation(AxialExpansionTestBase, unittest.TestCase):
         chngr = AxialExpansionChanger()
         chngr.performPrescribedAxialExpansion(assembly, cList, pList, setFuel=True)
 
+        # get total assembly fluid mass post-expansion
+        postExpAssemFluidMass = self._getTotalAssemblyFluidMass(assembly)
+
         # do assertion
         self.assertEqual(
             aclpZBottom,
@@ -493,6 +503,26 @@ class TestConservation(AxialExpansionTestBase, unittest.TestCase):
             msg="ACLP ztop has changed. It should not with fuel component only expansion!",
         )
 
+        # verify that the component volumes are correctly updated
+        for b in assembly:
+            for c in b:
+                self.assertAlmostEqual(
+                    c.getArea() * b.getHeight(),
+                    c.getVolume(),
+                    places=12,
+                )
+        # verify that the total assembly fluid mass is preserved through expansion
+        self.assertAlmostEqual(preExpAssemFluidMass, postExpAssemFluidMass, places=11)
+
+    @staticmethod
+    def _getTotalAssemblyFluidMass(assembly) -> float:
+        totalAssemblyFluidMass = 0.0
+        for b in assembly:
+            for c in b:
+                if isinstance(c.material, materials.material.Fluid):
+                    totalAssemblyFluidMass += c.getMass()
+        return totalAssemblyFluidMass
+
     def test_reset(self):
         self.obj.setAssembly(self.a)
         self.obj.reset()