armi.operators.operator module

The standard ARMI operator.

This builds and maintains the interface stack and loops through it for a certain number of cycles with a certain number of timenodes per cycle.

This is analogous to a real reactor operating over some period of time, often from initial startup, through the various cycles, and out to the end of plant life.

Implementation: ARMI controls the time flow of the reactor, by running a sequence of Interfaces at each time step. IMPL_EVOLVING_STATE_0 ../_images/arrow-right-circle.svg
has_dead_links: True
has_forbidden_dead_links: True
links outgoing: REQ_EVOLVING_STATE
class armi.operators.operator.Operator(cs)[source]

Bases: object

Orchestrates an ARMI run, building all the pieces, looping through the interfaces, and manipulating the reactor.

This Standard Operator loops over a user-input number of cycles, each with a user-input number of subcycles (called time nodes). It calls a series of interaction hooks on each of the Interface in the Interface Stack.

../_images/armi_general_flowchart.png

Figure 1. The computational flow of the interface hooks in a Standard Operator

Note

The Framework Architecture has some additional narrative on this topic.

Variables
  • ~Operator.cs (CaseSettings object) – Global settings that define the run.

  • ~Operator.cycleNames (list of str) – The name of each cycle. Cycles without a name are None.

  • ~Operator.stepLengths (list of list of float) – A two-tiered list, where primary indices correspond to cycle and secondary indices correspond to the length of each intra-cycle step (in days).

  • ~Operator.cycleLengths (list of float) – The duration of each individual cycle in a run (in days). This is the entire cycle, from startup to startup and includes outage time.

  • ~Operator.burnSteps (list of int) – The number of sub-cycles in each cycle.

  • ~Operator.availabilityFactors (list of float) – The fraction of time in a cycle that the plant is producing power. Note that capacity factor is always less than or equal to this, depending on the power fraction achieved during each cycle. Note that this is not a two-tiered list like stepLengths or powerFractions, because each cycle can have only one availabilityFactor.

  • ~Operator.powerFractions (list of list of float) – A two-tiered list, where primary indices correspond to cycles and secondary indices correspond to the fraction of full rated capacity that the plant achieves during that step of the cycle. Zero power fraction can indicate decay-only cycles.

  • ~Operator.interfaces (list) – The Interface objects that will operate upon the reactor

Constructor for operator.

Parameters

cs (CaseSettings object) – Global settings that define the run.

Raises

OSError – If unable to create the FAST_PATH directory.

inspector

alias of armi.operators.settingsValidation.Inspector

property burnSteps
property maxBurnSteps
property stepLengths
property cycleLengths
property powerFractions
property availabilityFactors
property cycleNames
property atEOL

Return whether we are approaching EOL.

For the standard operator, this will return true when the current cycle is the last cycle (cs[“nCycles”] - 1). Other operators may need to impose different logic.

initializeInterfaces(r)[source]

Attach the reactor to the operator and initialize all interfaces.

This does not occur in __init__ so that the ARMI operator can be initialized before a reactor is created, which is useful for summarizing the case information quickly.

Parameters

r (Reactor) – The Reactor object to attach to this Operator.

operate()[source]

Run the operation loop.

See also

mainOperator

run the operator loop on the primary MPI node (for parallel runs)

workerOperate

run the operator loop for the worker MPI nodes

printInterfaceSummary(interface, interactionName, statePointIndex, *args)[source]

Log which interaction point is about to be executed.

This looks better as multiple lines but it’s a lot easier to grep as one line. We leverage newlines instead of long banners to save disk space.

interactAllInit()[source]

Call interactInit on all interfaces in the stack after they are initialized.

interactAllBOL(excludedInterfaceNames=())[source]

Call interactBOL for all interfaces in the interface stack at beginning-of-life.

All enabled or bolForce interfaces will be called excluding interfaces with excludedInterfaceNames.

interactAllBOC(cycle)[source]

Interact at beginning of cycle of all enabled interfaces.

interactAllEveryNode(cycle, tn, excludedInterfaceNames=None)[source]

Call the interactEveryNode hook for all enabled interfaces.

All enabled interfaces will be called excluding interfaces with excludedInterfaceNames.

Parameters
  • cycle (int) – The cycle that is currently being run. Starts at 0

  • tn (int) – The time node that is currently being run (0 for BOC, etc.)

  • excludedInterfaceNames (list, optional) – Names of interface names that will not be interacted with.

interactAllEOC(cycle, excludedInterfaceNames=None)[source]

Interact end of cycle for all enabled interfaces.

interactAllEOL()[source]

Run interactEOL for all enabled interfaces.

Notes

If the interfaces are flagged to be reversed at EOL, they are separated from the main stack and appended at the end in reverse order. This allows, for example, an interface that must run first to also run last.

interactAllCoupled(coupledIteration)[source]

Interact for tight physics coupling over all enabled interfaces.

