Skip to content

Commit

Permalink
Componentwise mat mods (#517)
Browse files Browse the repository at this point in the history
* Fix applyInputParams bug when values are zero

* Only check against user-provided power when the current node power is available

No new capability is added. The check of the power on the uniform mesh against the
user-provided power for the cycle is only changed so that it no longer occurs on
the BOC time node of each cycle, when the power data on the blocks is stale.

* Add the ability to specify material modifications on a component level

This adds the ability to specify material modifications on a component level
within a block. Using the `componentwise` attribute in the `material modifictions`
section of the blueprints, a given material modification may be specified to apply
to only a selection of components in the block.

Backwards compatibility is maintained in terms of the blueprints input file.
But an additional attribute `blockwise` has been added for the user to highlight
that a given material modification applies to all applicable components in the block.
This `blockwise` keyword may be used optionally and material modifications without
either the `componentwise` or `blockwise` keyword will be treated blockwise as
before.

* Remove the `_compileAssemblyMaterialInput` method and retool associated funtionalities

The `_compileAssemblyMaterialInput` method was duplicating data unnecessarily, so
it was gotten rid of. To get rid of it, some minor changes needed to be made, like
changing the material modification yamlize defaults and doing some dict manipulation
on the fly.

In addition, the `blockwise` yamlize attribute was removed. Now if the user wants
to specify a `blockwise` material modification, they do so using the old syntax.
This will be reflected in the docs in a future commit.
  • Loading branch information
keckler committed Jan 20, 2022
1 parent c6acb9d commit 33def90
Show file tree
Hide file tree
Showing 5 changed files with 495 additions and 20 deletions.
77 changes: 63 additions & 14 deletions armi/reactor/blueprints/assemblyBlueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,46 @@ def _configureAssemblyTypes():
return assemTypes


class Modifications(yamlize.Map):
"""
The names of material modifications and lists of the modification values for
each block in the assembly.
"""

key_type = yamlize.Typed(str)
value_type = yamlize.Sequence


class ByComponentModifications(yamlize.Map):
"""
The name of a component within the block and an associated Modifications
object.
"""

key_type = yamlize.Typed(str)
value_type = Modifications


class MaterialModifications(yamlize.Map):
"""
A yamlize map for reading and holding material modifications.
A user may specify material modifications directly
as keys/values on this class, in which case these material modifications will
be blanket applied to the entire block.
If the user wishes to specify material modifications specific to a component
within the block, they should use the `by component` attribute, specifying
the keys/values underneath the name of a specific component in the block.
"""

key_type = yamlize.Typed(str)
value_type = yamlize.Sequence
byComponent = yamlize.Attribute(
key="by component",
type=ByComponentModifications,
default=ByComponentModifications(),
)


class AssemblyBlueprint(yamlize.Object):
Expand All @@ -69,7 +106,9 @@ class AssemblyBlueprint(yamlize.Object):
key="azimuthal mesh points", type=int, default=None
)
materialModifications = yamlize.Attribute(
key="material modifications", type=MaterialModifications, default=None
key="material modifications",
type=MaterialModifications,
default=MaterialModifications(),
)
xsTypes = yamlize.Attribute(key="xs types", type=yamlize.StrList)
# note: yamlizable does not call an __init__ method, instead it uses __new__ and setattr
Expand Down Expand Up @@ -106,8 +145,8 @@ def construct(self, cs, blueprint):
Root blueprint object containing relevant modeling options.
"""
runLog.info("Constructing assembly `{}`".format(self.name))
self._checkParamConsistency()
a = self._constructAssembly(cs, blueprint)
self._checkParamConsistency(a)
a.calculateZCoords()
return a

Expand Down Expand Up @@ -155,15 +194,22 @@ def _constructAssembly(self, cs, blueprint):

def _createBlock(self, cs, blueprint, bDesign, axialIndex):
"""Create a block based on the block design and the axial index."""
materialInputs = self.materialModifications or {}
meshPoints = self.axialMeshPoints[axialIndex]
height = self.height[axialIndex]
xsType = self.xsTypes[axialIndex]
materialInput = {
modName: modList[axialIndex]
for modName, modList in materialInputs.items()
if modList[axialIndex] != ""
}

materialInput = {}

for key, mod in {
"byBlock": {**self.materialModifications},
**self.materialModifications.byComponent,
}.items():
materialInput[key] = {
modName: modList[axialIndex]
for modName, modList in mod.items()
if modList[axialIndex] != ""
}

b = bDesign.construct(
cs, blueprint, axialIndex, meshPoints, height, xsType, materialInput
)
Expand All @@ -172,24 +218,27 @@ def _createBlock(self, cs, blueprint, bDesign, axialIndex):
b.completeInitialLoading()
return b

def _checkParamConsistency(self, a):
def _checkParamConsistency(self):
"""Check that the number of block params specified is equal to the number of blocks specified."""
materialInputs = self.materialModifications or {}
paramsToCheck = {
"mesh points": self.axialMeshPoints,
"heights": self.height,
"xs types": self.xsTypes,
}
for modName, modList in materialInputs.items():
paramName = "material modifications for {}".format(modName)
paramsToCheck[paramName] = modList

for mod in [self.materialModifications] + list(
self.materialModifications.byComponent.values()
):
for modName, modList in mod.items():
paramName = "material modifications for {}".format(modName)
paramsToCheck[paramName] = modList

for paramName, blockVals in paramsToCheck.items():
if len(self.blocks) != len(blockVals):
raise ValueError(
"Assembly {} had {} blocks, but {} {}. These numbers should be equal. "
"Check input for errors.".format(
a, len(self.blocks), len(blockVals), paramName
self.name, len(self.blocks), len(blockVals), paramName
)
)

Expand Down
53 changes: 51 additions & 2 deletions armi/reactor/blueprints/blockBlueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ def construct(
String representing the xsType of this block.
materialInput : dict
dict containing material modification names and values
Double-layered dict.
Top layer groups the by-block material modifications under the `byBlock` key
and the by-component material modifications under the component's name.
The inner dict under each key contains material modification names and values.
"""
runLog.debug("Constructing block {}".format(self.name))
components = collections.OrderedDict()
Expand All @@ -106,8 +109,14 @@ def construct(
spatialGrid = gridDesign.construct()
else:
spatialGrid = None

self._checkByComponentMaterialInput(materialInput)

for componentDesign in self:
c = componentDesign.construct(blueprint, materialInput)
filteredMaterialInput = self._filterMaterialInput(
materialInput, componentDesign
)
c = componentDesign.construct(blueprint, filteredMaterialInput)
components[c.name] = c
if spatialGrid:
componentLocators = gridDesign.getMultiLocator(
Expand Down Expand Up @@ -170,6 +179,46 @@ def construct(
runLog.warning(str(e), single=True)
return b

def _checkByComponentMaterialInput(self, materialInput):
for component in materialInput:
if component != "byBlock":
if component not in [componentDesign.name for componentDesign in self]:
if materialInput[component]: # ensure it is not empty
raise ValueError(
f"The component '{component}' used to specify a by-component"
f" material modification is not in block '{self.name}'."
)

@staticmethod
def _filterMaterialInput(materialInput, componentDesign):
"""
Get the by-block material modifications and those specifically for this
component.
If a material modification is specified both by-block and by-component
for a given component, the by-component value will be used.
"""
filteredMaterialInput = {}

# first add the by-block modifications without question
if "byBlock" in materialInput:
for modName, modVal in materialInput["byBlock"].items():
filteredMaterialInput[modName] = modVal

# then get the by-component modifications as appropriate
for component, mod in materialInput.items():
if component == "byBlock":
pass # we already added these
else:
# these are by-component mods, first test if the component matches
# before adding. if component matches, add the modifications,
# overwriting any by-block modifications of the same type
if component == componentDesign.name:
for modName, modVal in mod.items():
filteredMaterialInput[modName] = modVal

return filteredMaterialInput

def _getGridDesign(self, blueprint):
"""
Get the appropriate grid design
Expand Down
Loading

0 comments on commit 33def90

Please sign in to comment.