def test_getIndexBounds(self): numRings = 5 grid = grids.hexGridFromPitch(1.0, numRings=numRings) boundsIJK = grid.getIndexBounds() self.assertEqual( boundsIJK, ((-numRings, numRings), (-numRings, numRings), (0, 1)) )
def addRing(self, ring, p0=None, p1=None): """ Adds a section of a ring (or a whole ring) to the zone Parameters ---------- ring : int The ring to add p0 : int, optional beginning position within ring. Default: None (full ring) p1 : int, optional Ending position within ring. """ if p0 is None or p1 is None: if self.symmetry == 3: grid = grids.hexGridFromPitch(1.0) posList = grid.allPositionsInThird(ring) elif self.symmetry == 1: posList = range(1, hexagon.numPositionsInRing(ring) + 1) else: raise RuntimeError( "Zones are not written to handle {0}-fold symmetry yet" "".format(self.symmetry)) else: posList = range(p0, p1 + 1) for pos in posList: newLoc = str(locations.HexLocation(ring, pos)) if newLoc not in self.locList: self.append(newLoc)
def growToFullCore(self): """ Convert geometry input to full core. Notes ----- This only works for Hex 1/3rd core geometry inputs. """ if self.symmetry == FULL_CORE: # already full core from geometry file. No need to copy symmetry over. runLog.important( "Detected that full core geometry already exists. Cannot expand." ) return elif self.symmetry != THIRD_CORE + PERIODIC: raise ValueError( "Cannot convert symmetry `{}` to full core, must be {}".format( self.symmetry, THIRD_CORE + PERIODIC ) ) grid = grids.hexGridFromPitch(1.0) # need to cast to a list because we will modify during iteration for (ring, pos), specifierID in list(self.assemTypeByIndices.items()): indices = grids.getIndicesFromRingAndPos(ring, pos) for symmetricI, symmetricJ in grid.getSymmetricIdenticalsThird(indices): symmetricRingPos = grids.indicesToRingPos(symmetricI, symmetricJ) self.assemTypeByIndices[symmetricRingPos] = specifierID self.symmetry = FULL_CORE
def test_isInFirstThird(self): grid = grids.hexGridFromPitch(1.0, numRings=10) self.assertTrue(grid.isInFirstThird(grid[0, 0, 0])) self.assertTrue(grid.isInFirstThird(grid[1, 0, 0])) self.assertTrue(grid.isInFirstThird(grid[3, -1, 0])) self.assertFalse(grid.isInFirstThird(grid[1, -1, 0])) self.assertFalse(grid.isInFirstThird(grid[-1, -1, 0])) self.assertFalse(grid.isInFirstThird(grid[3, -2, 0]))
def _constructSpatialGrid(self): """ Build spatial grid. If you do not enter latticeDimensions, a unit grid will be produced which must be adjusted to the proper dimensions (often by inspection of children) at a later time. """ geom = self.geom maxIndex = self._getMaxIndex() runLog.extra("Creating the spatial grid") if geom in (geometry.RZT, geometry.RZ): if self.gridBounds is None: # This check is regrattably late. It would be nice if we could validate # that bounds are provided if R-Theta mesh is being used. raise InputError( "Grid bounds must be provided for `{}` to specify a grid with " "r-theta components.".format(self.name)) for key in ("theta", "r"): if key not in self.gridBounds: raise InputError( "{} grid bounds were not provided for `{}`.".format( key, self.name)) # convert to list, otherwise it is a CommentedSeq theta = numpy.array(self.gridBounds["theta"]) radii = numpy.array(self.gridBounds["r"]) for l, name in ((theta, "theta"), (radii, "radii")): if not _isMonotonicUnique(l): raise InputError( "Grid bounds for {}:{} is not sorted or contains " "duplicates. Check blueprints.".format( self.name, name)) spatialGrid = grids.ThetaRZGrid(bounds=(theta, radii, (0.0, 0.0))) if geom == geometry.HEX: pitch = self.latticeDimensions.x if self.latticeDimensions else 1.0 # add 2 for potential dummy assems spatialGrid = grids.hexGridFromPitch(pitch, numRings=maxIndex + 2) elif geom == geometry.CARTESIAN: # if full core or not cut-off, bump the first assembly from the center of # the mesh into the positive values. xw, yw = ((self.latticeDimensions.x, self.latticeDimensions.y) if self.latticeDimensions else (1.0, 1.0)) isOffset = (self.symmetry and geometry.THROUGH_CENTER_ASSEMBLY not in self.symmetry) spatialGrid = grids.cartesianGridFromRectangle(xw, yw, numRings=maxIndex, isOffset=isOffset) runLog.debug("Built grid: {}".format(spatialGrid)) # set geometric metadata on spatialGrid. This information is needed in various # parts of the code and is best encapsulated on the grid itself rather than on # the container state. spatialGrid.geomType = self.geom spatialGrid.symmetry = self.symmetry return spatialGrid
def test_is_pickleable(self): grid = grids.hexGridFromPitch(1.0, numRings=3) loc = grid[1, 1, 0] for protocol in range(cPickle.HIGHEST_PROTOCOL + 1): buf = BytesIO() cPickle.dump(loc, buf, protocol=protocol) buf.seek(0) newLoc = cPickle.load(buf) assert_allclose(loc.indices, newLoc.indices)
def test_badIndices(self): grid = grids.hexGridFromPitch(1.0, numRings=3) # this is actually ok because step-defined grids are infinite self.assertEqual(grid.getCoordinates((-100, 2000, 5))[2], 0.0) grid = grids.axialUnitGrid(10) with self.assertRaises(IndexError): grid.getCoordinates((0, 5, -1))
def test_getSymmetricIdenticalsThird(self): grid = grids.hexGridFromPitch(1.0) self.assertEqual(grid.getSymmetricIdenticalsThird((3, -2)), [(-1, 3), (-2, -1)]) self.assertEqual(grid.getSymmetricIdenticalsThird((2, 1)), [(-3, 2), (1, -3)]) symmetrics = grid.getSymmetricIdenticalsThird( grid.getIndicesFromRingAndPos(5, 3) ) self.assertEqual( [(5, 11), (5, 19)], [grid.getRingPos(indices) for indices in symmetrics] )
def getEmptyHexReactor(cs=None): """Make an empty hex reactor used in some tests.""" cs = cs or settings.getMasterCs() bp = blueprints.Blueprints() reactor = reactors.Reactor(cs, bp) reactor.add(reactors.Core("Core", cs)) reactor.core.spatialGrid = grids.hexGridFromPitch(1.0) reactor.core.spatialGrid.symmetry = geometry.THIRD_CORE + geometry.PERIODIC reactor.core.spatialGrid.geomType = geometry.HEX reactor.core.spatialGrid.armiObject = reactor.core return reactor
def getEmptyHexReactor(): """Make an empty hex reactor used in some tests.""" from armi.reactor import blueprints bp = blueprints.Blueprints() reactor = reactors.Reactor("Reactor", bp) reactor.add(reactors.Core("Core")) reactor.core.spatialGrid = grids.hexGridFromPitch(1.0) reactor.core.spatialGrid.symmetry = geometry.THIRD_CORE + geometry.PERIODIC reactor.core.spatialGrid.geomType = geometry.HEX reactor.core.spatialGrid.armiObject = reactor.core return reactor
def test_overlapsWhichSymmetryLine(self): grid = grids.hexGridFromPitch(1.0) self.assertEqual( grid.overlapsWhichSymmetryLine(grid.getIndicesFromRingAndPos(5, 3)), grids.BOUNDARY_60_DEGREES, ) self.assertEqual( grid.overlapsWhichSymmetryLine(grid.getIndicesFromRingAndPos(5, 23)), grids.BOUNDARY_0_DEGREES, ) self.assertEqual( grid.overlapsWhichSymmetryLine(grid.getIndicesFromRingAndPos(3, 4)), grids.BOUNDARY_120_DEGREES, )
def setUp(self): bp = blueprints.Blueprints() r = reactors.Reactor(settings.getMasterCs(), bp) r.add(reactors.Core("Core", settings.getMasterCs())) r.core.spatialGrid = grids.hexGridFromPitch(1.0) r.core.spatialGrid.symmetry = geometry.THIRD_CORE + geometry.PERIODIC r.core.spatialGrid.geomType = geometry.HEX aList = [] for ring in range(10): a = assemblies.HexAssembly("fuel") a.spatialLocator = r.core.spatialGrid[ring, 1, 0] a.parent = r.core aList.append(a) self.aList = aList
def setUp(self): bp = blueprints.Blueprints() geom = geometry.SystemLayoutInput() geom.symmetry = "third core periodic" r = reactors.Reactor(settings.getMasterCs(), bp) r.add(reactors.Core("Core", settings.getMasterCs(), geom)) r.core.spatialGrid = grids.hexGridFromPitch(1.0) aList = [] for ring in range(10): a = assemblies.HexAssembly("fuel") a.spatialLocator = r.core.spatialGrid[ring, 1, 0] a.parent = r.core aList.append(a) self.aList = aList
def test_triangleCoords(self): grid = grids.hexGridFromPitch(8.15) indices1 = grid.getIndicesFromRingAndPos(5, 3) + (0,) indices2 = grid.getIndicesFromRingAndPos(5, 23) + (0,) indices3 = grid.getIndicesFromRingAndPos(3, 4) + (0,) cur = grid.triangleCoords(indices1) ref = [ (16.468_916_428_634_078, 25.808_333_333_333_337), (14.116_214_081_686_351, 27.166_666_666_666_67), (11.763_511_734_738_627, 25.808_333_333_333_337), (11.763_511_734_738_627, 23.091_666_666_666_67), (14.116_214_081_686_351, 21.733_333_333_333_334), (16.468_916_428_634_078, 23.091_666_666_666_67), ] assert_allclose(cur, ref) cur = grids.hexGridFromPitch(2.5).triangleCoords(indices2) ref = [ (9.381_941_874_331_42, 0.416_666_666_666_666_7), (8.660_254_037_844_387, 0.833_333_333_333_333_4), (7.938_566_201_357_355_5, 0.416_666_666_666_666_7), (7.938_566_201_357_355_5, -0.416_666_666_666_666_7), (8.660_254_037_844_387, -0.833_333_333_333_333_4), (9.381_941_874_331_42, -0.416_666_666_666_666_7), ] assert_allclose(cur, ref) cur = grids.hexGridFromPitch(3.14).triangleCoords(indices3) ref = [ (-1.812_879_845_255_425, 5.233_333_333_333_333), (-2.719_319_767_883_137_6, 5.756_666_666_666_667), (-3.625_759_690_510_850_2, 5.233_333_333_333_333), (-3.625_759_690_510_850_2, 4.186_666_666_666_666_5), (-2.719_319_767_883_137_6, 3.663_333_333_333_333), (-1.812_879_845_255_425, 4.186_666_666_666_666_5), ] assert_allclose(cur, ref)
def _constructSpatialGrid(self): """ Build spatial grid. If you do not enter latticeDimensions, a unit grid will be produced which must be adjusted to the proper dimensions (often by inspection of children) at a later time. """ geom = self.geom maxIndex = self._getMaxIndex() runLog.extra("Creating the spatial grid") if geom in [geometry.RZT, geometry.RZ]: # for now, these can only be read in from the old geometry XML files. spatialGrid = self._makeRZGridFromLatticeFile() if geom == geometry.HEX: pitch = self.latticeDimensions.x if self.latticeDimensions else 1.0 # add 2 for potential dummy assems spatialGrid = grids.hexGridFromPitch( pitch, numRings=maxIndex + 2, ) elif geom == geometry.CARTESIAN: # if full core or not cut-off, bump the first assembly from the center of the mesh # into the positive values. xw, yw = ((self.latticeDimensions.x, self.latticeDimensions.y) if self.latticeDimensions else (1.0, 1.0)) isOffset = (self.symmetry and geometry.THROUGH_CENTER_ASSEMBLY not in self.symmetry) spatialGrid = grids.cartesianGridFromRectangle( xw, yw, numRings=maxIndex, isOffset=isOffset, ) runLog.debug("Built grid: {}".format(spatialGrid)) # set geometric metadata on spatialGrid. This information is needed in various # parts of the code and is best encapsulated on the grid itself rather than on # the container state. spatialGrid.geomType = self.geom spatialGrid.symmetry = self.symmetry return spatialGrid
def testPositions(self): grid = grids.hexGridFromPitch(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)), (1.5 * side, 0.5, 0.0)) assert_allclose(grid.getCoordinates((-1, 0, 0)), (-1.5 * side, -0.5, 0.0)) assert_allclose(grid.getCoordinates((0, 1, 0)), (0, 1.0, 0.0)) assert_allclose(grid.getCoordinates((1, -1, 0)), (1.5 * side, -0.5, 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 testRingPosFromIndices(self): """Test conversion from<-->to ring/position based on hand-prepared right answers.""" grid = grids.hexGridFromPitch(1.0) for indices, ringPos in [ ((0, 0), (1, 1)), ((1, 0), (2, 1)), ((0, 1), (2, 2)), ((-1, 1), (2, 3)), ((-1, 0), (2, 4)), ((0, -1), (2, 5)), ((1, -1), (2, 6)), ((1, 1), (3, 2)), ((11, -7), (12, 60)), ((-1, -2), (4, 12)), ((-3, 1), (4, 9)), ((-2, 3), (4, 6)), ((1, 2), (4, 3)), ((2, -4), (5, 19)), ]: self.assertEqual(indices, grid.getIndicesFromRingAndPos(*ringPos)) self.assertEqual(ringPos, grid.getRingPos(indices))
def test_isAxialOnly(self): grid = grids.hexGridFromPitch(1.0, numRings=3) self.assertEqual(grid.isAxialOnly, False) grid2 = grids.axialUnitGrid(10) self.assertEqual(grid2.isAxialOnly, True)
def test_quasiReduce(self): """Make sure our DB-friendly version of reduce works.""" grid = grids.hexGridFromPitch(1.0, numRings=3) reduction = grid.reduce() self.assertAlmostEqual(reduction[0][1][1], 1.0)
def test_adjustPitch(self): grid = grids.hexGridFromPitch(1.0, numRings=3) v1 = grid.getCoordinates((1, 0, 0)) grid.changePitch(2.0) v2 = grid.getCoordinates((1, 0, 0)) assert_allclose(2 * v1, v2)
def testNeighbors(self): grid = grids.hexGridFromPitch(1.0) neighbs = grid.getNeighboringCellIndices(0, 0, 0) self.assertEqual(len(neighbs), 6) self.assertIn((1, -1, 0), neighbs)
def test_buildLocations(self): grid = grids.hexGridFromPitch(1.0, numRings=3) loc1 = grid[1, 2, 0] self.assertEqual(loc1.i, 1) self.assertEqual(loc1.j, 2)
def test_getAllIndices(self): grid = grids.hexGridFromPitch(1.0, numRings=3) indices = grid.getAllIndices() self.assertIn((1, 2, 0), indices)
def test_lookupFactory(self): grid = grids.hexGridFromPitch(1.0, numRings=3) self.assertEqual(grid[10, 5, 0].i, 10)
def testLabel(self): grid = grids.hexGridFromPitch(1.0) indices = grid.getIndicesFromRingAndPos(12, 5) self.assertEqual(grid.getLabel(indices), "B2005") self.assertEqual(grid.getLabel(indices + (5,)), "B2005F")