Tight coupling implies operator-split iterations between two or more physics solvers at the same solution point in time. For example, a flux solution might be computed, then a temperature solution, and then another flux solution based on updated temperatures (which updated densities, dimensions, and Doppler).

This is distinct from loose coupling, which would simply uses the temperature values from the previous timestep in the current flux solution. It’s also distinct from full coupling where all fields are solved simultaneously. ARMI supports tight and loose coupling.

interactAllError()[source]

Interact when an error is raised by any other interface. Provides a wrap-up option on the way to a crash.

createInterfaces()[source]

Dynamically discover all available interfaces and call their factories, potentially adding them to the stack.

An operator contains an ordered list of interfaces. These communicate between the core ARMI structure and auxiliary computational modules and/or external codes. At specified interaction points in a run, the list of interfaces is executed.

Each interface optionally defines interaction “hooks” for each of the interaction points. The normal interaction points are BOL, BOC, every node, EOC, and EOL. If an interface defines an interactBOL method, that will run at BOL, and so on.

The majority of ARMI capabilities lie within interfaces, and this architecture provides much of the flexibility of ARMI.

See also

addInterface

Adds a particular interface to the interface stack.

armi.interfaces.STACK_ORDER

A system to determine the required order of interfaces.

armi.interfaces.getActiveInterfaceInfo

Collects the interface classes from relevant packages.

addInterface(interface, index=None, reverseAtEOL=False, enabled=True, bolForce=False)[source]

Attach an interface to this operator.

Notes

Order matters.

Parameters
  • interface (Interface) – the interface to add

  • index (int, optional. Will insert the interface at this index rather than appending it to the end of) – the list

  • reverseAtEOL (bool, optional.) – The interactEOL hooks will run in reverse order if True. All interfaces with this flag will be run as a group after all other interfaces. This allows something to run first at BOL and last at EOL, etc.

  • enabled (bool, optional) – If enabled, will run at all hooks. If not, won’t run any (with possible exception at BOL, see bolForce). Whenever possible, Interfaces that are needed during runtime for some peripheral operation but not during the main loop should be instantiated by the part of the code that actually needs the interface.

  • bolForce (bool, optional) – If true, will run at BOL hook even if disabled. This is often a sign that the interface in question should be ephemerally instantiated on demand rather than added to the interface stack at all.

Raises

RuntimeError – If an interface of the same name or function is already attached to the Operator.

removeAllInterfaces()[source]

Removes all of the interfaces

removeInterface(interface=None, interfaceName=None)[source]

Remove a single interface from the interface stack.

Parameters
  • interface (Interface, optional) – An actual interface object to remove.

  • interfaceName (str, optional) – The name of the interface to remove.

Returns

success – True if the interface was removed False if it was not (because it wasn’t there to be removed)

Return type

boolean

getInterface(name=None, function=None)[source]

Returns a specific interface from the stack by its name or more generic function.

Parameters
  • name (str, optional) – Interface name

  • function (str) – Interface function (general, like ‘globalFlux’,’th’,etc.). This is useful when you need the ___ solver (e.g. globalFlux) but don’t care which particular one is active (e.g. SERPENT vs. DIF3D)

Raises

RuntimeError – If there are more than one interfaces of the given name or function.

interfaceIsActive(name)[source]

True if named interface exists and is active.

getInterfaces()[source]

Get list of interfaces in interface stack.

Notes

Returns a copy so you can manipulate the list in an interface, like dependencies.

reattach(r, cs=None)[source]

Add links to globally-shared objects to this operator and all interfaces.

Notes

Could be a good opportunity for weakrefs.

detach()[source]

Break links to globally-shared objects to this operator and all interfaces.

May be required prior to copying these objects over the network.

Notes

Could be a good opportunity for weakrefs.

loadState(cycle, timeNode, timeStepName='', fileName=None, updateMassFractions=None)[source]

Convenience method reroute to the database interface state reload method

See also

armi.bookeeping.db.loadOperator

A method for loading an operator given a database. loadOperator does not require an operator prior to loading the state of the reactor. loadState does, and therefore armi.init must be called which requires access to the blueprints, settings, and geometry files. These files are stored implicitly on the database, so loadOperator creates the reactor first, and then attaches it to the operator. loadState should be used if you are in the middle of an ARMI calculation and need load a different time step. If you are loading from a fresh ARMI session, either method is sufficient if you have access to all the input files.

snapshotRequest(cycle, node)[source]

Process a snapshot request at this time.

This copies various physics input and output files to a special folder that follow-on analysis be executed upon later.

Notes

This was originally used to produce MC2/DIF3D inputs for external parties (who didn’t have ARMI) to review. Since then, the concept of snapshots has evolved with respect to the OperatorSnapshots.

static setStateToDefault(cs)[source]

Update the state of ARMI to fit the kind of run this operator manages

couplingIsActive()[source]

True if any kind of physics coupling is active.