Skip to content

Commit

Permalink
Merge branch 'main' into add_endfb-VII.1_support
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron Reynolds committed Oct 30, 2024
2 parents 11752a6 + 6fcc481 commit dd6cc03
Show file tree
Hide file tree
Showing 14 changed files with 430 additions and 175 deletions.
15 changes: 0 additions & 15 deletions armi/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,6 @@
# limitations under the License.

"""Code that needs to be executed before most ARMI components are safe to import."""

import sys

# This is a courtesy, to help people who accidently run ARMI with an old version of Python.
if (
sys.version_info.major < 3
or sys.version_info.major == 3
and sys.version_info.minor < 7
):
raise RuntimeError(
"ARMI highly recommends using Python 3.9 or 3.11. Are you sure you are using the "
f"correct interpreter?\nYou are using: {sys.executable}"
)


from armi.nucDirectory import nuclideBases # noqa: E402

# Nuclide bases get built explicitly here to have better determinism
Expand Down
3 changes: 0 additions & 3 deletions armi/bookkeeping/historyTracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,6 @@ def __init__(self, r, cs):
self.xsHistory = {}
self._preloadedBlockHistory = None

msg = "The HistoryTrackerInterface is deprecated, and will be removed."
runLog.warning(msg)

def interactBOL(self):
self.addDetailAssembliesBOL()

Expand Down
18 changes: 16 additions & 2 deletions armi/reactor/assemblies.py
Original file line number Diff line number Diff line change
Expand Up @@ -1219,9 +1219,8 @@ def rotate(self, rad):
Parameters
----------
rad: float
rad : float
number (in radians) specifying the angle of counter clockwise rotation
"""
for b in self:
b.rotate(rad)
Expand All @@ -1230,6 +1229,21 @@ def isOnWhichSymmetryLine(self):
grid = self.parent.spatialGrid
return grid.overlapsWhichSymmetryLine(self.spatialLocator.getCompleteIndices())

def orientBlocks(self, parentSpatialGrid):
"""Add special grids to the blocks inside this Assembly, respecting their orientation.
Parameters
----------
parentSpatialGrid : Grid
Spatial Grid of the parent of this Assembly (probably a system-level grid).
"""
for b in self:
if b.spatialGrid is None:
try:
b.autoCreateSpatialGrids(parentSpatialGrid)
except (ValueError, NotImplementedError) as e:
runLog.warning(str(e), single=True)


class HexAssembly(Assembly):
"""An assembly that is hexagonal in cross-section."""
Expand Down
87 changes: 60 additions & 27 deletions armi/reactor/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,22 +293,28 @@ def getSmearDensity(self, cold=True):

return smearDensity

def autoCreateSpatialGrids(self):
def autoCreateSpatialGrids(self, systemSpatialGrid=None):
"""
Creates a spatialGrid for a Block.
Blocks do not always have a spatialGrid from Blueprints, but, some Blocks can have their
spatialGrids inferred based on the multiplicty of their components.
This would add the ability to create a spatialGrid for a Block and give its children
the corresponding spatialLocators if certain conditions are met.
Blocks do not always have a spatialGrid from Blueprints, but some Blocks can have their
spatialGrids inferred based on the multiplicty of their components. This would add the
ability to create a spatialGrid for a Block and give its children the corresponding
spatialLocators if certain conditions are met.
Parameters
----------
systemSpatialGrid : Grid, optional
Spatial Grid of the system-level parent of this Assembly that contains this Block.
Raises
------
ValueError
If the multiplicities of the block are not only 1 or N or if generated ringNumber leads
to more positions than necessary.
"""
raise NotImplementedError()
if self.spatialGrid is None:
self.spatialGrid = systemSpatialGrid

def getMgFlux(self, adjoint=False, average=False, volume=None, gamma=False):
"""
Expand Down Expand Up @@ -2316,7 +2322,7 @@ def getSymmetryFactor(self):
return 2.0
return 1.0

