Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions armi/bookkeeping/historyTracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@
become available. For example::

def getHistoryParams(self):
return ['flux', 'percentBu']
return ["flux", "percentBu"]

When you'd like to access history information, you need to grab the history interface. The history
interfaces is present by default in your interface stack. To get it, just call::

history = self.getInterface('history')
history = self.getInterface("history")

Now you can do a few things, such as::

Expand All @@ -60,7 +60,7 @@ def getHistoryParams(self):
timeStepsAvailable = history.getTimeIndices()

# now go out and get some time-dependent block params:
fluxAtTimeStep3 = history.getBlockHistoryVal('B1003A', 'flux', 3)
fluxAtTimeStep3 = history.getBlockHistoryVal("B1003A", "flux", 3)

Specifying blocks and assemblies to track
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
29 changes: 12 additions & 17 deletions armi/cases/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,43 @@
"""
Case and CaseSuite objects for running and analyzing ARMI cases.

A ``Case`` is a collection of inputs that represents one particular run.
Cases have special knowledge about dependencies and can perform useful
operations like compare, clone, and run.
A ``Case`` is a collection of inputs that represents one particular run. Cases have special knowledge about dependencies
and can perform useful operations like compare, clone, and run.

A ``CaseSuite`` is a set of (often related) Cases. These are fundamental to
parameter sweeps and test suites.
A ``CaseSuite`` is a set of (often related) Cases. These are fundamental to parameter sweeps and test suites.

See Also
--------
armi.cli : Entry points that build Cases and/or CaseSuites and send them off to
do work

armi.cli : Entry points that build Cases and/or CaseSuites and send them off to do work
armi.operators : Operations that ARMI will perform on a reactor model.
Generally these are made by an individual Case.

Examples
--------
Create a Case and run it::

case = Case(settings.Settings('path-to-settings.yaml'))
case = Case(settings.Settings("path-to-settings.yaml"))
case.run()

# do something with output database

Create a case suite from existing files, and run the suite::

cs = settings.Settings() # default settings
suite = CaseSuite(settings.Settings()) # default settings
suite.discover('my-cases*.yaml', recursive=True)
cs = settings.Settings() # default settings
suite = CaseSuite(settings.Settings()) # default settings
suite.discover("my-cases*.yaml", recursive=True)
suite.run()

.. warning:: Suite running may not work yet if the cases have interdependencies.

Create a ``burnStep`` sensitivity study from some base CS::

baseCase = Case(settings.Settings('base-settings.yaml')) # default settings
suite = CaseSuite(baseCase.cs) # basically just sets armiLocation
baseCase = Case(settings.Settings("base-settings.yaml")) # default settings
suite = CaseSuite(baseCase.cs) # basically just sets armiLocation

for numSteps in range(3, 11):
with ForcedCreationDirectoryChanger('{}steps'.format(numSteps)):
case = baseCase.clone(title=baseCase.title + '-with{}steps'.format(numSteps),
settings={'burnSteps': numSteps})
with ForcedCreationDirectoryChanger("{}steps".format(numSteps)):
case = baseCase.clone(title=baseCase.title + f"-with{numSteps}steps", settings={"burnSteps": numSteps})
suite.add(case)

suite.writeInputs()
Expand Down
4 changes: 1 addition & 3 deletions armi/cases/inputModifiers/inputModifiers.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ class MultiSettingModifier(InputModifier):

Examples
--------
>>> inputModifiers.MultiSettingModifier(
... {CONF_NEUTRONICS_TYPE: "both", CONF_COARSE_MESH_REBALANCE: -1}
... )
>>> inputModifiers.MultiSettingModifier({CONF_NEUTRONICS_TYPE: "both", CONF_COARSE_MESH_REBALANCE: -1})

"""

Expand Down
20 changes: 9 additions & 11 deletions armi/cases/suiteBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ def addDegreeOfFreedom(self, inputModifiers):
For example::

class SettingModifier(InputModifier):

