Skip to content

Commit

Permalink
Global flux review (#1536)
Browse files Browse the repository at this point in the history
* respond to comments on the globalFluxInterface reqs

* add assert for nonuniform assemblies

* remove unused assignment
  • Loading branch information
bsculac authored Dec 8, 2023
1 parent 9f2b322 commit 4be1314
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 23 deletions.
2 changes: 1 addition & 1 deletion armi/physics/neutronics/globalFlux/globalFluxInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ def computeDpaRate(mgFlux, dpaXs):
r"""
Compute the DPA rate incurred by exposure of a certain flux spectrum.
.. impl:: Compute DPA and DPA rates.
.. impl:: Compute DPA rates.
:id: I_ARMI_FLUX_DPA
:implements: R_ARMI_FLUX_DPA
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
"""Tests for generic global flux interface."""
import unittest
from unittest.mock import patch

import numpy

Expand Down Expand Up @@ -107,18 +108,30 @@ class TestGlobalFluxOptions(unittest.TestCase):
"""Tests for GlobalFluxOptions."""

def test_readFromSettings(self):
"""Test reading global flux options.
"""Test reading global flux options from case settings.
.. test:: Tests GlobalFluxOptions.
:id: T_ARMI_FLUX_OPTIONS
:id: T_ARMI_FLUX_OPTIONS_FROM_CASE_SETTINGS
:tests: R_ARMI_FLUX_OPTIONS
:acceptance_criteria: This test is satisfied when it demonstrates
the ability of the globalFluxInterface to read options from a case
settings object.
"""
cs = settings.Settings()
opts = globalFluxInterface.GlobalFluxOptions("neutronics-run")
opts.fromUserSettings(cs)
self.assertFalse(opts.adjoint)

def test_readFromReactors(self):
"""Test reading global flux options from reactor objects.
.. test:: Tests GlobalFluxOptions.
:id: T_ARMI_FLUX_OPTIONS_FROM_REACTOR
:tests: R_ARMI_FLUX_OPTIONS
:acceptance_criteria: This test is satisfied when it demonstrates
the ability of the globalFluxInterface to read options from a
reactor object.
"""
reactor = MockReactor()
opts = globalFluxInterface.GlobalFluxOptions("neutronics-run")
opts.fromReactor(reactor)
Expand All @@ -145,7 +158,7 @@ def test_computeDpaRate(self):
"""
Compute DPA and DPA rates from multi-group neutron flux and cross sections.
.. test:: Compute DPA and DPA rates.
.. test:: Compute DPA rates.
:id: T_ARMI_FLUX_DPA
:tests: R_ARMI_FLUX_DPA
"""
Expand Down Expand Up @@ -189,7 +202,12 @@ def test_checkEnergyBalance(self):
cs = settings.Settings()
_o, r = test_reactors.loadTestReactor()
gfi = MockGlobalFluxInterface(r, cs)
gfi.checkEnergyBalance()
self.assertEqual(gfi.checkEnergyBalance(), None)

# Test when nameplate power doesn't equal sum of block power
r.core.p.power = 1e-10
with self.assertRaises(ValueError):
gfi.checkEnergyBalance()


class TestGlobalFluxInterfaceWithExecuters(unittest.TestCase):
Expand All @@ -204,20 +222,31 @@ def setUp(self):
self.r.core.p.keff = 1.0
self.gfi = MockGlobalFluxWithExecuters(self.r, self.cs)

def test_executerInteraction(self):
@patch(
"armi.physics.neutronics.globalFlux.globalFluxInterface.GlobalFluxExecuter._execute"
)
@patch(
"armi.physics.neutronics.globalFlux.globalFluxInterface.GlobalFluxExecuter._performGeometryTransformations"
)
def test_executerInteraction(self, mockGeometryTransform, mockExecute):
"""Run the global flux interface and executer though one time now.
.. test:: Run the global flux interface to prove the mesh in the reactor is suffience for the neutronics solver.
:id: T_ARMI_FLUX_GEOM_TRANSFORM1
.. test:: Run the global flux interface to check that the mesh
converter is called before the neutronics solver.
:id: T_ARMI_FLUX_GEOM_TRANSFORM_CHECK_CALL_ORDER
:tests: R_ARMI_FLUX_GEOM_TRANSFORM
:acceptance_criteria: The test is considered passing when the mesh
converter is verified to be called before the neutronics solver.
"""
gfi, r = self.gfi, self.r
call_order = []
mockGeometryTransform.side_effect = lambda *a, **kw: call_order.append(
mockGeometryTransform
)
mockExecute.side_effect = lambda *a, **kw: call_order.append(mockExecute)
gfi = self.gfi
gfi.interactBOC()
gfi.interactEveryNode(0, 0)
r.p.timeNode += 1
gfi.interactEveryNode(0, 1)
gfi.interactEOC()
self.assertAlmostEqual(r.core.p.rxSwing, (1.02 - 1.01) / 1.01 * 1e5)
self.assertEqual([mockGeometryTransform, mockExecute], call_order)

def test_calculateKeff(self):
self.assertEqual(self.gfi.calculateKeff(), 1.05) # set in mock
Expand Down Expand Up @@ -246,9 +275,21 @@ def test_getTightCouplingValue(self):
for a in self.r.core.getChildren():
for b in a:
b.p.power = 10.0
self.assertIsInstance(self.gfi.getTightCouplingValue(), list)
self.assertEqual(
self.gfi.getTightCouplingValue(),
self._getCouplingPowerDistributions(self.r.core),
)
self._setTightCouplingFalse()

@staticmethod
def _getCouplingPowerDistributions(core):
scaledPowers = []
for a in core:
assemblyPower = sum(b.p.power for b in a)
scaledPowers.append([b.p.power / assemblyPower for b in a])

return scaledPowers

def _setTightCouplingTrue(self):
self.cs["tightCoupling"] = True
self.gfi._setTightCouplingDefaults()
Expand All @@ -267,23 +308,26 @@ def setUpClass(cls):
cls.r.core.p.keff = 1.0
cls.gfi = MockGlobalFluxWithExecutersNonUniform(cls.r, cs)

def test_executerInteractionNonUniformAssems(self):
@patch("armi.reactor.converters.uniformMesh.converterFactory")
def test_executerInteractionNonUniformAssems(self, mockConverterFactory):
"""Run the global flux interface with non-uniform assemblies.
This will serve as a broad end-to-end test of the interface, and also
stress test the mesh issues with non-uniform assemblies.
.. test:: Run the global flux interface to prove the mesh in the reactor is suffience for the neutronics solver.
:id: T_ARMI_FLUX_GEOM_TRANSFORM0
.. test:: Run the global flux interface to show the geometry converter
is called when the nonuniform mesh option is used.
:id: T_ARMI_FLUX_GEOM_TRANSFORM_CHECK_CONVERTER_CALL
:tests: R_ARMI_FLUX_GEOM_TRANSFORM
:acceptance_criteria: The test is satisfied when the geometry
converter is shown to have been called when a nonuniform flag is
used.
"""
gfi, r = self.gfi, self.r
gfi = self.gfi
gfi.interactBOC()
gfi.interactEveryNode(0, 0)
r.p.timeNode += 1
gfi.interactEveryNode(0, 1)
gfi.interactEOC()
self.assertAlmostEqual(r.core.p.rxSwing, (1.02 - 1.01) / 1.01 * 1e5)
self.assertTrue(gfi.getExecuterOptions().hasNonUniformAssems)
mockConverterFactory.assert_called()

def test_calculateKeff(self):
self.assertEqual(self.gfi.calculateKeff(), 1.05) # set in mock
Expand Down Expand Up @@ -402,7 +446,7 @@ def test_calcReactionRates(self):
"""
b = test_blocks.loadTestBlock()
test_blocks.applyDummyData(b)
self.assertAlmostEqual(b.p.rateAbs, 0.0)
self.assertEqual(b.p.rateAbs, 0.0)
globalFluxInterface.calcReactionRates(b, 1.01, b.r.core.lib)
self.assertGreater(b.p.rateAbs, 0.0)
vfrac = b.getComponentAreaFrac(Flags.FUEL)
Expand Down

0 comments on commit 4be1314

Please sign in to comment.