def autoCreateSpatialGrids(self):
def autoCreateSpatialGrids(self, systemSpatialGrid=None):
"""
Given a block without a spatialGrid, create a spatialGrid and give its children the
corresponding spatialLocators (if it is a simple block).
Expand All @@ -2325,20 +2331,27 @@ def autoCreateSpatialGrids(self):
to 1 or N but no other multiplicities. Also, this should only happen when N fits exactly
into a given number of hex rings. Otherwise, do not create a grid for this block.
Parameters
----------
systemSpatialGrid : Grid, optional
Spatial Grid of the system-level parent of this Assembly that contains this Block.
Notes
-----
If the Block meets all the conditions, we gather all components to either be a
multiIndexLocation containing all of the pin positions, or the locator is the center (0,0).
When a hex grid has another hex grid nested inside it, the nested grid has the opposite
orientation (corners vs flats up). This method takes care of that.
Also, this only works on blocks that have 'flat side up'.
If components inside this block are multiplicity 1, they get a single locator at the center
of the grid cell. If the multiplicity is greater than 1, all the components are added to a
multiIndexLocation on the hex grid.
Raises
------
ValueError
If the multiplicities of the block are not only 1 or N or if generated ringNumber leads
to more positions than necessary.
"""
# Check multiplicities...
# Check multiplicities
mults = {c.getDimension("mult") for c in self.iterComponents()}

if len(mults) != 2 or 1 not in mults:
Expand All @@ -2348,29 +2361,39 @@ def autoCreateSpatialGrids(self):
)
)

ringNumber = hexagon.numRingsToHoldNumCells(self.getNumPins())
# For the below to work, there must not be multiple wire or multiple clad types.
# note that it's the pointed end of the cell hexes that are up (but the
# macro shape of the pins forms a hex with a flat top fitting in the assembly)
# build the grid, from pitch and orientation
if isinstance(systemSpatialGrid, grids.HexGrid):
cornersUp = not systemSpatialGrid.cornersUp
else:
cornersUp = False

grid = grids.HexGrid.fromPitch(
self.getPinPitch(cold=True), numRings=0, cornersUp=True
self.getPinPitch(cold=True),
numRings=0,
armiObject=self,
cornersUp=cornersUp,
)
spatialLocators = grids.MultiIndexLocation(grid=self.spatialGrid)

ringNumber = hexagon.numRingsToHoldNumCells(self.getNumPins())
numLocations = 0
for ring in range(ringNumber):
numLocations = numLocations + hexagon.numPositionsInRing(ring + 1)

if numLocations != self.getNumPins():
raise ValueError(
"Cannot create spatialGrid, number of locations in rings{} not equal to pin number{}".format(
"Cannot create spatialGrid, number of locations in rings {} not equal to pin number {}".format(
numLocations, self.getNumPins()
)
)

i = 0
# set the spatial position of the sub-block components
spatialLocators = grids.MultiIndexLocation(grid=grid)
for ring in range(ringNumber):
for pos in range(grid.getPositionsInRing(ring + 1)):
i, j = grid.getIndicesFromRingAndPos(ring + 1, pos + 1)
spatialLocators.append(grid[i, j, 0])

# finally, fill the spatial grid, and put the sub-block components on it
if self.spatialGrid is None:
self.spatialGrid = grid
for c in self:
Expand Down Expand Up @@ -2486,13 +2509,10 @@ def getWettedPerimeter(self):
)

# flags pertaining to circular pin components where the exterior of the circle is wetted
wettedPinComponentFlags = (
Flags.CLAD,
Flags.WIRE,
)
wettedPinComponentFlags = (Flags.CLAD, Flags.WIRE)

# flags pertaining to circular components where both the interior and exterior of the circle are wetted
wettedHollowCircleComponentFlags = (Flags.DUCT | Flags.INNER,)
# flags pertaining to components where both the interior and exterior are wetted
wettedHollowComponentFlags = (Flags.DUCT | Flags.INNER,)