def __init__(self, settingName, value):
self.settingName = settingName
self.value = value
Expand All @@ -207,9 +206,10 @@ def __call__(self, cs, bp):
cs = cs.modified(newSettings={self.settingName: self.value})
return cs, bp


builder = FullFactorialSuiteBuilder(someCase)
builder.addDegreeOfFreedom(SettingModifier('settingName1', value) for value in (1,2))
builder.addDegreeOfFreedom(SettingModifier('settingName2', value) for value in (3,4,5))
builder.addDegreeOfFreedom(SettingModifier("settingName1", value) for value in (1, 2))
builder.addDegreeOfFreedom(SettingModifier("settingName2", value) for value in (3, 4, 5))

would result in 6 cases:

Expand Down Expand Up @@ -289,7 +289,6 @@ def addDegreeOfFreedom(self, inputModifiers):
For example::

class SettingModifier(InputModifier):

def __init__(self, settingName, value):
self.settingName = settingName
self.value = value
Expand All @@ -298,9 +297,10 @@ def __call__(self, cs, bp):
cs = cs.modified(newSettings={self.settignName: self.value})
return cs, bp


builder = SeparateEffectsSuiteBuilder(someCase)
builder.addDegreeOfFreedom(SettingModifier('settingName1', value) for value in (1,2))
builder.addDegreeOfFreedom(SettingModifier('settingName2', value) for value in (3,4,5))
builder.addDegreeOfFreedom(SettingModifier("settingName1", value) for value in (1, 2))
builder.addDegreeOfFreedom(SettingModifier("settingName2", value) for value in (3, 4, 5))

would result in 5 cases:

Expand Down Expand Up @@ -356,17 +356,15 @@ def addDegreeOfFreedom(self, inputModifiers):
For example::

class InputParameterModifier(SamplingInputModifier):

def __init__(
self,
name: str,
pararmType: str, # either 'continuous' or 'discrete'
bounds: Optional[Tuple, List]
pararmType: str, # either 'continuous' or 'discrete'
bounds: Optional[Tuple, List],
):
super().__init__(name, paramType, bounds)

def __call__(self, cs, bp):
...
def __call__(self, cs, bp): ...

If the modifier is discrete then bounds specifies a list of options the values can take. If
continuous, then bounds specifies a range of values.
Expand Down
79 changes: 33 additions & 46 deletions armi/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
# limitations under the License.

"""
Interfaces are objects of code that interact with ARMI. They read information off the state,
perform calculations (or run external codes), and then store the results back in the state.
Interfaces are objects of code that interact with ARMI. They read information off the state, perform calculations (or\
run external codes), and then store the results back in the state.

Learn all about interfaces in :doc:`/developer/guide`

Expand All @@ -39,8 +39,8 @@ class STACK_ORDER: # noqa: N801
"""
Constants that help determine the order of modules in the interface stack.

Each module defines an ``ORDER`` constant that specifies where in this order it should be placed
in the Interface Stack.
Each module defines an ``ORDER`` constant that specifies where in this order it should be placed in the Interface
Stack.

.. impl:: Define an ordered list of interfaces.
:id: I_ARMI_OPERATOR_INTERFACES0
Expand Down Expand Up @@ -155,8 +155,7 @@ def storePreviousIterationValue(self, val: _SUPPORTED_TYPES):

def isConverged(self, val: _SUPPORTED_TYPES) -> bool:
"""
Return boolean indicating if the convergence criteria between the current and previous
iteration values are met.
Return boolean indicating if the convergence criteria between the current and previous iteration values are met.

Parameters
----------
Expand All @@ -182,15 +181,15 @@ def isConverged(self, val: _SUPPORTED_TYPES) -> bool:
Raises
------
ValueError
If the previous iteration value has not been assigned. The
``storePreviousIterationValue`` method must be called first.
If the previous iteration value has not been assigned. The ``storePreviousIterationValue`` method must be
called first.
RuntimeError
Only support calculating norms for up to 2D arrays.
"""
if self._previousIterationValue is None:
raise ValueError(
f"Cannot check convergence of {self} with no previous iteration value set. "
"Set using `storePreviousIterationValue` first."
f"Cannot check convergence of {self} with no previous iteration value set. Set using "
"`storePreviousIterationValue` first."
)

