Source code for armi.physics.neutronics.latticePhysics.tests.test_latticeInterface

# Copyright 2021 TerraPower, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Test the Lattice Interface."""

import unittest
from collections import OrderedDict

from armi import settings
from armi.nuclearDataIO.cccc import isotxs
from armi.operators.operator import Operator
from armi.physics.neutronics import LatticePhysicsFrequency
from armi.physics.neutronics.crossSectionGroupManager import CrossSectionGroupManager
from armi.physics.neutronics.latticePhysics.latticePhysicsInterface import (
    LatticePhysicsInterface,
)
from armi.physics.neutronics.settings import CONF_GEN_XS, CONF_GLOBAL_FLUX_ACTIVE
from armi.reactor.assemblies import (
    HexAssembly,
    grids,
)
from armi.reactor.reactors import Core, Reactor
from armi.reactor.tests.test_blocks import buildSimpleFuelBlock
from armi.tests import ISOAA_PATH, mockRunLogs


# As an interface, LatticePhysicsInterface must be subclassed to be used
[docs] class LatticeInterfaceTester(LatticePhysicsInterface): def __init__(self, r, cs): self.name = "LatticeInterfaceTester" super().__init__(r, cs) def _getExecutablePath(self): return "/tmp/fake_path"
[docs] def readExistingXSLibraries(self, cycle, node): pass
[docs] class LatticeInterfaceTesterLibFalse(LatticeInterfaceTester): """Subclass setting _newLibraryShouldBeCreated = False.""" def _newLibraryShouldBeCreated(self, cycle, representativeBlockList, xsIDs): self.testVerification = True return False
[docs] class TestLatticePhysicsInterfaceBase(unittest.TestCase): @classmethod def setUpClass(cls): # create empty reactor core cls.o = Operator(settings.Settings()) cls.o.r = Reactor("testReactor", None) cls.o.r.core = Core("testCore") # add an assembly with a single block cls.assembly = HexAssembly("testAssembly") cls.assembly.spatialGrid = grids.AxialGrid.fromNCells(1) cls.assembly.spatialGrid.armiObject = cls.assembly cls.assembly.add(buildSimpleFuelBlock()) # init and add interfaces cls.xsGroupInterface = CrossSectionGroupManager(cls.o.r, cls.o.cs) cls.o.addInterface(cls.xsGroupInterface)
[docs] class TestLatticePhysicsInterface(TestLatticePhysicsInterfaceBase): """Test Lattice Physics Interface.""" @classmethod def setUpClass(cls): super().setUpClass() cls.latticeInterface = LatticeInterfaceTesterLibFalse(cls.o.r, cls.o.cs) cls.o.addInterface(cls.latticeInterface) def setUp(self): self.o.r.core.lib = "Nonsense" self.latticeInterface.testVerification = False
[docs] def test_includeGammaXS(self): """Test that we can correctly flip the switch to calculate gamma XS.""" # The default operator here turns off Gamma XS generation self.assertFalse(self.latticeInterface.includeGammaXS) self.assertEqual(self.o.cs[CONF_GLOBAL_FLUX_ACTIVE], "Neutron") # but we can create an operator that turns on Gamma XS generation cs = settings.Settings().modified(newSettings={CONF_GLOBAL_FLUX_ACTIVE: "Neutron and Gamma"}) newOperator = Operator(cs) newLatticeInterface = LatticeInterfaceTesterLibFalse(newOperator.r, cs) self.assertTrue(newLatticeInterface.includeGammaXS) self.assertEqual(cs[CONF_GLOBAL_FLUX_ACTIVE], "Neutron and Gamma")
[docs] def test_latticePhysicsInterface(self): """Super basic test of the LatticePhysicsInterface.""" self.assertEqual(self.latticeInterface._updateBlockNeutronVelocities, True) self.assertEqual(self.latticeInterface.executablePath, "/tmp/fake_path") self.assertEqual(self.latticeInterface.executableRoot, "/tmp") self.latticeInterface.updateXSLibrary(0) self.assertEqual(len(self.latticeInterface._oldXsIdsAndBurnup), 0)
[docs] def test_interactBOL(self): """ Test interactBOL() with different update frequencies. Notes ----- Unlike other interactions, self.o.r.core.lib is not set to None at BOC, so this test uses self.testVerification instead. """ self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.never self.latticeInterface.interactBOL() self.assertFalse(self.latticeInterface.testVerification) self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.everyNode self.latticeInterface.interactBOL() self.assertFalse(self.latticeInterface.testVerification) self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.BOL self.latticeInterface.interactBOL() self.assertTrue(self.latticeInterface.testVerification)
[docs] def test_interactBOC(self): """ Test interactBOC() with different update frequencies. Notes ----- Unlike other interactions, self.o.r.core.lib is not set to None at BOC, so this test uses self.testVerification instead. """ self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.BOL self.latticeInterface.interactBOC() self.assertFalse(self.latticeInterface.testVerification) self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.everyNode self.latticeInterface.interactBOC() self.assertFalse(self.latticeInterface.testVerification) self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.BOC self.latticeInterface.interactBOC() self.assertTrue(self.latticeInterface.testVerification)
[docs] def test_interactEveryNode(self): """Test interactEveryNode() with different update frequencies.""" self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.BOC self.latticeInterface.interactEveryNode() self.assertEqual(self.o.r.core.lib, "Nonsense") self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.everyNode self.latticeInterface.interactEveryNode() self.assertIsNone(self.o.r.core.lib)
[docs] def test_interactEveryNodeWhenCoupled(self): """ Test that the XS lib is not cleared when coupled iterations are turned on and XS will be generated during the coupled iterations. """ self.o.couplingIsActive = lambda: True self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.firstCoupledIteration self.latticeInterface.interactEveryNode() self.assertEqual(self.o.r.core.lib, "Nonsense") self.o.couplingIsActive = lambda: False self.latticeInterface.interactEveryNode() self.assertIsNone(self.o.r.core.lib)
[docs] def test_interactEveryNodeWhenCoupledButNot(self): """ Test that the XS lib is cleared when coupled iterations are turned on but the lattice physics frequency is not high enough. """ self.o.couplingIsActive = lambda: True self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.firstCoupledIteration self.latticeInterface.interactEveryNode() self.assertEqual(self.o.r.core.lib, "Nonsense") self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.everyNode self.latticeInterface.interactEveryNode() self.assertIsNone(self.o.r.core.lib)
[docs] def test_interactEveryNodeFirstCoupled(self): """Test interactEveryNode() with LatticePhysicsFrequency.firstCoupledIteration.""" self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.firstCoupledIteration self.latticeInterface.interactEveryNode() self.assertIsNone(self.o.r.core.lib)
[docs] def test_interactEveryNodeAll(self): """Test interactEveryNode() with LatticePhysicsFrequency.all.""" self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.all self.latticeInterface.interactEveryNode() self.assertIsNone(self.o.r.core.lib)
[docs] def test_interactFirstCoupledIteration(self): """Test interactCoupled() with different update frequencies on first iteration.""" self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.everyNode self.latticeInterface.interactCoupled(iteration=0) self.assertEqual(self.o.r.core.lib, "Nonsense") self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.firstCoupledIteration self.latticeInterface.interactCoupled(iteration=0) self.assertIsNone(self.o.r.core.lib)
[docs] def test_interactAll(self): """Test interactCoupled() with different update frequencies on non-first iteration.""" self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.firstCoupledIteration self.latticeInterface.interactCoupled(iteration=1) self.assertEqual(self.o.r.core.lib, "Nonsense") self.latticeInterface._latticePhysicsFrequency = LatticePhysicsFrequency.all self.latticeInterface.interactCoupled(iteration=1) self.assertIsNone(self.o.r.core.lib)
[docs] def test_getSuffix(self): self.assertEqual(self.latticeInterface._getSuffix(7), "")
[docs] class TestLatticePhysicsLibraryCreation(TestLatticePhysicsInterfaceBase): """Test variations of _newLibraryShouldBeCreated.""" @classmethod def setUpClass(cls): super().setUpClass() cls.latticeInterface = LatticeInterfaceTester(cls.o.r, cls.o.cs) cls.o.addInterface(cls.latticeInterface) cls.xsGroupInterface.representativeBlocks = OrderedDict({"AA": cls.assembly[0]}) cls.b, cls.xsIDs = cls.latticeInterface._getBlocksAndXsIds() def setUp(self): """Reset representativeBlocks and CONF_GEN_XS.""" self.xsGroupInterface.representativeBlocks = OrderedDict({"AA": self.assembly[0]}) self.assembly[0].p.xsType = "A" self.o.cs[CONF_GEN_XS] = "" self.o.r.core.lib = isotxs.readBinary(ISOAA_PATH)
[docs] def test_libCreation_NoGenXS(self): """No ISOTXS and xs gen not requested.""" self.o.r.core.lib = None with mockRunLogs.BufferLog() as mock: xsGen = self.latticeInterface._newLibraryShouldBeCreated(1, self.b, self.xsIDs) self.assertIn("Cross sections will not be generated on cycle 1.", mock.getStdout()) self.assertFalse(xsGen)
[docs] def test_libCreation_GenXS(self): """No ISOTXS and xs gen requested.""" self.o.cs[CONF_GEN_XS] = "Neutron" self.o.r.core.lib = None with mockRunLogs.BufferLog() as mock: xsGen = self.latticeInterface._newLibraryShouldBeCreated(1, self.b, self.xsIDs) self.assertIn( "Cross sections will be generated on cycle 1 for the following XS IDs: ['AA']", mock.getStdout(), ) self.assertTrue(xsGen)
[docs] def test_libCreation_NoGenXS_2(self): """ISOTXS present and has all of the necessary information.""" with mockRunLogs.BufferLog() as mock: xsGen = self.latticeInterface._newLibraryShouldBeCreated(1, self.b, self.xsIDs) self.assertIn( "The generation of XS will be skipped.", mock.getStdout(), ) self.assertFalse(xsGen)
[docs] def test_libCreation_GenXS_2(self): """ISOTXS present and does not have all of the necessary information.""" self.xsGroupInterface.representativeBlocks = OrderedDict({"BB": self.assembly[0]}) b, xsIDs = self._modifyXSType() with mockRunLogs.BufferLog() as mock: xsGen = self.latticeInterface._newLibraryShouldBeCreated(1, b, xsIDs) self.assertIn( "is not enabled, but will be run to generate these missing cross sections.", mock.getStdout(), ) self.assertTrue(xsGen)
[docs] def test_libCreation_GenXS_3(self): """ISOTXS present and does not have all of the necessary information.""" self.o.cs[CONF_GEN_XS] = "Neutron" b, xsIDs = self._modifyXSType() with mockRunLogs.BufferLog() as mock: xsGen = self.latticeInterface._newLibraryShouldBeCreated(1, b, xsIDs) self.assertIn("These will be generated on cycle ", mock.getStdout()) self.assertTrue(xsGen)
def _modifyXSType(self): self.xsGroupInterface.representativeBlocks = OrderedDict({"BB": self.assembly[0]}) self.assembly[0].p.xsType = "B" return self.latticeInterface._getBlocksAndXsIds()