Source code for armi.cases.inputModifiers.inputModifiers
# Copyright 2019 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.
"""Modifies inputs."""
[docs]class InputModifier:
"""
Object that modifies input definitions in some well-defined way.
.. impl:: A generic tool to modify user inputs on multiple cases.
:id: I_ARMI_CASE_MOD1
:implements: R_ARMI_CASE_MOD
This class serves as an abstract base class for modifying the inputs of
a case, typically case settings. Child classes must implement a
``__call__`` method accepting a
:py:class:`~armi.settings.caseSettings.Settings`,
:py:class:`~armi.reactor.blueprints.Blueprints`, and
:py:class:`~armi.reactor.systemLayoutInput.SystemLayoutInput` and return
the appropriately modified version of these objects. The class attribute
``FAIL_IF_AFTER`` should be a tuple defining what, if any, modifications
this should fail if performed after. For example, one should not adjust
the smear density (a function of Cladding ID) before adjusting the
Cladding ID. Some generic child classes are provided in this module, but
it is expected that design-specific modifiers are built individually.
"""
FAIL_IF_AFTER = ()
def __init__(self, independentVariable=None):
"""
Constuctor.
Parameters
----------
independentVariable : dict or None, optional
Name/value pairs to associate with the independent variable being modified
by this object. Will be analyzed and plotted against other modifiers with
the same name.
"""
if independentVariable is None:
independentVariable = {}
self.independentVariable = independentVariable
def __call__(self, cs, bp, geom):
"""Perform the desired modifications to input objects."""
raise NotImplementedError
[docs]class SamplingInputModifier(InputModifier):
"""
Object that modifies input definitions in some well-defined way.
(This class is abstract.)
Subclasses must implement a ``__call__`` method accepting a ``Settings``,
``Blueprints``, and ``SystemLayoutInput``.
This is a modified version of the InputModifier abstract class that imposes
structure for parameters in a design space that will be sampled by a
quasi-random sampling algorithm. These algorithms require input modifiers
to specify if the parameter is continuous or discrete and have the bounds
specified.
"""
def __init__(
self, name: str, paramType: str, bounds: list, independentVariable=None
):
"""Constructor for the Sampling input modifier.
Parameters
----------
name: str
Name of input modifier.
paramType : str
specify if parameter is 'continuous' or 'discrete'
bounds : list
If continuous, provide floating points [a, b] specifing the inclusive bounds.
If discrete, provide a list of potential values [a, b, c, ...]
independentVariable : [type], optional
Name/value pairs to associate with the independent variable being modified
by this object. Will be analyzed and plotted against other modifiers with
the same name, by default None
"""
InputModifier.__init__(self, independentVariable=independentVariable)
self.name = name
self.paramType = paramType
self.bounds = bounds
def __call__(self, cs, blueprints, geom):
"""Perform the desired modifications to input objects."""
raise NotImplementedError
[docs]class FullCoreModifier(InputModifier):
"""
Grow the SystemLayoutInput to from a symmetric core to a full core.
Notes
-----
Besides the Core, other grids may also be of interest for expansion, like
a grid that defines fuel management. However, the expansion of a fuel
management schedule to full core is less trivial than just expanding
the core itself. Thus, this modifier currently does not attempt
to update fuel management grids, but an expanded implementation could
do so in the future if needed. For now, users must expand fuel management
grids to full core themself.
"""
def __call__(self, cs, bp, geom):
"""Core might be on a geom object or a grid blueprint."""
if geom:
geom.growToFullCore()
else:
coreBp = bp.gridDesigns["core"]
coreBp.expandToFull()
return cs, bp, geom
[docs]class SettingsModifier(InputModifier):
"""Adjust setting to specified value."""
def __init__(self, settingName, value):
InputModifier.__init__(self, independentVariable={settingName: value})
self.settingName = settingName
self.value = value
def __call__(self, cs, bp, geom):
cs = cs.modified(newSettings={self.settingName: self.value})
return cs, bp, geom
[docs]class MultiSettingModifier(InputModifier):
"""
Adjust multiple settings to specified values.
Examples
--------
>>> inputModifiers.MultiSettingModifier(
... {CONF_NEUTRONICS_TYPE: "both", CONF_COARSE_MESH_REBALANCE: -1}
... )
"""
def __init__(self, settingVals: dict):
InputModifier.__init__(self, independentVariable=settingVals)
self.settings = settingVals
def __call__(self, cs, bp, geom):
newSettings = {}
for name, val in self.settings.items():
newSettings[name] = val
cs = cs.modified(newSettings=newSettings)
return cs, bp, geom
[docs]class BluePrintBlockModifier(InputModifier):
"""Adjust blueprint block->component->dimension to specified value."""
def __init__(self, block, component, dimension, value):
InputModifier.__init__(self, independentVariable={dimension: value})
self.block = block
self.component = component
self.dimension = dimension
self.value = value
def __call__(self, cs, bp, geom):
# parse block
for blockDesign in bp.blockDesigns:
if blockDesign.name == self.block:
# parse component
for componentDesign in blockDesign:
if componentDesign.name == self.component:
# set new value
setattr(componentDesign, self.dimension, self.value)
return cs, bp, geom
return cs, bp, geom