Skip to content

Commit

Permalink
Merge branch 'main' into framework_crumbs
Browse files Browse the repository at this point in the history
  • Loading branch information
john-science committed Nov 28, 2023
2 parents 8b2c332 + f2909b5 commit 8f655d7
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 45 deletions.
42 changes: 36 additions & 6 deletions armi/physics/neutronics/crossSectionGroupManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ class AverageBlockCollection(BlockCollection):
Averages number densities, fission product yields, and fission gas
removal fractions.
.. impl:: Create representative blocks using volume-weighted averaging.
:id: I_ARMI_XSGM_CREATE_REPR_BLOCKS0
:implements: R_ARMI_XSGM_CREATE_REPR_BLOCKS
"""

def _makeRepresentativeBlock(self):
Expand Down Expand Up @@ -474,9 +478,7 @@ def getBlockNuclideTemperatureAvgTerms(block, allNucNames):
"""

def getNumberDensitiesWithTrace(component, allNucNames):
"""
Needed to make sure temperature of 0-density nuclides in fuel get fuel temperature
"""
"""Needed to make sure temperature of 0-density nuclides in fuel get fuel temperature."""
return [
component.p.numberDensities[nucName] or TRACE_NUMBER_DENSITY
if nucName in component.p.numberDensities
Expand Down Expand Up @@ -506,6 +508,10 @@ class CylindricalComponentsAverageBlockCollection(BlockCollection):
Creates a representative block for the purpose of cross section generation with a one-dimensional
cylindrical model.
.. impl:: Create representative blocks using custom cylindrical averaging.
:id: I_ARMI_XSGM_CREATE_REPR_BLOCKS1
:implements: R_ARMI_XSGM_CREATE_REPR_BLOCKS
Notes
-----
When generating the representative block within this collection, the geometry is checked
Expand Down Expand Up @@ -832,6 +838,12 @@ def __init__(self, r, cs):
self._unrepresentedXSIDs = []

def interactBOL(self):
"""Called at the Beginning-of-Life of a run, before any cycles start.
.. impl:: The lattice physics interface and XSGM are connected at BOL.
:id: I_ARMI_XSGM_FREQ0
:implements: R_ARMI_XSGM_FREQ
"""
# now that all cs settings are loaded, apply defaults to compound XS settings
from armi.physics.neutronics.settings import CONF_XS_BLOCK_REPRESENTATION
from armi.physics.neutronics.settings import (
Expand All @@ -853,6 +865,10 @@ def interactBOC(self, cycle=None):
"""
Update representative blocks and block burnup groups.
.. impl:: The lattice physics interface and XSGM are connected at BOC.
:id: I_ARMI_XSGM_FREQ1
:implements: R_ARMI_XSGM_FREQ
Notes
-----
The block list each each block collection cannot be emptied since it is used to derive nuclide temperatures.
Expand All @@ -861,20 +877,29 @@ def interactBOC(self, cycle=None):
self.createRepresentativeBlocks()

def interactEOC(self, cycle=None):
"""
EOC interaction.
"""EOC interaction.
Clear out big dictionary of all blocks to avoid memory issues and out-of-date representers.
"""
self.clearRepresentativeBlocks()

def interactEveryNode(self, cycle=None, tn=None):
"""Interactino at every time now.
.. impl:: The lattice physics interface and XSGM are connected at every time node.
:id: I_ARMI_XSGM_FREQ2
:implements: R_ARMI_XSGM_FREQ
"""
if self._latticePhysicsFrequency >= LatticePhysicsFrequency.everyNode:
self.createRepresentativeBlocks()

def interactCoupled(self, iteration):
"""Update XS groups on each physics coupling iteration to get latest temperatures.
.. impl:: The lattice physics interface and XSGM are connected during coupling.
:id: I_ARMI_XSGM_FREQ3
:implements: R_ARMI_XSGM_FREQ
Notes
-----
Updating the XS on only the first (i.e., iteration == 0) timenode can be a reasonable approximation to
Expand Down Expand Up @@ -1052,7 +1077,12 @@ def _getPregeneratedFluxFileLocationData(self, xsID):
return (filePath, fileName)

def createRepresentativeBlocks(self):
"""Get a representative block from each cross section ID managed here."""
"""Get a representative block from each cross section ID managed here.
.. impl:: Create collections of blocks based on XS type and burn-up group.
:id: I_ARMI_XSGM_CREATE_XS_GROUPS
:implements: R_ARMI_XSGM_CREATE_XS_GROUPS
"""
representativeBlocks = {}
self.avgNucTemperatures = {}
self._unrepresentedXSIDs = []
Expand Down
85 changes: 58 additions & 27 deletions armi/physics/neutronics/tests/test_crossSectionManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ def setUp(self):
self.bc.extend(self.blockList)

def test_createRepresentativeBlock(self):

avgB = self.bc.createRepresentativeBlock()
self.assertAlmostEqual(avgB.p.percentBu, 50.0)

Expand Down Expand Up @@ -132,25 +131,24 @@ def setUp(self):
self.bc.averageByComponent = True

def test_performAverageByComponent(self):
"""
Check the averageByComponent attribute
"""
"""Check the averageByComponent attribute."""
self.bc._checkBlockSimilarity = MagicMock(return_value=True)
self.assertTrue(self.bc._performAverageByComponent())
self.bc.averageByComponent = False
self.assertFalse(self.bc._performAverageByComponent())

def test_checkBlockSimilarity(self):
"""
Check the block similarity test
"""
"""Check the block similarity test."""
self.assertTrue(self.bc._checkBlockSimilarity())
self.bc.append(test_blocks.loadTestBlock())
self.assertFalse(self.bc._checkBlockSimilarity())

def test_createRepresentativeBlock(self):
"""
Test creation of a representative block
"""Test creation of a representative block.
.. test:: Create representative blocks using a volume-weighted averaging.
:id: T_ARMI_XSGM_CREATE_REPR_BLOCKS0
:tests: R_ARMI_XSGM_CREATE_REPR_BLOCKS
"""
avgB = self.bc.createRepresentativeBlock()
self.assertNotIn(avgB, self.bc)
Expand All @@ -174,7 +172,6 @@ def test_createRepresentativeBlockDissimilar(self):
"""
Test creation of a representative block from a collection with dissimilar blocks
"""

uniqueBlock = test_blocks.loadTestBlock()
uniqueBlock.p.percentBu = 50.0
fpFactory = test_lumpedFissionProduct.getDummyLFPFile()
Expand Down Expand Up @@ -379,10 +376,10 @@ def setUp(self):
self.expectedAreas = [[1, 6, 1], [1, 2, 1, 4]]

def test_ComponentAverageRepBlock(self):
r"""
tests that the XS group manager calculates the expected component atom density
and component area correctly. Order of components is also checked since in
1D cases the order of the components matters.
"""Tests that the XS group manager calculates the expected component atom density
and component area correctly.
Order of components is also checked since in 1D cases the order of the components matters.
"""
xsgm = self.o.getInterface("xsGroups")

Expand Down Expand Up @@ -421,11 +418,11 @@ def test_ComponentAverageRepBlock(self):


class TestBlockCollectionComponentAverage1DCylinder(unittest.TestCase):
r"""tests for 1D cylinder XS gen cases."""
"""tests for 1D cylinder XS gen cases."""

def setUp(self):
r"""
First part of setup same as test_Cartesian.
"""First part of setup same as test_Cartesian.
Second part of setup builds lists/dictionaries of expected values to compare to.
has expected values for component isotopic atom density and component area.
"""
Expand Down Expand Up @@ -498,10 +495,14 @@ def setUp(self):
]

def test_ComponentAverage1DCylinder(self):
r"""
tests that the XS group manager calculates the expected component atom density
and component area correctly. Order of components is also checked since in
1D cases the order of the components matters.
"""Tests that the XS group manager calculates the expected component atom density
and component area correctly.
Order of components is also checked since in 1D cases the order of the components matters.
.. test:: Create representative blocks using custom cylindrical averaging.
:id: T_ARMI_XSGM_CREATE_REPR_BLOCKS1
:tests: R_ARMI_XSGM_CREATE_REPR_BLOCKS
"""
xsgm = self.o.getInterface("xsGroups")

Expand Down Expand Up @@ -546,7 +547,6 @@ def test_ComponentAverage1DCylinder(self):
)

def test_checkComponentConsistency(self):

xsgm = self.o.getInterface("xsGroups")
xsgm.interactBOL()
blockCollectionsByXsGroup = xsgm.makeCrossSectionGroups()
Expand Down Expand Up @@ -775,6 +775,12 @@ def test_getNextAvailableXsType(self):
self.assertEqual("D", xsType3)

def test_getRepresentativeBlocks(self):
"""Test that we can create the representative blocks for a reactor.
.. test:: Build representative blocks for a reactor.
:id: T_ARMI_XSGM_CREATE_XS_GROUPS
:tests: R_ARMI_XSGM_CREATE_XS_GROUPS
"""
_o, r = test_reactors.loadTestReactor(TEST_ROOT)
self.csm.r = r

Expand Down Expand Up @@ -844,22 +850,37 @@ def test_createRepresentativeBlocksUsingExistingBlocks(self):
self.assertEqual(origXSIDsFromNew["BA"], "AA")

def test_interactBOL(self):
"""Test `BOL` lattice physics update frequency."""
"""Test `BOL` lattice physics update frequency.
.. test:: The XSGM frequency depends on the LPI frequency at BOL.
:id: T_ARMI_XSGM_FREQ0
:tests: R_ARMI_XSGM_FREQ
"""
self.blockList[0].r.p.timeNode = 0
self.csm.cs[CONF_LATTICE_PHYSICS_FREQUENCY] = "BOL"
self.csm.interactBOL()
self.assertTrue(self.csm.representativeBlocks)

def test_interactBOC(self):
"""Test `BOC` lattice physics update frequency."""
"""Test `BOC` lattice physics update frequency.
.. test:: The XSGM frequency depends on the LPI frequency at BOC.
:id: T_ARMI_XSGM_FREQ1
:tests: R_ARMI_XSGM_FREQ
"""
self.blockList[0].r.p.timeNode = 0
self.csm.cs[CONF_LATTICE_PHYSICS_FREQUENCY] = "BOC"
self.csm.interactBOL()
self.csm.interactBOC()
self.assertTrue(self.csm.representativeBlocks)

def test_interactEveryNode(self):
"""Test `everyNode` lattice physics update frequency."""
"""Test `everyNode` lattice physics update frequency.
.. test:: The XSGM frequency depends on the LPI frequency at every time node.
:id: T_ARMI_XSGM_FREQ2
:tests: R_ARMI_XSGM_FREQ
"""
self.csm.cs[CONF_LATTICE_PHYSICS_FREQUENCY] = "BOC"
self.csm.interactBOL()
self.csm.interactEveryNode()
Expand All @@ -870,7 +891,12 @@ def test_interactEveryNode(self):
self.assertTrue(self.csm.representativeBlocks)

def test_interactFirstCoupledIteration(self):
"""Test `firstCoupledIteration` lattice physics update frequency."""
"""Test `firstCoupledIteration` lattice physics update frequency.
.. test:: The XSGM frequency depends on the LPI frequency during first coupled iteration.
:id: T_ARMI_XSGM_FREQ3
:tests: R_ARMI_XSGM_FREQ
"""
self.csm.cs[CONF_LATTICE_PHYSICS_FREQUENCY] = "everyNode"
self.csm.interactBOL()
self.csm.interactCoupled(iteration=0)
Expand All @@ -881,7 +907,12 @@ def test_interactFirstCoupledIteration(self):
self.assertTrue(self.csm.representativeBlocks)

def test_interactAllCoupled(self):
"""Test `all` lattice physics update frequency."""
"""Test `all` lattice physics update frequency.
.. test:: The XSGM frequency depends on the LPI frequency during coupling.
:id: T_ARMI_XSGM_FREQ4
:tests: R_ARMI_XSGM_FREQ
"""
self.csm.cs[CONF_LATTICE_PHYSICS_FREQUENCY] = "firstCoupledIteration"
self.csm.interactBOL()
self.csm.interactCoupled(iteration=1)
Expand Down
24 changes: 12 additions & 12 deletions armi/reactor/blockParameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ def xsTypeNum(self, value):

pb.defParam(
"fuelWorth",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Reactivity worth of fuel material per unit mass",
)

Expand Down Expand Up @@ -491,13 +491,13 @@ def xsTypeNum(self, value):

pb.defParam(
"coolantWorth",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Reactivity worth of coolant material per unit mass",
)

pb.defParam(
"cladWorth",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Reactivity worth of clad material per unit mass",
)

Expand Down Expand Up @@ -623,7 +623,7 @@ def xsTypeNum(self, value):
# FUEL COEFFICIENTS
pb.defParam(
"rxFuelDensityCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Fuel Density Coefficient",
)

Expand All @@ -641,20 +641,20 @@ def xsTypeNum(self, value):

pb.defParam(
"rxFuelTemperatureCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Fuel Temperature Coefficient",
)

pb.defParam(
"rxFuelVoidedTemperatureCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Fuel Voided-Coolant Temperature Coefficient",
)

# CLAD COEFFICIENTS
pb.defParam(
"rxCladDensityCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Clad Density Coefficient",
)

Expand All @@ -666,14 +666,14 @@ def xsTypeNum(self, value):

pb.defParam(
"rxCladTemperatureCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Clad Temperature Coefficient",
)

# STRUCTURE COEFFICIENTS
pb.defParam(
"rxStructureDensityCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Structure Density Coefficient",
)

Expand All @@ -685,20 +685,20 @@ def xsTypeNum(self, value):

pb.defParam(
"rxStructureTemperatureCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Structure Temperature Coefficient",
)

# COOLANT COEFFICIENTS
pb.defParam(
"rxCoolantDensityCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Coolant Density Coefficient",
)

pb.defParam(
"rxCoolantTemperatureCoeffPerMass",
units=f"{units.REACTIVITY}/{units.KG})",
units=f"{units.REACTIVITY}/{units.KG}",
description="Coolant Temperature Coefficient",
)

Expand Down
1 change: 1 addition & 0 deletions doc/tutorials/armi-example-app
Submodule armi-example-app added at 60becb

0 comments on commit 8f655d7

Please sign in to comment.