From 0a3764cdca44cc86022eaf3749b5a5c64a5a7321 Mon Sep 17 00:00:00 2001 From: jstilley Date: Thu, 10 Oct 2024 15:56:23 -0700 Subject: [PATCH 01/13] Save point --- armi/reactor/assemblies.py | 13 +++- armi/reactor/blocks.py | 56 +++++++++++---- armi/reactor/blueprints/blockBlueprint.py | 10 +-- armi/reactor/cores.py | 4 ++ armi/reactor/grids/locations.py | 14 ++-- armi/reactor/grids/tests/test_grids.py | 85 +++++++++++++++++++++-- armi/reactor/spentFuelPool.py | 4 ++ armi/reactor/tests/test_blocks.py | 80 +++++++++++++++++++++ 8 files changed, 231 insertions(+), 35 deletions(-) diff --git a/armi/reactor/assemblies.py b/armi/reactor/assemblies.py index c26d74d6b..67b2a3c6d 100644 --- a/armi/reactor/assemblies.py +++ b/armi/reactor/assemblies.py @@ -1239,9 +1239,8 @@ def rotate(self, rad): Parameters ---------- - rad: float + float number (in radians) specifying the angle of counter clockwise rotation - """ for b in self: b.rotate(rad) @@ -1250,6 +1249,16 @@ def isOnWhichSymmetryLine(self): grid = self.parent.spatialGrid return grid.overlapsWhichSymmetryLine(self.spatialLocator.getCompleteIndices()) + def orientBlocks(self, cornersUp): + """TODO: JOHN.""" + for b in self: + # TODO: JOHN and cs[globalSettings.CONF_BLOCK_AUTO_GRID]: + if b.spatialGrid is None: + try: + b.autoCreateSpatialGrids(cornersUp) + except (ValueError, NotImplementedError) as e: + runLog.warning(str(e), single=True) + class HexAssembly(Assembly): """Placeholder, so users can explicitly define a hex-based Assembly.""" diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index 7d9f4cb51..abf8df650 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -292,7 +292,7 @@ def getSmearDensity(self, cold=True): return smearDensity - def autoCreateSpatialGrids(self): + def autoCreateSpatialGrids(self, cornersUp=True): """ Creates a spatialGrid for a Block. @@ -2332,7 +2332,7 @@ def getSymmetryFactor(self): return 2.0 return 1.0 - def autoCreateSpatialGrids(self): + def autoCreateSpatialGrids(self, cornersUp=True): """ Given a block without a spatialGrid, create a spatialGrid and give its children the corresponding spatialLocators (if it is a simple block). @@ -2341,6 +2341,11 @@ 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 + ---------- + cornersUp: bool + Should the hexagons of this grid be corners up (as opposed to flats-up)? + Notes ----- If the Block meets all the conditions, we gather all components to either be a @@ -2354,7 +2359,7 @@ def autoCreateSpatialGrids(self): 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: @@ -2364,17 +2369,17 @@ 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 grid = grids.HexGrid.fromPitch( - self.getPinPitch(cold=True), numRings=0, cornersUp=True + self.getPinPitch(cold=True), numRings=0, cornersUp=cornersUp ) - spatialLocators = grids.MultiIndexLocation(grid=self.spatialGrid) + assert grid.cornersUp + + 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( @@ -2382,11 +2387,38 @@ def autoCreateSpatialGrids(self): ) ) - i = 0 + x = [] + + #for pos0 in range(grid.getPositionsInRing(2)): + # print(pos0) + # i0, j0 = grid.getIndicesFromRingAndPos(2, pos0 + 1) + # print(i0, j0) + + # 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]) + i, j = grid.getIndicesFromRingAndPos(ring + 1, pos + 1) # TODO: JOHN: Not here + + locX = grid[i, j, 0] + if not isinstance(locX, grids.MultiIndexLocation): + locX = [locX] + for locx0 in locX: + try: + x.append(locx0.getLocalCoordinates()) # TODO: John. Maybe here + except Exception as e: + print(e) + raise e + + #print(grid[i, j, 0].grid.cornersUp) + spatialLocators.append(grid[i, j, 0]) # TODO: John. Maybe here + + print(f"min x: {min([v[0] for v in x])}") + print(f"max x: {max([v[0] for v in x])}") + print(f"min y: {min([v[1] for v in x])}") + print(f"max y: {max([v[1] for v in x])}") + + # 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: diff --git a/armi/reactor/blueprints/blockBlueprint.py b/armi/reactor/blueprints/blockBlueprint.py index f233fd58a..692ae84af 100644 --- a/armi/reactor/blueprints/blockBlueprint.py +++ b/armi/reactor/blueprints/blockBlueprint.py @@ -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(): @@ -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( diff --git a/armi/reactor/cores.py b/armi/reactor/cores.py index e84225145..311b3a4d4 100644 --- a/armi/reactor/cores.py +++ b/armi/reactor/cores.py @@ -563,11 +563,15 @@ 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 if self.geomType == geometry.GeomType.HEX: + cornerUp = self.spatialGrid.cornersUp + a.orientBlocks(cornersUp=cornerUp) + ring, _loc = self.spatialGrid.getRingPos( a.spatialLocator.getCompleteIndices() ) diff --git a/armi/reactor/grids/locations.py b/armi/reactor/grids/locations.py index ca9e93e1b..bb443f662 100644 --- a/armi/reactor/grids/locations.py +++ b/armi/reactor/grids/locations.py @@ -51,6 +51,10 @@ def __init__(self, i: int, j: int, k: int, grid: Optional["Grid"]): self._k = k self._grid = grid + #if grid is not None: + # print(grid) + # assert grid.cornersUp + def __repr__(self) -> str: return "<{} @ ({},{:},{})>".format( self.__class__.__name__, self.i, self.j, self.k @@ -288,9 +292,7 @@ def getCompleteIndices(self) -> IJKType: 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) - ) + raise ValueError(f"Cannot get local coordinates of {self} because grid is None.") return self.grid.getCoordinates(self.indices, nativeCoords=nativeCoords) def getGlobalCoordinates(self, nativeCoords=False): @@ -306,9 +308,7 @@ def getGlobalCellBase(self): """Return the cell base (i.e. "bottom left"), in global coordinate system.""" parentLocation = self.parentLocation # to avoid evaluating property if's twice if parentLocation: - return parentLocation.getGlobalCellBase() + self.grid.getCellBase( - self.indices - ) + return parentLocation.getGlobalCellBase() + self.grid.getCellBase(self.indices) return self.grid.getCellBase(self.indices) def getGlobalCellTop(self): @@ -376,6 +376,8 @@ class MultiIndexLocation(IndexLocation): def __init__(self, grid: "Grid"): IndexLocation.__init__(self, 0, 0, 0, grid) self._locations = [] + print(f"type(grid): {type(grid)}") + print(f"corners up? in multi index loc: {grid.cornersUp}") def __getstate__(self) -> List[IndexLocation]: """Used in pickling and deepcopy, this detaches the grid.""" diff --git a/armi/reactor/grids/tests/test_grids.py b/armi/reactor/grids/tests/test_grids.py index 26b5a334b..ec04b0df5 100644 --- a/armi/reactor/grids/tests/test_grids.py +++ b/armi/reactor/grids/tests/test_grids.py @@ -238,8 +238,8 @@ def test_ringPosFromIndicesIncorrect(self): class TestHexGrid(unittest.TestCase): """A set of tests for the Hexagonal Grid.""" - def test_positions(self): - grid = grids.HexGrid.fromPitch(1.0) + def test_getCoordinatesFlatsUp(self): + grid = grids.HexGrid.fromPitch(1.0, cornersUp=False) 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)) @@ -261,6 +261,82 @@ def test_positions(self): assert_allclose(grid.getCoordinates((1, 0, 0)), iDirection) assert_allclose(grid.getCoordinates((0, 1, 0)), jDirection) + def test_getCoordinatesCornersUp(self): + 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_getLocalCoordinates(self): + 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): + # validate the first ring of a corners-up hex gric + 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) + self.assertLess(maxY, 1) + self.assertGreater(minY, -1) + + # 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): + # validate the first ring of a flats-up hex gric + 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) + self.assertLess(maxX, 1) + self.assertGreater(minX, -1) + def test_neighbors(self): grid = grids.HexGrid.fromPitch(1.0) neighbs = grid.getNeighboringCellIndices(0, 0, 0) @@ -837,8 +913,3 @@ 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() diff --git a/armi/reactor/spentFuelPool.py b/armi/reactor/spentFuelPool.py index 7ca9e3e8f..d14a16f7b 100644 --- a/armi/reactor/spentFuelPool.py +++ b/armi/reactor/spentFuelPool.py @@ -70,6 +70,10 @@ def add(self, assem, loc=None): else: loc = self._getNextLocation() + # orient the blocks to match this grid + cornerUp = self.spatialGrid._unitSteps[0][1] == 0 + assem.orientBlocks(cornerUp) + super().add(assem, loc) def getAssembly(self, name): diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index d7b7f2a0c..d2ec38023 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -35,8 +35,10 @@ from armi.reactor.components import basicShapes, complexShapes from armi.reactor.flags import Flags from armi.reactor.tests.test_assemblies import makeTestAssembly +from armi.reactor.tests.test_reactors import loadTestReactor, TEST_ROOT from armi.tests import ISOAA_PATH, TEST_ROOT from armi.utils import hexagon, units +from armi.utils.directoryChangers import TemporaryDirectoryChanger from armi.utils.units import MOLES_PER_CC_TO_ATOMS_PER_BARN_CM NUM_PINS_IN_TEST_BLOCK = 217 @@ -2228,6 +2230,84 @@ def test_gridNotCreatedMultipleMultiplicities(self): self.assertIsNone(self.HexBlock.spatialGrid) +class TestHexBlockOrientation(unittest.TestCase): + def setUp(self): + self.td = TemporaryDirectoryChanger() + self.td.__enter__() + + def tearDown(self): + self.td.__exit__(None, None, None) + + def test_validateCornersUp(self): + # load a corners up reactor + _o, r = loadTestReactor( + os.path.join(TEST_ROOT, "smallestTestReactor"), + inputFileName="armiRunSmallest.yaml" + ) + + # grab a pinned fuel block, and verify it is corners up + b = r.core.getFirstBlock(Flags.FUEL) + self.assertTrue(b.spatialGrid.cornersUp) + + # if a hex shape is corners up, the pins should stretch more in Y than in X + maxX = -111 + minX = 999 + maxY = -111 + minY = 999 + print(len(b)) + for comp in b: + locs = comp.spatialLocator + if not isinstance(locs, grids.MultiIndexLocation): + print(comp, 1) + locs = [locs] + else: + print(comp, len(locs)) + for loc in locs: + x, y, _ = loc.getLocalCoordinates() + if x > maxX: + maxX = x + elif x < minX: + minX = x + + if y > maxY: + maxY = y + elif y < minY: + minY = y + + self.assertGreater(maxY - minY, maxX - minX) + + def test_validateFlatsUp(self): + # load a flats up reactor + _o, r = loadTestReactor(TEST_ROOT, inputFileName="armiRun.yaml") + + # grab a pinned fuel block, and verify it is flats up + b = r.core.getFirstBlock(Flags.FUEL) + self.assertFalse(b.spatialGrid.cornersUp) + + # if a hex shape is flats up, the pins should stretch more in X than in Y + maxX = -111 + minX = 999 + maxY = -111 + minY = 999 + for comp in b: + locs = comp.spatialLocator + if not isinstance(locs, grids.MultiIndexLocation): + locs = [locs] + for loc in locs: + x, y, _ = loc.getLocalCoordinates() + if x > maxX: + maxX = x + elif x < minX: + minX = x + + if y > maxY: + maxY = y + elif y < minY: + minY = y + + self.assertGreater(maxX - minX, maxY - minY) + + class ThRZBlock_TestCase(unittest.TestCase): def setUp(self): _ = settings.Settings() From f19ea492f00a3f2a956bff75da919f9ab53e423d Mon Sep 17 00:00:00 2001 From: jstilley Date: Thu, 10 Oct 2024 16:33:21 -0700 Subject: [PATCH 02/13] linting --- armi/reactor/blocks.py | 29 +++----------------------- armi/reactor/grids/locations.py | 14 ++++++------- armi/reactor/grids/structuredGrid.py | 4 ++-- armi/reactor/grids/tests/test_grids.py | 2 +- armi/reactor/tests/test_blocks.py | 16 ++++++-------- 5 files changed, 18 insertions(+), 47 deletions(-) diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index abf8df650..c5a3db340 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -2373,7 +2373,6 @@ def autoCreateSpatialGrids(self, cornersUp=True): grid = grids.HexGrid.fromPitch( self.getPinPitch(cold=True), numRings=0, cornersUp=cornersUp ) - assert grid.cornersUp ringNumber = hexagon.numRingsToHoldNumCells(self.getNumPins()) numLocations = 0 @@ -2387,37 +2386,15 @@ def autoCreateSpatialGrids(self, cornersUp=True): ) ) - x = [] - - #for pos0 in range(grid.getPositionsInRing(2)): - # print(pos0) - # i0, j0 = grid.getIndicesFromRingAndPos(2, pos0 + 1) - # print(i0, j0) - # 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) # TODO: JOHN: Not here - - locX = grid[i, j, 0] - if not isinstance(locX, grids.MultiIndexLocation): - locX = [locX] - for locx0 in locX: - try: - x.append(locx0.getLocalCoordinates()) # TODO: John. Maybe here - except Exception as e: - print(e) - raise e - - #print(grid[i, j, 0].grid.cornersUp) + i, j = grid.getIndicesFromRingAndPos( + ring + 1, pos + 1 + ) # TODO: JOHN: Not here spatialLocators.append(grid[i, j, 0]) # TODO: John. Maybe here - print(f"min x: {min([v[0] for v in x])}") - print(f"max x: {max([v[0] for v in x])}") - print(f"min y: {min([v[1] for v in x])}") - print(f"max y: {max([v[1] for v in x])}") - # finally, fill the spatial grid, and put the sub-block components on it if self.spatialGrid is None: self.spatialGrid = grid diff --git a/armi/reactor/grids/locations.py b/armi/reactor/grids/locations.py index bb443f662..fe150d251 100644 --- a/armi/reactor/grids/locations.py +++ b/armi/reactor/grids/locations.py @@ -51,10 +51,6 @@ def __init__(self, i: int, j: int, k: int, grid: Optional["Grid"]): self._k = k self._grid = grid - #if grid is not None: - # print(grid) - # assert grid.cornersUp - def __repr__(self) -> str: return "<{} @ ({},{:},{})>".format( self.__class__.__name__, self.i, self.j, self.k @@ -292,7 +288,9 @@ def getCompleteIndices(self) -> IJKType: 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.") + raise ValueError( + f"Cannot get local coordinates of {self} because grid is None." + ) return self.grid.getCoordinates(self.indices, nativeCoords=nativeCoords) def getGlobalCoordinates(self, nativeCoords=False): @@ -308,7 +306,9 @@ def getGlobalCellBase(self): """Return the cell base (i.e. "bottom left"), in global coordinate system.""" parentLocation = self.parentLocation # to avoid evaluating property if's twice if parentLocation: - return parentLocation.getGlobalCellBase() + self.grid.getCellBase(self.indices) + return parentLocation.getGlobalCellBase() + self.grid.getCellBase( + self.indices + ) return self.grid.getCellBase(self.indices) def getGlobalCellTop(self): @@ -376,8 +376,6 @@ class MultiIndexLocation(IndexLocation): def __init__(self, grid: "Grid"): IndexLocation.__init__(self, 0, 0, 0, grid) self._locations = [] - print(f"type(grid): {type(grid)}") - print(f"corners up? in multi index loc: {grid.cornersUp}") def __getstate__(self) -> List[IndexLocation]: """Used in pickling and deepcopy, this detaches the grid.""" diff --git a/armi/reactor/grids/structuredGrid.py b/armi/reactor/grids/structuredGrid.py index 437bb5b66..07388338b 100644 --- a/armi/reactor/grids/structuredGrid.py +++ b/armi/reactor/grids/structuredGrid.py @@ -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( diff --git a/armi/reactor/grids/tests/test_grids.py b/armi/reactor/grids/tests/test_grids.py index ec04b0df5..56f2bde4a 100644 --- a/armi/reactor/grids/tests/test_grids.py +++ b/armi/reactor/grids/tests/test_grids.py @@ -15,8 +15,8 @@ """Tests for grids.""" from io import BytesIO import math -import unittest import pickle +import unittest import numpy as np from numpy.testing import assert_allclose, assert_array_equal diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index d2ec38023..a4b3d6dbe 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -36,7 +36,7 @@ from armi.reactor.flags import Flags from armi.reactor.tests.test_assemblies import makeTestAssembly from armi.reactor.tests.test_reactors import loadTestReactor, TEST_ROOT -from armi.tests import ISOAA_PATH, TEST_ROOT +from armi.tests import ISOAA_PATH from armi.utils import hexagon, units from armi.utils.directoryChangers import TemporaryDirectoryChanger from armi.utils.units import MOLES_PER_CC_TO_ATOMS_PER_BARN_CM @@ -2242,26 +2242,22 @@ def test_validateCornersUp(self): # load a corners up reactor _o, r = loadTestReactor( os.path.join(TEST_ROOT, "smallestTestReactor"), - inputFileName="armiRunSmallest.yaml" + inputFileName="armiRunSmallest.yaml", ) # grab a pinned fuel block, and verify it is corners up b = r.core.getFirstBlock(Flags.FUEL) self.assertTrue(b.spatialGrid.cornersUp) - # if a hex shape is corners up, the pins should stretch more in Y than in X + # for corners up, the hex centroids should stretch more in X than Y maxX = -111 minX = 999 maxY = -111 minY = 999 - print(len(b)) for comp in b: locs = comp.spatialLocator if not isinstance(locs, grids.MultiIndexLocation): - print(comp, 1) locs = [locs] - else: - print(comp, len(locs)) for loc in locs: x, y, _ = loc.getLocalCoordinates() if x > maxX: @@ -2274,7 +2270,7 @@ def test_validateCornersUp(self): elif y < minY: minY = y - self.assertGreater(maxY - minY, maxX - minX) + self.assertGreater(maxX - minX, maxY - minY) def test_validateFlatsUp(self): # load a flats up reactor @@ -2284,7 +2280,7 @@ def test_validateFlatsUp(self): b = r.core.getFirstBlock(Flags.FUEL) self.assertFalse(b.spatialGrid.cornersUp) - # if a hex shape is flats up, the pins should stretch more in X than in Y + # for flats up, the hex centroids should stretch more in Y than X maxX = -111 minX = 999 maxY = -111 @@ -2305,7 +2301,7 @@ def test_validateFlatsUp(self): elif y < minY: minY = y - self.assertGreater(maxX - minX, maxY - minY) + self.assertGreater(maxY - minY, maxX - minX) class ThRZBlock_TestCase(unittest.TestCase): From b79e2e7c4cf0e8b60d31210fc077930950d88400 Mon Sep 17 00:00:00 2001 From: jstilley Date: Thu, 10 Oct 2024 16:37:08 -0700 Subject: [PATCH 03/13] cleanup --- armi/reactor/assemblies.py | 5 ++--- armi/reactor/blocks.py | 6 ++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/armi/reactor/assemblies.py b/armi/reactor/assemblies.py index 67b2a3c6d..0fcf97abe 100644 --- a/armi/reactor/assemblies.py +++ b/armi/reactor/assemblies.py @@ -1239,7 +1239,7 @@ def rotate(self, rad): Parameters ---------- - float + rad : float number (in radians) specifying the angle of counter clockwise rotation """ for b in self: @@ -1250,9 +1250,8 @@ def isOnWhichSymmetryLine(self): return grid.overlapsWhichSymmetryLine(self.spatialLocator.getCompleteIndices()) def orientBlocks(self, cornersUp): - """TODO: JOHN.""" + """Add special grids to the blocks inside this Assembly, respecting their orientation.""" for b in self: - # TODO: JOHN and cs[globalSettings.CONF_BLOCK_AUTO_GRID]: if b.spatialGrid is None: try: b.autoCreateSpatialGrids(cornersUp) diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index c5a3db340..ce4ceba72 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -2390,10 +2390,8 @@ def autoCreateSpatialGrids(self, cornersUp=True): 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 - ) # TODO: JOHN: Not here - spatialLocators.append(grid[i, j, 0]) # TODO: John. Maybe here + 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: From b244c8ae8331f2d64ae60afc96c9968388514edc Mon Sep 17 00:00:00 2001 From: jstilley Date: Fri, 11 Oct 2024 09:15:20 -0700 Subject: [PATCH 04/13] Adding release note --- doc/release/0.4.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst index e427faf9a..f6da64941 100644 --- a/doc/release/0.4.rst +++ b/doc/release/0.4.rst @@ -38,6 +38,7 @@ API Changes Bug Fixes --------- +#. Fixed locations of pins in Blocks on flats-up grids. (`PR#1947 `_) #. Fixed ``DerivedShape.getArea`` for ``cold=True``. (`PR#1831 `_) #. Fixed error parsing command line integers in ``ReportsEntryPoint``. (`PR#1824 `_) #. Fixed ``PermissionError`` when using ``syncDbAfterWrite``. (`PR#1857 `_) From 55c67152ff96e6926446dc5783dd96a6ab14fe34 Mon Sep 17 00:00:00 2001 From: John Stilley <1831479+john-science@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:26:13 -0700 Subject: [PATCH 05/13] Apply suggestions from code review Co-authored-by: Drew Johnson --- armi/reactor/grids/tests/test_grids.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armi/reactor/grids/tests/test_grids.py b/armi/reactor/grids/tests/test_grids.py index 56f2bde4a..fb2764da8 100644 --- a/armi/reactor/grids/tests/test_grids.py +++ b/armi/reactor/grids/tests/test_grids.py @@ -298,7 +298,7 @@ def test_getLocalCoordinates(self): self.assertEqual(coords0[2], coords1[2], msg=f"Z @ ({i}, {j})") def test_getLocalCoordinatesCornersUp(self): - # validate the first ring of a corners-up hex gric + # 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)): @@ -318,7 +318,7 @@ def test_getLocalCoordinatesCornersUp(self): self.assertAlmostEqual(minX, -1) def test_getLocalCoordinatesFlatsUp(self): - # validate the first ring of a flats-up hex gric + # 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)): From dc733429b71b389d3cbb6458e1c1d9dbe41f2e26 Mon Sep 17 00:00:00 2001 From: jstilley Date: Fri, 11 Oct 2024 14:01:54 -0700 Subject: [PATCH 06/13] Responding to comments --- armi/reactor/grids/grid.py | 4 ++++ armi/reactor/spentFuelPool.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/armi/reactor/grids/grid.py b/armi/reactor/grids/grid.py index fac584260..3e0f985a6 100644 --- a/armi/reactor/grids/grid.py +++ b/armi/reactor/grids/grid.py @@ -158,6 +158,10 @@ def __setstate__(self, state: Dict): def isAxialOnly(self) -> bool: """Indicate to parts of ARMI if this Grid handles only axial cells.""" + @property + def cornersUp(self) -> bool: + return False + @abstractmethod def __len__(self) -> int: """Number of items in the grid.""" diff --git a/armi/reactor/spentFuelPool.py b/armi/reactor/spentFuelPool.py index d14a16f7b..870036f9c 100644 --- a/armi/reactor/spentFuelPool.py +++ b/armi/reactor/spentFuelPool.py @@ -71,7 +71,7 @@ def add(self, assem, loc=None): loc = self._getNextLocation() # orient the blocks to match this grid - cornerUp = self.spatialGrid._unitSteps[0][1] == 0 + cornerUp = self.spatialGrid.cornersUp assem.orientBlocks(cornerUp) super().add(assem, loc) From 1942ed1688673d7c3a9ce91e751762a8d1f0ae98 Mon Sep 17 00:00:00 2001 From: jstilley Date: Fri, 11 Oct 2024 14:07:29 -0700 Subject: [PATCH 07/13] responding to reviewer: test docstrings --- armi/reactor/grids/tests/test_grids.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/armi/reactor/grids/tests/test_grids.py b/armi/reactor/grids/tests/test_grids.py index fb2764da8..0af5705a2 100644 --- a/armi/reactor/grids/tests/test_grids.py +++ b/armi/reactor/grids/tests/test_grids.py @@ -239,6 +239,7 @@ 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) self.assertAlmostEqual(grid.pitch, 1.0) side = 1.0 / math.sqrt(3) @@ -262,6 +263,7 @@ def test_getCoordinatesFlatsUp(self): 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) @@ -284,7 +286,8 @@ def test_getCoordinatesCornersUp(self): assert_allclose(grid.getCoordinates((1, 0, 0)), iDirection) assert_allclose(grid.getCoordinates((0, 1, 0)), jDirection) - def test_getLocalCoordinates(self): + 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): @@ -298,6 +301,7 @@ def test_getLocalCoordinates(self): 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 = [] @@ -318,6 +322,7 @@ def test_getLocalCoordinatesCornersUp(self): 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 = [] From 3facbc8ec456df4a71309e1e912bd3adfbb377c9 Mon Sep 17 00:00:00 2001 From: jstilley Date: Fri, 11 Oct 2024 14:14:12 -0700 Subject: [PATCH 08/13] Removed unused setting autoGenerateBlockGrids --- armi/settings/fwSettings/globalSettings.py | 10 ---------- doc/release/0.4.rst | 1 + 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/armi/settings/fwSettings/globalSettings.py b/armi/settings/fwSettings/globalSettings.py index 3b1143880..e5ad6122e 100644 --- a/armi/settings/fwSettings/globalSettings.py +++ b/armi/settings/fwSettings/globalSettings.py @@ -38,7 +38,6 @@ CONF_AVAILABILITY_FACTORS = "availabilityFactors" CONF_AXIAL_MESH_REFINEMENT_FACTOR = "axialMeshRefinementFactor" CONF_BETA = "beta" -CONF_BLOCK_AUTO_GRID = "autoGenerateBlockGrids" CONF_BRANCH_VERBOSITY = "branchVerbosity" CONF_BU_GROUPS = "buGroups" CONF_BURN_CHAIN_FILE_NAME = "burnChainFileName" @@ -828,15 +827,6 @@ def defineSettings() -> List[setting.Setting]: "than from the framework." ), ), - # It may make sense to remove this setting when MILs become more stable. - setting.Setting( - CONF_BLOCK_AUTO_GRID, - default=True, - label="Auto-generate Block grids", - description="Should block blueprints attempt to auto-generate a spatial " - "grid upon construction? This feature makes heavy use of multi-index " - "locations, which are not yet universally supported.", - ), setting.Setting( CONF_CYCLES, default=[], diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst index f6da64941..35a2f07c6 100644 --- a/doc/release/0.4.rst +++ b/doc/release/0.4.rst @@ -34,6 +34,7 @@ API Changes #. Removing ``assemblyLists.py`` and the ``AssemblyList`` class. (`PR#1891 `_) #. Removing ``Assembly.rotatePins`` and ``Block.rotatePins``. Prefer ``Assembly.rotate`` and ``Block.rotate``. (`PR#1846 `) +#. Removed unused setting ``autoGenerateBlockGrids``. (`PR#1947 `_) #. TBD Bug Fixes From 37dd62e6785f3a07fceeb32b9de1650f77b47799 Mon Sep 17 00:00:00 2001 From: jstilley Date: Fri, 11 Oct 2024 14:30:54 -0700 Subject: [PATCH 09/13] Anchroring grid to block - per reviewer --- armi/reactor/blocks.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index e69e5ee72..dc78d76bd 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -2356,7 +2356,10 @@ def autoCreateSpatialGrids(self, cornersUp=True): # build the grid, from pitch and orientation grid = grids.HexGrid.fromPitch( - self.getPinPitch(cold=True), numRings=0, cornersUp=cornersUp + self.getPinPitch(cold=True), + numRings=0, + armiObject=self, + cornersUp=cornersUp, ) ringNumber = hexagon.numRingsToHoldNumCells(self.getNumPins()) From 0d55251b6fcf1bae7b505bf8a05f988f964e953e Mon Sep 17 00:00:00 2001 From: jstilley Date: Fri, 11 Oct 2024 15:03:45 -0700 Subject: [PATCH 10/13] Responding to comments - test refactor --- armi/reactor/tests/test_blocks.py | 54 +++++++++++++------------------ 1 file changed, 22 insertions(+), 32 deletions(-) diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index e4e62dcc8..364eedc06 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -2254,18 +2254,9 @@ def setUp(self): def tearDown(self): self.td.__exit__(None, None, None) - def test_validateCornersUp(self): - # load a corners up reactor - _o, r = loadTestReactor( - os.path.join(TEST_ROOT, "smallestTestReactor"), - inputFileName="armiRunSmallest.yaml", - ) - - # grab a pinned fuel block, and verify it is corners up - b = r.core.getFirstBlock(Flags.FUEL) - self.assertTrue(b.spatialGrid.cornersUp) - - # for corners up, the hex centroids should stretch more in X than Y + @staticmethod + def getLocalCoordinatesBlockBounds(b: blocks.HexBlock): + """Call getLocalCoordinates() for every Component in the Block and find the X/Y bounds.""" maxX = -111 minX = 999 maxY = -111 @@ -2274,6 +2265,7 @@ def test_validateCornersUp(self): locs = comp.spatialLocator if not isinstance(locs, grids.MultiIndexLocation): locs = [locs] + for loc in locs: x, y, _ = loc.getLocalCoordinates() if x > maxX: @@ -2286,9 +2278,26 @@ def test_validateCornersUp(self): elif y < minY: minY = y + return minX, maxX, minY, maxY + + def test_validateCornersUp(self): + """Validate the spatial grid for a corners up HexBlock and its children.""" + # load a corners up reactor + _o, r = loadTestReactor( + os.path.join(TEST_ROOT, "smallestTestReactor"), + inputFileName="armiRunSmallest.yaml", + ) + + # grab a pinned fuel block, and verify it is corners up + b = r.core.getFirstBlock(Flags.FUEL) + self.assertTrue(b.spatialGrid.cornersUp) + + # for corners up, the hex centroids should stretch more in X than Y + minX, maxX, minY, maxY = self.getLocalCoordinatesBlockBounds(b) self.assertGreater(maxX - minX, maxY - minY) def test_validateFlatsUp(self): + """Validate the spatial grid for a flats up HexBlock and its children.""" # load a flats up reactor _o, r = loadTestReactor(TEST_ROOT, inputFileName="armiRun.yaml") @@ -2297,26 +2306,7 @@ def test_validateFlatsUp(self): self.assertFalse(b.spatialGrid.cornersUp) # for flats up, the hex centroids should stretch more in Y than X - maxX = -111 - minX = 999 - maxY = -111 - minY = 999 - for comp in b: - locs = comp.spatialLocator - if not isinstance(locs, grids.MultiIndexLocation): - locs = [locs] - for loc in locs: - x, y, _ = loc.getLocalCoordinates() - if x > maxX: - maxX = x - elif x < minX: - minX = x - - if y > maxY: - maxY = y - elif y < minY: - minY = y - + minX, maxX, minY, maxY = self.getLocalCoordinatesBlockBounds(b) self.assertGreater(maxY - minY, maxX - minX) From 7d8ab19d7af8101e0d5360d46afc489fc23d4bcb Mon Sep 17 00:00:00 2001 From: jstilley Date: Mon, 14 Oct 2024 16:39:44 -0700 Subject: [PATCH 11/13] On a hex lattice, sub-hex grids are rotated --- armi/reactor/blocks.py | 24 +++++++++++++++++------- armi/reactor/tests/test_blocks.py | 21 +++++++++++---------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index ec320b178..09f817fdf 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -2356,10 +2356,12 @@ def autoCreateSpatialGrids(self, cornersUp=True): 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 ------ @@ -2385,6 +2387,14 @@ def autoCreateSpatialGrids(self, cornersUp=True): cornersUp=cornersUp, ) + # build the sub-grid, with opposite orientation to the block + subGrid = grids.HexGrid.fromPitch( + self.getPinPitch(cold=True), + numRings=0, + armiObject=self, + cornersUp=not cornersUp, + ) + ringNumber = hexagon.numRingsToHoldNumCells(self.getNumPins()) numLocations = 0 for ring in range(ringNumber): @@ -2398,11 +2408,11 @@ def autoCreateSpatialGrids(self, cornersUp=True): ) # set the spatial position of the sub-block components - spatialLocators = grids.MultiIndexLocation(grid=grid) + spatialLocators = grids.MultiIndexLocation(grid=subGrid) 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]) + for pos in range(subGrid.getPositionsInRing(ring + 1)): + i, j = subGrid.getIndicesFromRingAndPos(ring + 1, pos + 1) + spatialLocators.append(subGrid[i, j, 0]) # finally, fill the spatial grid, and put the sub-block components on it if self.spatialGrid is None: diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index 81772eda8..aecfb2b0d 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -34,9 +34,9 @@ from armi.reactor import blocks, blueprints, components, geometry, grids from armi.reactor.components import basicShapes, complexShapes from armi.reactor.flags import Flags -from armi.reactor.tests.test_reactors import loadTestReactor from armi.reactor.tests.test_assemblies import makeTestAssembly -from armi.reactor.tests.test_reactors import loadTestReactor, TEST_ROOT +from armi.reactor.tests.test_reactors import loadTestReactor +from armi.reactor.tests.test_reactors import TEST_ROOT from armi.tests import ISOAA_PATH from armi.utils import hexagon, units from armi.utils.directoryChangers import TemporaryDirectoryChanger @@ -2092,10 +2092,11 @@ def test_getPinCoords(self): side = hexagon.side(blockPitch) xyz = self.HexBlock.getPinCoordinates() x, y, _z = zip(*xyz) - self.assertAlmostEqual( - y[1], y[2] - ) # first two pins should be side by side on top. - self.assertNotAlmostEqual(x[1], x[2]) + + # these two pins should be side by side on top + self.assertTrue(self.HexBlock.spatialGrid.cornersUp) + self.assertAlmostEqual(y[1], y[3]) + self.assertNotAlmostEqual(x[1], x[3]) self.assertEqual(len(xyz), self.HexBlock.getNumPins()) # ensure all pins are within the proper bounds of a @@ -2326,9 +2327,9 @@ def test_validateCornersUp(self): b = r.core.getFirstBlock(Flags.FUEL) self.assertTrue(b.spatialGrid.cornersUp) - # for corners up, the hex centroids should stretch more in X than Y + # for a flats up sub-grid, the hex centroids should stretch more in Y than X minX, maxX, minY, maxY = self.getLocalCoordinatesBlockBounds(b) - self.assertGreater(maxX - minX, maxY - minY) + self.assertGreater(maxY - minY, maxX - minX) def test_validateFlatsUp(self): """Validate the spatial grid for a flats up HexBlock and its children.""" @@ -2339,9 +2340,9 @@ def test_validateFlatsUp(self): b = r.core.getFirstBlock(Flags.FUEL) self.assertFalse(b.spatialGrid.cornersUp) - # for flats up, the hex centroids should stretch more in Y than X + # for a corners up sub-grid, the hex centroids should stretch more in X than Y minX, maxX, minY, maxY = self.getLocalCoordinatesBlockBounds(b) - self.assertGreater(maxY - minY, maxX - minX) + self.assertGreater(maxX - minX, maxY - minY) class ThRZBlock_TestCase(unittest.TestCase): From e8182dd157cbb29ff8370b60b86fdec88699aefb Mon Sep 17 00:00:00 2001 From: jstilley Date: Tue, 15 Oct 2024 15:25:48 -0700 Subject: [PATCH 12/13] Making unit tests more stable --- armi/reactor/blocks.py | 2 +- armi/reactor/tests/test_blocks.py | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index 09f817fdf..969c7c57e 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -2402,7 +2402,7 @@ def autoCreateSpatialGrids(self, cornersUp=True): 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() ) ) diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index aecfb2b0d..94ec315fc 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -16,7 +16,9 @@ import io import math import os +import shutil import unittest +from glob import glob from unittest.mock import MagicMock, patch import numpy as np @@ -2333,8 +2335,22 @@ def test_validateCornersUp(self): def test_validateFlatsUp(self): """Validate the spatial grid for a flats up HexBlock and its children.""" + # copy the files over + inDir = os.path.join(TEST_ROOT, "smallestTestReactor") + for filePath in glob(os.path.join(inDir, "*.yaml")): + outPath = os.path.join(self.td.destination, os.path.basename(filePath)) + shutil.copyfile(filePath, outPath) + + # modify the reactor to make it flats up + testFile = os.path.join(self.td.destination, "refSmallestReactor.yaml") + txt = open(testFile, "r").read() + txt = txt.replace("geom: hex_corners_up", "geom: hex") + open(testFile, "w").write(txt) + # load a flats up reactor - _o, r = loadTestReactor(TEST_ROOT, inputFileName="armiRun.yaml") + _o, r = loadTestReactor( + self.td.destination, inputFileName="armiRunSmallest.yaml" + ) # grab a pinned fuel block, and verify it is flats up b = r.core.getFirstBlock(Flags.FUEL) From 86516c7e4eda11b8ecd0864674c9d71c1b2a4fea Mon Sep 17 00:00:00 2001 From: jstilley Date: Wed, 16 Oct 2024 11:12:59 -0700 Subject: [PATCH 13/13] Blocks are on same grid as Core --- armi/reactor/tests/test_blocks.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index 94ec315fc..dd9fa1460 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -2328,6 +2328,7 @@ def test_validateCornersUp(self): # grab a pinned fuel block, and verify it is corners up b = r.core.getFirstBlock(Flags.FUEL) self.assertTrue(b.spatialGrid.cornersUp) + self.assertEqual(r.core.spatialGrid.cornersUp, b.spatialGrid.cornersUp) # for a flats up sub-grid, the hex centroids should stretch more in Y than X minX, maxX, minY, maxY = self.getLocalCoordinatesBlockBounds(b) @@ -2355,6 +2356,7 @@ def test_validateFlatsUp(self): # grab a pinned fuel block, and verify it is flats up b = r.core.getFirstBlock(Flags.FUEL) self.assertFalse(b.spatialGrid.cornersUp) + self.assertEqual(r.core.spatialGrid.cornersUp, b.spatialGrid.cornersUp) # for a corners up sub-grid, the hex centroids should stretch more in X than Y minX, maxX, minY, maxY = self.getLocalCoordinatesBlockBounds(b)