# 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."""
from collections import OrderedDict
import unittest
from armi.physics.neutronics.latticePhysics.latticePhysicsInterface import (
LatticePhysicsInterface,
)
from armi import settings
from armi.operators.operator import Operator
from armi.physics.neutronics.crossSectionGroupManager import CrossSectionGroupManager
from armi.physics.neutronics.settings import CONF_GEN_XS
from armi.reactor.reactors import Reactor, Core
from armi.reactor.tests.test_blocks import buildSimpleFuelBlock
from armi.tests import mockRunLogs
from armi.reactor.assemblies import (
HexAssembly,
grids,
)
from armi.nuclearDataIO.cccc import isotxs
from armi.physics.neutronics import LatticePhysicsFrequency
from armi.tests import ISOAA_PATH
# 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.axialUnitGrid(1)
cls.assembly.spatialGrid.armiObject = cls.assembly
cls.assembly.add(buildSimpleFuelBlock())
# cls.o.r.core.add(assembly)
# 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_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 by the BOC
interaction, so this test does not have a good means of verifying the
correct function, so we use 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 by the BOC interaction, so this test does not have a
good means of verifying the correct function,
so we use 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_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]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()