Skip to content

Commit

Permalink
Enable Users To Explicitly Specify Target Component for Axial Expansi…
Browse files Browse the repository at this point in the history
…on (#777)

In some cases, the standard methodology to infer a target component for the axial expansion changer may not easily enable specifically what is needed. This update adds a new setting to enable users to explicitly specify the target component for axial expansion on a block.

- Class method name change from specifyTargetComponent to determineTargetComponent
- Modifies runLog.debug statement to specify whether the target component was set or inferred.
- Has a check during block construction to determine if the specified axial expansion target component is valid.
- Unit test added to support new additions.
  • Loading branch information
albeanth authored Aug 3, 2022
1 parent 87f0ff1 commit e336bad
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 22 deletions.
15 changes: 15 additions & 0 deletions armi/reactor/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def __init__(self, name: str, height: float = 1.0):

self.points = []
self.macros = None
self.axialExpTargetComponent = None

# flag to indicated when DerivedShape children must be updated.
self.derivedMustUpdate = False
Expand Down Expand Up @@ -1529,6 +1530,20 @@ def rotate(self, deg):
"""
raise NotImplementedError

def setAxialExpTargetComp(self, targetComponent):
"""sets the targetComponent for the axial expansion changer
Parameter
---------
targetComponent: :py:class:`Component <armi.reactor.components.component.Component>` object
component specified to be target component for axial expansion changer
See Also
--------
armi.reactor.converters.axialExpansionChanger.py::ExpansionData::_setTargetComponents
"""
self.axialExpTargetComponent = targetComponent

def getPinCoordinates(self):
"""
Compute the local centroid coordinates of any pins in this block.
Expand Down
17 changes: 17 additions & 0 deletions armi/reactor/blueprints/blockBlueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class BlockBlueprint(yamlize.KeyedList):
name = yamlize.Attribute(key="name", type=str)
gridName = yamlize.Attribute(key="grid name", type=str, default=None)
flags = yamlize.Attribute(type=str, default=None)
axialExpTargetComponent = yamlize.Attribute(
key="axial expansion target component", type=str, default=None
)
_geomOptions = _configureGeomOptions()

def _getBlockClass(self, outerComponent):
Expand Down Expand Up @@ -168,6 +171,20 @@ def construct(
flags = Flags.fromString(self.flags)

b.setType(self.name, flags)

if self.axialExpTargetComponent is not None:
try:
b.setAxialExpTargetComp(components[self.axialExpTargetComponent])
except KeyError as noMatchingComponent:
raise RuntimeError(
"Block {0} --> axial expansion target component {1} specified in the blueprints does not "
"match any component names. Revise axial expansion target component in blueprints "
"to match the name of a component and retry.".format(
b,
self.axialExpTargetComponent,
)
) from noMatchingComponent

for c in components.values():
b.add(c)
b.p.nPins = b.getNumPins()
Expand Down
33 changes: 24 additions & 9 deletions armi/reactor/converters/axialExpansionChanger.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,18 @@ def axiallyExpandAssembly(self, thermal: bool = False):
c.ztop = c.zbottom + c.height
# redistribute block boundaries if on the target component
if self.expansionData.isTargetComponent(c):
runLog.debug(
" Component {0} is target component".format(c)
)
if b.axialExpTargetComponent is None:
runLog.debug(
" Component {0} is target component (inferred)".format(
c
)
)
else:
runLog.debug(
" Component {0} is target component (blueprints defined)".format(
c
)
)
b.p.ztop = c.ztop

# see also b.setHeight()
Expand Down Expand Up @@ -620,19 +629,25 @@ def getExpansionFactor(self, c):
def _setTargetComponents(self, setFuel):
"""sets target component for each block
- To-Do: allow users to specify target component for a block in settings
Parameters
----------
setFuel : bool
boolean to determine if fuel block should have its target component set. Useful for when
target components should be determined on the fly.
"""
for b in self._a:
if b.hasFlags(Flags.PLENUM) or b.hasFlags(Flags.ACLP):
self.specifyTargetComponent(b, Flags.CLAD)
if b.axialExpTargetComponent is not None:
self._componentDeterminesBlockHeight[b.axialExpTargetComponent] = True
elif b.hasFlags(Flags.PLENUM) or b.hasFlags(Flags.ACLP):
self.determineTargetComponent(b, Flags.CLAD)
elif b.hasFlags(Flags.DUMMY):
self.specifyTargetComponent(b, Flags.COOLANT)
self.determineTargetComponent(b, Flags.COOLANT)
elif setFuel and b.hasFlags(Flags.FUEL):
self._isFuelLocked(b)
else:
self.specifyTargetComponent(b)
self.determineTargetComponent(b)

def specifyTargetComponent(self, b, flagOfInterest=None):
def determineTargetComponent(self, b, flagOfInterest=None):
"""appends target component to self._componentDeterminesBlockHeight
Parameters
Expand Down
53 changes: 41 additions & 12 deletions armi/reactor/converters/tests/test_axialExpansionChanger.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ def test_AssemblyAxialExpansionException(self):
the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

def test_specifyTargetComponentRuntimeErrorFirst(self):
def test_determineTargetComponentRuntimeErrorFirst(self):
# build block for testing
b = HexBlock("test", height=10.0)
fuelDims = {"Tinput": 25.0, "Thot": 25.0, "od": 0.76, "id": 0.00, "mult": 127.0}
Expand All @@ -579,12 +579,12 @@ def test_specifyTargetComponentRuntimeErrorFirst(self):
b.getVolumeFractions()
# do test
with self.assertRaises(RuntimeError) as cm:
self.obj.expansionData.specifyTargetComponent(b)
self.obj.expansionData.determineTargetComponent(b)

the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

def test_specifyTargetComponentRuntimeErrorSecond(self):
def test_determineTargetComponentRuntimeErrorSecond(self):
# build block for testing
b = HexBlock("test", height=10.0)
fuelDims = {"Tinput": 25.0, "Thot": 25.0, "od": 0.76, "id": 0.00, "mult": 127.0}
Expand All @@ -597,7 +597,7 @@ def test_specifyTargetComponentRuntimeErrorSecond(self):
b.getVolumeFractions()
# do test
with self.assertRaises(RuntimeError) as cm:
self.obj.expansionData.specifyTargetComponent(b)
self.obj.expansionData.determineTargetComponent(b)

the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)
Expand Down Expand Up @@ -635,8 +635,8 @@ def test_isFuelLocked(self):
self.assertEqual(the_exception.error_code, 3)


class TestSpecifyTargetComponent(unittest.TestCase):
"""verify specifyTargetComponent method is properly updating _componentDeterminesBlockHeight"""
class TestDetermineTargetComponent(unittest.TestCase):
"""verify determineTargetComponent method is properly updating _componentDeterminesBlockHeight"""

def setUp(self):
self.obj = AxialExpansionChanger()
Expand All @@ -645,7 +645,7 @@ def setUp(self):
# need an empty dictionary because we want to test for the added component only
self.obj.expansionData._componentDeterminesBlockHeight = {}

def test_specifyTargetComponent(self):
def test_determineTargetComponent(self):
# build a test block
b = HexBlock("fuel", height=10.0)
fuelDims = {"Tinput": 25.0, "Thot": 25.0, "od": 0.76, "id": 0.00, "mult": 127.0}
Expand All @@ -655,15 +655,15 @@ def test_specifyTargetComponent(self):
b.add(fuel)
b.add(clad)
# call method, and check that target component is correct
self.obj.expansionData.specifyTargetComponent(b)
self.obj.expansionData.determineTargetComponent(b)
self.assertTrue(
self.obj.expansionData.isTargetComponent(fuel),
msg="specifyTargetComponent failed to recognize intended component: {}".format(
msg="determineTargetComponent failed to recognize intended component: {}".format(
fuel
),
)

def test_specifyTargetComponentBlockWithMultipleFlags(self):
def test_determineTargetComponentBlockWithMultipleFlags(self):
# build a block that has two flags as well as a component matching each
# flag
b = HexBlock("fuel poison", height=10.0)
Expand All @@ -674,14 +674,43 @@ def test_specifyTargetComponentBlockWithMultipleFlags(self):
b.add(fuel)
b.add(poison)
# call method, and check that target component is correct
self.obj.expansionData.specifyTargetComponent(b)
self.obj.expansionData.determineTargetComponent(b)
self.assertTrue(
self.obj.expansionData.isTargetComponent(fuel),
msg="specifyTargetComponent failed to recognize intended component: {}".format(
msg="determineTargetComponent failed to recognize intended component: {}".format(
fuel
),
)

def test_specifyTargetComponet_BlueprintSpecifed(self):
b = HexBlock("SodiumBlock", height=10.0)
sodiumDims = {"Tinput": 25.0, "Thot": 25.0, "op": 17, "ip": 0.0, "mult": 1.0}
dummy = Hexagon("coolant", "Sodium", **sodiumDims)
b.add(dummy)
b.getVolumeFractions()
b.setType("SodiumBlock")

# check for no target component found
with self.assertRaises(RuntimeError) as cm:
self.obj.expansionData.determineTargetComponent(b)
the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)

b.setAxialExpTargetComp(dummy)
self.assertEqual(
b.axialExpTargetComponent,
dummy,
)

self.obj.expansionData._componentDeterminesBlockHeight[
b.axialExpTargetComponent
] = True
self.assertTrue(
self.obj.expansionData._componentDeterminesBlockHeight[
b.axialExpTargetComponent
]
)


class TestInputHeightsConsideredHot(unittest.TestCase):
"""verify thermal expansion for process loading of core"""
Expand Down
4 changes: 3 additions & 1 deletion armi/tests/detailedAxialExpansion/refSmallReactorBase.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ blocks:
mult: 1.0
op: 16.75

dummy : &block_dummy
SodiumBlock : &block_dummy
flags: dummy
coolant:
shape: Hexagon
material: Sodium
Expand All @@ -51,6 +52,7 @@ blocks:
ip: 0.0
mult: 1.0
op: 16.75
axial expansion target component: coolant

## ------------------------------------------------------------------------------------
## fuel blocks
Expand Down
1 change: 1 addition & 0 deletions doc/release/0.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ What's new in ARMI
#. Made the min/max temperatures of ``Material`` curves discoverable.
#. Introduction of axial expansion changer to enable component-level axial expansion of assemblies.
#. Add setting ``inputHeightsConsideredHot`` to enable thermal expansion of assemblies at BOL.
#. Add blueprints setting, ``axial expansion target component``, to enable users to manually set a "target component" for axial expansion.
#. TBD

Bug fixes
Expand Down

0 comments on commit e336bad

Please sign in to comment.