Skip to content

Commit

Permalink
Revert "Fixing sub-block grids (#1947)"
Browse files Browse the repository at this point in the history
This reverts commit 6b356b3.
  • Loading branch information
john-science authored Oct 30, 2024
1 parent 6b356b3 commit d0f64ec
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 335 deletions.
15 changes: 15 additions & 0 deletions armi/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@
# 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: 3 additions & 0 deletions armi/bookkeeping/historyTracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ 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: 2 additions & 16 deletions armi/reactor/assemblies.py
Original file line number Diff line number Diff line change
Expand Up @@ -1219,8 +1219,9 @@ 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 @@ -1229,21 +1230,6 @@ 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
61 changes: 19 additions & 42 deletions armi/reactor/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,28 +293,22 @@ def getSmearDensity(self, cold=True):

return smearDensity

def autoCreateSpatialGrids(self, systemSpatialGrid=None):
def autoCreateSpatialGrids(self):
"""
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.
Parameters
----------
systemSpatialGrid : Grid, optional
Spatial Grid of the system-level parent of this Assembly that contains this 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.
Raises
------
ValueError
If the multiplicities of the block are not only 1 or N or if generated ringNumber leads
to more positions than necessary.
"""
if self.spatialGrid is None:
self.spatialGrid = systemSpatialGrid
raise NotImplementedError()

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

