Skip to content

Commit

Permalink
Revamping Requirements (#2074)
Browse files Browse the repository at this point in the history
Here we delete the requirements:

- R_ARMI_ASSEM_DIMS
- R_ARMI_BLOCK_DIMS
- R_ARMI_CMP_BY_NAME
- R_ARMI_CMP_GET_NAME
- R_ARMI_COMP_SOLID
- R_ARMI_DEPL_DEPLETABLE
- R_ARMI_FLUX_COUPLING_VALUE
- R_ARMI_GAMMA_XS
- R_ARMI_MAT_NAME
- R_ARMI_MAT_VOID
- R_ARMI_R_CORE
- R_ARMI_R_NUM_RINGS
- R_ARMI_SETTINGS_BEFORE_REACTOR_HOOK
- R_ARMI_SETTINGS_UNIQUE
- R_ARMI_SHUFFLE_MOVE
- R_ARMI_UTIL_DENS_TOOLS
- R_ARMI_UTIL_HEXAGON

And we are merging these requirements:

- Merge R_ARMI_DB_R_LOAD into R_ARMI_DB_TIME
- Merge R_ARMI_PARAM_PART into R_ARMI_PARAM
- Merge R_ARMI_R_GET_ASSEM_LOC and R_ARMI_R_GET_ASSEM_NAME into R_ARMI_R_GET_ASSEM
- Merge R_ARMI_ZONES into R_ARMI_ZONE
  • Loading branch information
john-science authored Feb 7, 2025
1 parent 31dc3b0 commit 6febc65
Show file tree
Hide file tree
Showing 36 changed files with 175 additions and 711 deletions.
39 changes: 10 additions & 29 deletions armi/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,35 +115,17 @@ def pluginManager(self) -> pluginManager.ArmiPluginManager:
return self._pm

def getSettings(self) -> Dict[str, Setting]:
"""
Return a dictionary containing all Settings defined by the framework and all plugins.
.. impl:: Applications will not allow duplicate settings.
:id: I_ARMI_SETTINGS_UNIQUE
:implements: R_ARMI_SETTINGS_UNIQUE
Each ARMI application includes a collection of Plugins. Among other
things, these plugins can register new settings in addition to
the default settings that come with ARMI. This feature provides a
lot of utility, so application developers can easily configure
their ARMI appliction in customizable ways.
However, it would get confusing if two different plugins registered
a setting with the same name string. Or if a plugin registered a
setting with the same name as an ARMI default setting. So this
method throws an error if such a situation arises.
"""
"""Return a dictionary containing all Settings defined by the framework and all plugins."""
# Start with framework settings
settingDefs = {
setting.name: setting for setting in fwSettings.getFrameworkSettings()
}

# The optionsCache stores options that may have come from a plugin before the
# setting to which they apply. Whenever a new setting is added, we check to see
# if there are any options in the cache, popping them out and adding them to the
# setting. If all plugins' settings have been processed and the cache is not
# empty, that's an error, because a plugin must have provided options to a
# setting that doesn't exist.
# The optionsCache stores options that may have come from a plugin before the setting to
# which they apply. Whenever a new setting is added, we check to see if there are any
# options in the cache, popping them out and adding them to the setting. If all plugins'
# settings have been processed and the cache is not empty, that's an error, because a plugin
# must have provided options to a setting that doesn't exist.
optionsCache: Dict[str, List[settings.Option]] = collections.defaultdict(list)
defaultsCache: Dict[str, settings.Default] = {}

Expand Down Expand Up @@ -205,11 +187,10 @@ def getParamRenames(self) -> Dict[str, str]:
"""
Return the parameter renames from all registered plugins.
This renders a merged dictionary containing all parameter renames from all of
the registered plugins. It also performs simple error checking. The result of
this operation is cached, since it is somewhat expensive to perform. If the App
detects that its plugin manager's set of registered plugins has changed, the
cache will be invalidated and recomputed.
This renders a merged dictionary containing all parameter renames from all of the registered
plugins. It also performs simple error checking. The result of this operation is cached,
since it is somewhat expensive to perform. If the App detects that its plugin manager's set
of registered plugins has changed, the cache will be invalidated and recomputed.
"""
cacheInvalid = False
if self._paramRenames is not None:
Expand Down
7 changes: 3 additions & 4 deletions armi/bookkeeping/db/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,17 +724,16 @@ def load(
is read from the database.
.. impl:: Users can load a reactor from a DB.
:id: I_ARMI_DB_R_LOAD
:implements: R_ARMI_DB_R_LOAD
:id: I_ARMI_DB_TIME1
:implements: R_ARMI_DB_TIME
This method creates a ``Reactor`` object by reading the reactor state out
of an ARMI database file. This is done by passing in mandatory arguements
that specify the exact place in time you want to load the reactor from.
(That is, the cycle and node numbers.) Users can either pass the settings
and blueprints directly into this method, or it will attempt to read them
from the database file. The primary work done here is to read the hierarchy
of reactor objects from the data file, then reconstruct them in the correct
order.
of reactor objects from the data file, then reconstruct them in the correct order.
Parameters
----------
Expand Down
5 changes: 2 additions & 3 deletions armi/bookkeeping/db/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ def writeToDB(self, h5group):
"""Write a chunk of data to the database.
.. impl:: Write data to the DB for a given time step.
:id: I_ARMI_DB_TIME
:id: I_ARMI_DB_TIME0
:implements: R_ARMI_DB_TIME
This method writes a snapshot of the current state of the reactor to the
Expand All @@ -393,8 +393,7 @@ def writeToDB(self, h5group):
objects are written to the file. Though, this turns out to still be very
powerful. For instance, the data for all ``HexBlock`` children of a given
parent are stored contiguously within the ``HexBlock`` group, and will not
be interleaved with data from the ``HexBlock`` children of any of the
parent's siblings.
be interleaved with data from the ``HexBlock`` children of any of the parent's siblings.
"""
if "layout/type" in h5group:
# It looks like we have already written the layout to DB, skip for now
Expand Down
6 changes: 3 additions & 3 deletions armi/bookkeeping/db/tests/test_database3.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ def test_load(self):
"""Load a reactor at different time steps, from the database.
.. test:: Load the reactor from the database.
:id: T_ARMI_DB_R_LOAD
:tests: R_ARMI_DB_R_LOAD
:id: T_ARMI_DB_TIME1
:tests: R_ARMI_DB_TIME
"""
self.makeShuffleHistory()
with self.assertRaises(KeyError):
Expand Down Expand Up @@ -301,7 +301,7 @@ def test_writeToDB(self):
"""Test writing to the database.
.. test:: Write a single time step of data to the database.
:id: T_ARMI_DB_TIME
:id: T_ARMI_DB_TIME0
:tests: R_ARMI_DB_TIME
"""
self.r.p.cycle = 0
Expand Down
8 changes: 1 addition & 7 deletions armi/cases/tests/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,13 +648,7 @@ def test_copyInterfaceInputs_nonFilePath(self):
self.assertEqual(newSettings[testSetting], fakeShuffle)

def test_failOnDuplicateSetting(self):
"""
That that if a plugin attempts to add a duplicate setting, it raises an error.
.. test:: Plugins cannot register duplicate settings.
:id: T_ARMI_SETTINGS_UNIQUE
:tests: R_ARMI_SETTINGS_UNIQUE
"""
"""That that if a plugin attempts to add a duplicate setting, it raises an error."""
# register the new Plugin
app = getApp()
app.pluginManager.register(TestPluginWithDuplicateSetting)
Expand Down
13 changes: 1 addition & 12 deletions armi/materials/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,18 +146,7 @@ def __repr__(self):

@property
def name(self):
"""
Getter for the private name attribute of this Material.
.. impl:: The name of a material is accessible.
:id: I_ARMI_MAT_NAME
:implements: R_ARMI_MAT_NAME
Every instance of an ARMI material must have a simple, human-readable string name. And,
if possible, we want this string to match the class name. (This, of course, puts some
limits on both the string and the class name.) These names are easily retrievable as a
class property.
"""
"""Getter for the private name attribute of this Material."""
return self._name

@name.setter
Expand Down
32 changes: 4 additions & 28 deletions armi/materials/tests/test_materials.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,6 @@ def test_findMaterial(self):
.. test:: Materials can be grabbed from a list of namespaces.
:id: T_ARMI_MAT_NAMESPACE0
:tests: R_ARMI_MAT_NAMESPACE
.. test:: You can find a material by name.
:id: T_ARMI_MAT_NAME
:tests: R_ARMI_MAT_NAME
"""
self.assertIs(
materials.resolveMaterialClassByName(
Expand Down Expand Up @@ -893,47 +889,27 @@ class Void_TestCase(_Material_Test, unittest.TestCase):
MAT_CLASS = materials.Void

def test_pseudoDensity(self):
"""This material has a no pseudo-density.
.. test:: There is a void material.
:id: T_ARMI_MAT_VOID0
:tests: R_ARMI_MAT_VOID
"""
"""This material has a no pseudo-density."""
self.mat.setDefaultMassFracs()
cur = self.mat.pseudoDensity()
self.assertEqual(cur, 0.0)

def test_density(self):
"""This material has no density.
.. test:: There is a void material.
:id: T_ARMI_MAT_VOID1
:tests: R_ARMI_MAT_VOID
"""
"""This material has no density."""
self.assertEqual(self.mat.density(500), 0)

self.mat.setDefaultMassFracs()
cur = self.mat.density()
self.assertEqual(cur, 0.0)

def test_linearExpansion(self):
"""This material does not expand linearly.
.. test:: There is a void material.
:id: T_ARMI_MAT_VOID2
:tests: R_ARMI_MAT_VOID
"""
"""This material does not expand linearly."""
cur = self.mat.linearExpansion(400)
ref = 0.0
self.assertEqual(cur, ref)

def test_propertyValidTemperature(self):
"""This material has no valid temperatures.
.. test:: There is a void material.
:id: T_ARMI_MAT_VOID3
:tests: R_ARMI_MAT_VOID
"""
"""This material has no valid temperatures."""
self.assertEqual(len(self.mat.propertyValidTemperature), 0)


Expand Down
13 changes: 1 addition & 12 deletions armi/materials/void.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,7 @@


class Void(material.Fluid):
"""A Void material is a bookkeeping material with zero density.
.. impl:: Define a void material with zero density.
:id: I_ARMI_MAT_VOID
:implements: R_ARMI_MAT_VOID
To help with expansion, it is sometimes useful to put a small section of void
material into the reactor model. This is not meant to represent a true void,
that would cause negative pressure in a system, but just as a bookkeeping tool.
Sometimes this helps users define the geometry of an expanding and conctracting
reactor. It is called a "void" because it has zero density at all temperatures.
"""
"""A Void material is a bookkeeping material with zero density."""

def pseudoDensity(self, Tk: float = None, Tc: float = None) -> float:
return 0.0
Expand Down
34 changes: 11 additions & 23 deletions armi/physics/fuelCycle/fuelHandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -706,34 +706,22 @@ def _getAssembliesInRings(
def swapAssemblies(self, a1, a2):
"""Moves a whole assembly from one place to another.
.. impl:: Assemblies can be moved from one place to another.
:id: I_ARMI_SHUFFLE_MOVE
:implements: R_ARMI_SHUFFLE_MOVE
For the two assemblies that are passed in, call to their :py:meth:`~armi.reactor.assemblies.Assembly.moveTo`
methods to transfer their underlying ``spatialLocator`` attributes to
each other. This will also update the ``childrenByLocator`` list on the
core as well as the assembly parameters ``numMoves`` and ``daysSinceLastMove``.
.. impl:: User-specified blocks can be left in place during within-core swaps.
:id: I_ARMI_SHUFFLE_STATIONARY0
:implements: R_ARMI_SHUFFLE_STATIONARY
Before assemblies are moved,
the ``_transferStationaryBlocks`` class method is called to
check if there are any block types specified by the user as stationary
via the ``stationaryBlockFlags`` case setting. Using these flags, blocks
are gathered from each assembly which should remain stationary and
checked to make sure that both assemblies have the same number
and same height of stationary blocks. If not, return an error.
Before assemblies are moved, the ``_transferStationaryBlocks`` class method is called to
check if there are any block types specified by the user as stationary via the
``stationaryBlockFlags`` case setting. Using these flags, blocks are gathered from each
assembly which should remain stationary and checked to make sure that both assemblies
have the same number and same height of stationary blocks. If not, return an error.
If all checks pass, the :py:meth:`~armi.reactor.assemblies.Assembly.remove`
and :py:meth:`~armi.reactor.assemblies.Assembly.insert`
methods are used to swap the stationary blocks between the two assemblies.
If all checks pass, the :py:meth:`~armi.reactor.assemblies.Assembly.remove` and
:py:meth:`~armi.reactor.assemblies.Assembly.insert` methods are used to swap the
stationary blocks between the two assemblies.
Once this process is complete, the actual assembly movement can take
place. Through this process, the stationary blocks remain in the same
core location.
Once this process is complete, the actual assembly movement can take place. Through this
process, the stationary blocks remain in the same core location.
Parameters
----------
Expand Down Expand Up @@ -928,7 +916,7 @@ def swapCascade(self, assemList):
self.swapAssemblies(assemList[0], assemList[level + 1])

def repeatShufflePattern(self, explicitRepeatShuffles):
r"""
"""
Repeats the fuel management from a previous ARMI run.
Parameters
Expand Down
8 changes: 0 additions & 8 deletions armi/physics/fuelCycle/tests/test_fuelHandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -484,10 +484,6 @@ def test_repeatShuffles(self):
:id: T_ARMI_SHUFFLE
:tests: R_ARMI_SHUFFLE
.. test:: Move an assembly from one position in the core to another.
:id: T_ARMI_SHUFFLE_MOVE0
:tests: R_ARMI_SHUFFLE_MOVE
Notes
-----
The custom shuffle logic is executed by
Expand Down Expand Up @@ -798,10 +794,6 @@ def test_transferIncompatibleHeightStationaryBlocks(self):
def test_dischargeSwap(self):
"""Remove an assembly from the core and replace it with one from the SFP.
.. test:: Move an assembly from one position in the core to another.
:id: T_ARMI_SHUFFLE_MOVE1
:tests: R_ARMI_SHUFFLE_MOVE
.. test:: User-specified blocks can remain in place during shuffling
:id: T_ARMI_SHUFFLE_STATIONARY1
:tests: R_ARMI_SHUFFLE_STATIONARY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,7 @@ def setUp(self):
self.assertFalse(self.fpModel._useGlobalLFPs)

def test_nuclidesInModelAllDepletableBlocks(self):
"""Test that the depletable blocks contain all the MC2-3 modeled nuclides.
.. test:: Determine if any component is depletable.
:id: T_ARMI_DEPL_DEPLETABLE
:tests: R_ARMI_DEPL_DEPLETABLE
"""
"""Test that the depletable blocks contain all the MC2-3 modeled nuclides."""
# Check that there are some fuel and control blocks in the core model.
fuelBlocks = self.r.core.getBlocks(Flags.FUEL)
controlBlocks = self.r.core.getBlocks(Flags.CONTROL)
Expand Down
18 changes: 1 addition & 17 deletions armi/physics/neutronics/globalFlux/globalFluxInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,23 +251,7 @@ def interactCoupled(self, iteration):
GlobalFluxInterface.interactCoupled(self, iteration)

def getTightCouplingValue(self):
"""Return the parameter value.
.. impl:: Return k-eff or assembly-wise power distribution for coupled interactions.
:id: I_ARMI_FLUX_COUPLING_VALUE
:implements: R_ARMI_FLUX_COUPLING_VALUE
This method either returns the k-eff or assembly-wise power
distribution. If the :py:class:`coupler
<armi.interfaces.TightCoupler>` ``parameter`` member is ``"keff"``,
then this method returns the computed k-eff from the global flux
evaluation. If the ``parameter`` value is ``"power"``, then it
returns a list of power distributions in each assembly. The assembly
power distributions are lists of values representing the block
powers that are normalized to unity based on the assembly total
power. If the value is neither ``"keff"`` or ``"power"``, then this
method returns ``None``.
"""
"""Return the parameter value."""
if self.coupler.parameter == "keff":
return self.r.core.p.keff
if self.coupler.parameter == "power":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,7 @@ def test_setTightCouplingDefaults(self):
self._setTightCouplingFalse()

def test_getTightCouplingValue(self):
"""Test getTightCouplingValue returns the correct value for keff and type for power.
.. test:: Return k-eff or assembly-wise power for coupling interactions.
:id: T_ARMI_FLUX_COUPLING_VALUE
:tests: R_ARMI_FLUX_COUPLING_VALUE
"""
"""Test getTightCouplingValue returns the correct value for keff and type for power."""
self._setTightCouplingTrue()
self.assertEqual(self.gfi.getTightCouplingValue(), 1.0) # set in setUp
self.gfi.coupler.parameter = "power"
Expand Down
Loading

0 comments on commit 6febc65

Please sign in to comment.