previous = self._previousIterationValue
Expand Down Expand Up @@ -219,8 +218,8 @@ def isConverged(self, val: _SUPPORTED_TYPES) -> bool:
self._numIters += 1
if self._numIters == self.maxIters:
runLog.warning(
f"Maximum number of iterations for {self.parameter} reached without convergence!"
f"Prescribed convergence criteria is {self.tolerance}."
f"Maximum number of iterations for {self.parameter} reached without convergence! Prescribed "
f"convergence criteria is {self.tolerance}."
)
self._numIters = 0

Expand Down Expand Up @@ -358,7 +357,7 @@ def preDistributeState(self):

Examples
--------
>>> return {'neutronsPerFission',self.neutronsPerFission}
>>> return {"neutronsPerFission", self.neutronsPerFission}
"""
return {}

Expand Down Expand Up @@ -386,20 +385,17 @@ def attachReactor(self, o, r):
self.o = o

def detachReactor(self):
"""Delete the callbacks to reactor or operator. Useful when pickling, MPI sending, etc. to
save memory.
"""
"""Delete the callbacks to reactor or operator. Useful when pickling, MPI sending, etc. to save memory."""
self.o = None
self.r = None
self.cs = None

def duplicate(self):
"""
Duplicate this interface without duplicating some of the large attributes (like the entire
reactor).
Duplicate this interface without duplicating some of the large attributes (like the entire reactor).

Makes a copy of interface with detached reactor/operator/settings so that it can be attached
to an operator at a later point in time.
Makes a copy of interface with detached reactor/operator/settings so that it can be attached to an operator at a
later point in time.

Returns
-------
Expand Down Expand Up @@ -502,13 +498,11 @@ def interactDistributeState(self):
def interactRestart(self, startNode: Tuple[int, int], previousNode: Tuple[int, int]):
"""Perform any actions prior to simulating a restart.

Interfaces may want to restore some state that would have existed at the start of
``startNode`` prior to calling :meth:`interactBOL` for the desired start point.
The database interface will be used prior to any interfaces calling this method,
so you can assume the reactor state has been correctly loaded from the database
from the ``previousNode``. This helps ensure that interfaces restart at e.g.,
``(cycle, node)=(4, 3)`` would see the same data compared to the nominal simulation
without a restart.
Interfaces may want to restore some state that would have existed at the start of ``startNode`` prior to calling
:meth:`interactBOL` for the desired start point. The database interface will be used prior to any interfaces
calling this method, so you can assume the reactor state has been correctly loaded from the database from the
``previousNode``. This helps ensure that interfaces restart at e.g., ``(cycle, node)=(4, 3)`` would see the same
data compared to the nominal simulation without a restart.

Parameters
----------
Expand Down Expand Up @@ -688,13 +682,11 @@ class OutputReader:
Attributes
----------
success : bool
False by default, set to True if the run is considered
to have completed without error.
False by default, set to True if the run is considered to have completed without error.

Notes
-----
Should ideally not require r, eci, and fname arguments and would rather just have an
apply(reactor) method.
Should ideally not require r, eci, and fname arguments and would rather just have an apply(reactor) method.
"""

def __init__(self, r=None, externalCodeInterface=None, fName=None, cs=None):
Expand Down Expand Up @@ -723,10 +715,9 @@ def apply(self, reactor):
"""
Apply the output back to a reactor state.

This provides a generic interface for the output data of anything
to be applied to a reactor state. The application could involve
reading text or binary output or simply parameters to appropriate
values in some other data structure.
This provides a generic interface for the output data of anything to be applied to a reactor state. The
application could involve reading text or binary output or simply parameters to appropriate values in some other
data structure.
"""
raise NotImplementedError()