def autoCreateSpatialGrids(self, systemSpatialGrid=None):
def autoCreateSpatialGrids(self):
"""
Given a block without a spatialGrid, create a spatialGrid and give its children the
corresponding spatialLocators (if it is a simple block).
Expand All @@ -2331,27 +2325,20 @@ def autoCreateSpatialGrids(self, systemSpatialGrid=None):
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
-----
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.
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).
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.
Also, this only works on blocks that have 'flat side up'.
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 @@ -2361,39 +2348,29 @@ def autoCreateSpatialGrids(self, systemSpatialGrid=None):
)
)

# build the grid, from pitch and orientation
if isinstance(systemSpatialGrid, grids.HexGrid):
cornersUp = not systemSpatialGrid.cornersUp
else:
cornersUp = False

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)
grid = grids.HexGrid.fromPitch(
self.getPinPitch(cold=True),
numRings=0,
armiObject=self,
cornersUp=cornersUp,
self.getPinPitch(cold=True), numRings=0, cornersUp=True
)

ringNumber = hexagon.numRingsToHoldNumCells(self.getNumPins())
spatialLocators = grids.MultiIndexLocation(grid=self.spatialGrid)
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()
)
)

# set the spatial position of the sub-block components
spatialLocators = grids.MultiIndexLocation(grid=grid)
i = 0
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
10 changes: 8 additions & 2 deletions armi/reactor/blueprints/blockBlueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@
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.reactor.flags import Flags
from armi.settings.fwSettings import globalSettings


def _configureGeomOptions():
Expand Down Expand Up @@ -239,6 +240,11 @@ 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: 0 additions & 2 deletions armi/reactor/cores.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,12 +563,10 @@ 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(
f"Cannot get local coordinates of {self} because grid is None."
"Cannot get local coordinates of {} because grid is None.".format(self)
)
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,
IndexLocation,
LocationBase,
IndexLocation,
MultiIndexLocation,
)
from armi.reactor.grids.grid import Grid

# data structure for database-serialization of grids
GridParameters = collections.namedtuple(
Expand Down
98 changes: 10 additions & 88 deletions armi/reactor/grids/tests/test_grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@

"""Tests for grids."""
from io import BytesIO
from random import randint
import math
import pickle
from random import randint
import unittest
import pickle

import numpy as np
from numpy.testing import assert_allclose, assert_array_equal

from armi.utils import hexagon
from armi.reactor import geometry
from armi.reactor import grids
from armi.utils import hexagon


class MockLocator(grids.IndexLocation):
Expand Down Expand Up @@ -240,9 +240,8 @@ def test_ringPosFromIndicesIncorrect(self):
class TestHexGrid(unittest.TestCase):
"""A set of tests for the Hexagonal Grid."""

def test_getCoordinatesFlatsUp(self):
"""Test getCoordinates() for flats up hex grids."""
grid = grids.HexGrid.fromPitch(1.0, cornersUp=False)
def test_positions(self):
grid = grids.HexGrid.fromPitch(1.0)
self.assertAlmostEqual(grid.pitch, 1.0)
side = 1.0 / math.sqrt(3)
assert_allclose(grid.getCoordinates((0, 0, 0)), (0.0, 0.0, 0.0))
Expand All @@ -264,88 +263,6 @@ def test_getCoordinatesFlatsUp(self):
assert_allclose(grid.getCoordinates((1, 0, 0)), iDirection)
assert_allclose(grid.getCoordinates((0, 1, 0)), jDirection)

def test_getCoordinatesCornersUp(self):
"""Test getCoordinates() for corners up hex grids."""
grid = grids.HexGrid.fromPitch(1.0, cornersUp=True)
self.assertAlmostEqual(grid.pitch, 1.0)
side = 1.0 / math.sqrt(3)
assert_allclose(grid.getCoordinates((0, 0, 0)), (0.0, 0.0, 0.0))
assert_allclose(grid.getCoordinates((1, 0, 0)), (0.5, 1.5 * side, 0.0))
assert_allclose(grid.getCoordinates((-1, 0, 0)), (-0.5, -1.5 * side, 0.0))
assert_allclose(grid.getCoordinates((0, 1, 0)), (-0.5, 1.5 * side, 0.0))
assert_allclose(grid.getCoordinates((1, -1, 0)), (1, 0.0, 0.0))

unitSteps = grid.reduce()[0]
iDirection = tuple(direction[0] for direction in unitSteps)
jDirection = tuple(direction[1] for direction in unitSteps)
for directionVector in (iDirection, jDirection):
self.assertAlmostEqual(
(sum(val**2 for val in directionVector)) ** 0.5,
1.0,
msg=f"Direction vector {directionVector} should have "
"magnitude 1 for pitch 1.",
)
assert_allclose(grid.getCoordinates((1, 0, 0)), iDirection)
assert_allclose(grid.getCoordinates((0, 1, 0)), jDirection)

def test_getLocalCoordinatesHex(self):
"""Test getLocalCoordinates() is different for corners up vs flats up hex grids."""
grid0 = grids.HexGrid.fromPitch(1.0, cornersUp=True)
grid1 = grids.HexGrid.fromPitch(1.0, cornersUp=False)
for i in range(3):
for j in range(3):
if i == 0 and j == 0:
continue
coords0 = grid0[i, j, 0].getLocalCoordinates()
coords1 = grid1[i, j, 0].getLocalCoordinates()
self.assertNotEqual(coords0[0], coords1[0], msg=f"X @ ({i}, {j})")
self.assertNotEqual(coords0[1], coords1[1], msg=f"Y @ ({i}, {j})")
self.assertEqual(coords0[2], coords1[2], msg=f"Z @ ({i}, {j})")

def test_getLocalCoordinatesCornersUp(self):
"""Test getLocalCoordinates() for corners up hex grids."""
# validate the first ring of a corners-up hex grid
grid = grids.HexGrid.fromPitch(1.0, cornersUp=True)
vals = []
for pos in range(grid.getPositionsInRing(2)):
i, j = grid.getIndicesFromRingAndPos(2, pos + 1)
vals.append(grid[i, j, 0].getLocalCoordinates())

# short in Y
maxY = max(v[1] for v in vals)
minY = min(v[1] for v in vals)
val = math.sqrt(3) / 2
self.assertAlmostEqual(maxY, val, delta=0.0001)
self.assertAlmostEqual(minY, -val, delta=0.0001)

# long in X
maxX = max(v[0] for v in vals)
minX = min(v[0] for v in vals)
self.assertAlmostEqual(maxX, 1)
self.assertAlmostEqual(minX, -1)

def test_getLocalCoordinatesFlatsUp(self):
"""Test getLocalCoordinates() for flats up hex grids."""
# validate the first ring of a flats-up hex grid
grid = grids.HexGrid.fromPitch(1.0, cornersUp=False)
vals = []
for pos in range(grid.getPositionsInRing(2)):
i, j = grid.getIndicesFromRingAndPos(2, pos + 1)
vals.append(grid[i, j, 0].getLocalCoordinates())

# long in Y
maxY = max(v[1] for v in vals)
minY = min(v[1] for v in vals)
self.assertAlmostEqual(maxY, 1)
self.assertAlmostEqual(minY, -1)

# short in X
maxX = max(v[0] for v in vals)
minX = min(v[0] for v in vals)
val = math.sqrt(3) / 2
self.assertAlmostEqual(maxX, val, delta=0.0001)
self.assertAlmostEqual(minX, -val, delta=0.0001)

def test_neighbors(self):
grid = grids.HexGrid.fromPitch(1.0)
neighbs = grid.getNeighboringCellIndices(0, 0, 0)
Expand Down Expand Up @@ -1018,3 +935,8 @@ def test_getLocations(self):
self.assertEqual(x, 0.0)
self.assertEqual(y, 0.0)
self.assertEqual(z, count + 0.5)


if __name__ == "__main__":
# import sys;sys.argv = ["", "TestHexGrid.testPositions"]
unittest.main()
Loading

0 comments on commit d0f64ec

Please sign in to comment.