# obtain all wetted components based on type
wettedHollowHexagonComponents = []
Expand All @@ -2506,9 +2526,13 @@ def getWettedPerimeter(self):
wettedPinComponents.append(c) if c else None

wettedHollowCircleComponents = []
for flag in wettedHollowCircleComponentFlags:
wettedHollowHexComponents = []
for flag in wettedHollowComponentFlags:
c = self.getComponent(flag, exact=True)
wettedHollowCircleComponents.append(c) if c else None
if isinstance(c, Hexagon):
wettedHollowHexComponents.append(c) if c else None
else:
wettedHollowCircleComponents.append(c) if c else None

# calculate wetted perimeters according to their geometries

Expand Down Expand Up @@ -2542,10 +2566,19 @@ def getWettedPerimeter(self):
)
wettedHollowCirclePerimeter *= math.pi

# hollow hexagon = 6 * (ip + op) / sqrt(3)
wettedHollowHexPerimeter = 0.0
for c in wettedHollowHexComponents:
wettedHollowHexPerimeter += (
c.getDimension("ip") + c.getDimension("op") if c else 0.0
)
wettedHollowHexPerimeter *= 6 / math.sqrt(3)

return (
wettedHollowHexagonPerimeter
+ wettedPinPerimeter
+ wettedHollowCirclePerimeter
+ wettedHollowHexPerimeter
)

def getFlowArea(self):
Expand Down
10 changes: 2 additions & 8 deletions armi/reactor/blueprints/blockBlueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,12 @@
from armi import getPluginManagerOrFail, runLog
from armi.materials.material import Material
from armi.reactor import blocks
from armi.reactor.composites import Composite
from armi.reactor import parameters
from armi.reactor.flags import Flags
from armi.reactor.blueprints import componentBlueprint
from armi.reactor.components.component import Component
from armi.reactor.composites import Composite
from armi.reactor.converters import blockConverters
from armi.settings.fwSettings import globalSettings
from armi.reactor.flags import Flags


def _configureGeomOptions():
Expand Down Expand Up @@ -240,11 +239,6 @@ def construct(
b.verifyBlockDims()
b.spatialGrid = spatialGrid

if b.spatialGrid is None and cs[globalSettings.CONF_BLOCK_AUTO_GRID]:
try:
b.autoCreateSpatialGrids()
except (ValueError, NotImplementedError) as e:
runLog.warning(str(e), single=True)
return b

def _getBlockwiseMaterialModifierOptions(
Expand Down
2 changes: 2 additions & 0 deletions armi/reactor/cores.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,10 +563,12 @@ def add(self, a, spatialLocator=None):
"".format(aName, self.assembliesByName[aName], a, self.r.p.maxAssemNum)
)
raise RuntimeError("Core already contains an assembly with the same name.")

self.assembliesByName[aName] = a
for b in a:
self.blocksByName[b.getName()] = b

a.orientBlocks(parentSpatialGrid=self.spatialGrid)
if self.geomType == geometry.GeomType.HEX:
ring, _loc = self.spatialGrid.getRingPos(
a.spatialLocator.getCompleteIndices()
Expand Down
2 changes: 1 addition & 1 deletion armi/reactor/grids/locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ def getLocalCoordinates(self, nativeCoords=False):
"""Return the coordinates of the center of the mesh cell here in cm."""
if self.grid is None:
raise ValueError(
"Cannot get local coordinates of {} because grid is None.".format(self)
f"Cannot get local coordinates of {self} because grid is None."
)
return self.grid.getCoordinates(self.indices, nativeCoords=nativeCoords)

Expand Down
4 changes: 2 additions & 2 deletions armi/reactor/grids/structuredGrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

import numpy as np

from armi.reactor.grids.grid import Grid
from armi.reactor.grids.locations import (
IJKType,
LocationBase,
IndexLocation,
LocationBase,
MultiIndexLocation,
)
from armi.reactor.grids.grid import Grid

# data structure for database-serialization of grids
GridParameters = collections.namedtuple(
Expand Down
Loading

0 comments on commit dd6cc03

Please sign in to comment.