Expand All @@ -739,10 +730,9 @@ def _setTightCouplerByInterfaceFunction(interfaceClass, cs):
----------
interfaceClass : Interface
Interface class that a ``TightCoupler`` object will be added to.

cs : Settings
Case settings that are parsed to determine if tight coupling is enabled
globally and if both a target parameter and convergence criteria defined.
Case settings that are parsed to determine if tight coupling is enabled globally and if both a target parameter
and convergence criteria defined.
"""
# No tight coupling if there is no function for the Interface defined.
if interfaceClass.function is None:
Expand All @@ -762,12 +752,10 @@ def getActiveInterfaceInfo(cs):
"""
Return a list containing information for all of the Interface classes that are present.

This creates a list of tuples, each containing an Interface subclass and appropriate
kwargs for adding them to an Operator stack, given case settings. There should be
entries for all Interface classes that are returned from implementations of the
describeInterfaces() function in modules present in the passed list of packages. The
list is sorted by the ORDER specified by the module in which the specific Interfaces
are described.
This creates a list of tuples, each containing an Interface subclass and appropriate kwargs for adding them to an
Operator stack, given case settings. There should be entries for all Interface classes that are returned from
implementations of the describeInterfaces() function in modules present in the passed list of packages. The list is
sorted by the ORDER specified by the module in which the specific Interfaces are described.

Parameters
----------
Expand All @@ -794,8 +782,7 @@ class InterfaceInfo(NamedTuple):

Notes
-----
If kwargs is an empty dictionary, defaults from
``armi.operators.operator.Operator.addInterface`` will be applied.
If kwargs is an empty dictionary, defaults from ``armi.operators.operator.Operator.addInterface`` will be applied.

See Also
--------
Expand Down
10 changes: 5 additions & 5 deletions armi/nucDirectory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,16 @@
may be extended as needed by end-users as needs arise.

>>> r = Reactor("testReactor", bp)
>>> pu239 = r.nuclideBases.byName['PU239']
>>> pu239 = r.nuclideBases.byName["PU239"]
>>> pu239.z
94

Just like with elements, the item retrieved from the various dictionaries are the same object.

>>> tinFromName = r.nuclideBases.byName['SN112']
>>> tinFromLabel = r.nuclideBases.byLabel['SN112']
>>> tinFromMcc2Id = r.nuclideBases.byName['SN1125']
>>> tinFromMcc3Id = r.nuclideBases.byLabel['SN1127']
>>> tinFromName = r.nuclideBases.byName["SN112"]
>>> tinFromLabel = r.nuclideBases.byLabel["SN112"]
>>> tinFromMcc2Id = r.nuclideBases.byName["SN1125"]
>>> tinFromMcc3Id = r.nuclideBases.byLabel["SN1127"]
>>> tinFromName == tinFromLabel == tinFromMcc2Id == tinFromMcc3Id
True
>>> id(tinFromName) == id(tinFromLabel) == id(tinFromMcc2Id) == id(tinFromMcc3Id)
Expand Down
8 changes: 4 additions & 4 deletions armi/nucDirectory/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ def getName(self, z: int = None, symbol: str = None) -> str:
--------
>>> elements.getName(10)
'Neon'
>>> elements.getName(symbol='Ne')
>>> elements.getName(symbol="Ne")
'Neon'
"""
element = None
Expand All @@ -477,7 +477,7 @@ def getSymbol(self, z: int = None, name: str = None) -> str:
--------
>>> elements.getSymbol(10)
'Ne'
>>> elements.getSymbol(name='Neon')
>>> elements.getSymbol(name="Neon")
'Ne'

"""
Expand All @@ -502,9 +502,9 @@ def getElementZ(self, symbol: str = None, name: str = None) -> int:

Examples
--------
>>> elements.getZ('Zr')
>>> elements.getZ("Zr")
40
>>> elements.getZ(name='Zirconium')
>>> elements.getZ(name="Zirconium")
40

Notes
Expand Down
Loading
Loading