Ejemplo n.º 1
0
 def test_growToFullCoreFromThirdCore(self):
     """Test that a hex core can be converted from a third core to a full core geometry."""
     # Check the initialization of the third core model
     self.assertFalse(self.r.core.isFullCore)
     self.assertEqual(
         self.r.core.symmetry,
         geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                               geometry.BoundaryType.PERIODIC),
     )
     initialNumBlocks = len(self.r.core.getBlocks())
     # Perform reactor conversion
     changer = geometryConverters.ThirdCoreHexToFullCoreChanger(self.o.cs)
     changer.convert(self.r)
     # Check the full core conversion is successful
     self.assertGreater(len(self.r.core.getBlocks()), initialNumBlocks)
     self.assertEqual(self.r.core.symmetry.domain,
                      geometry.DomainType.FULL_CORE)
     # Check that the geometry can be restored to a third core
     changer.restorePreviousGeometry(self.o.cs, self.r)
     self.assertEqual(initialNumBlocks, len(self.r.core.getBlocks()))
     self.assertEqual(
         self.r.core.symmetry,
         geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                               geometry.BoundaryType.PERIODIC),
     )
Ejemplo n.º 2
0
    def test_checkValidGeomSymmetryCombo(self):
        geomHex = geometry.GeomType.HEX
        geomCart = geometry.GeomType.CARTESIAN
        geomRZT = geometry.GeomType.RZT
        geomRZ = geometry.GeomType.RZ
        fullCore = geometry.SymmetryType(geometry.DomainType.FULL_CORE,
                                         geometry.BoundaryType.NO_SYMMETRY)
        thirdPeriodic = geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                                              geometry.BoundaryType.PERIODIC)
        quarterCartesian = geometry.SymmetryType(
            geometry.DomainType.QUARTER_CORE, geometry.BoundaryType.REFLECTIVE)

        self.assertTrue(
            geometry.checkValidGeomSymmetryCombo(geomHex, thirdPeriodic))
        self.assertTrue(geometry.checkValidGeomSymmetryCombo(
            geomHex, fullCore))
        self.assertTrue(
            geometry.checkValidGeomSymmetryCombo(geomCart, quarterCartesian))
        self.assertTrue(
            geometry.checkValidGeomSymmetryCombo(geomRZT, quarterCartesian))
        self.assertTrue(geometry.checkValidGeomSymmetryCombo(geomRZ, fullCore))

        with self.assertRaises(ValueError):
            _ = geometry.SymmetryType(
                geometry.DomainType.THIRD_CORE,
                geometry.BoundaryType.REFLECTIVE,
                False,
            )
        with self.assertRaises(ValueError):
            geometry.checkValidGeomSymmetryCombo(geomHex, quarterCartesian)

        with self.assertRaises(ValueError):
            geometry.checkValidGeomSymmetryCombo(geomCart, thirdPeriodic)
Ejemplo n.º 3
0
 def testBaseConstructor(self):
     self.assertEqual(
         geometry.SymmetryType(geometry.DomainType.SIXTEENTH_CORE,
                               geometry.BoundaryType.REFLECTIVE).domain,
         geometry.DomainType.SIXTEENTH_CORE,
     )
     self.assertEqual(
         str(
             geometry.SymmetryType(
                 geometry.DomainType.FULL_CORE,
                 geometry.BoundaryType.NO_SYMMETRY).boundary),
         "",
     )
Ejemplo n.º 4
0
 def testSymmetryFactor(self):
     st = geometry.SymmetryType(geometry.DomainType.FULL_CORE,
                                geometry.BoundaryType.NO_SYMMETRY)
     self.assertEqual(st.symmetryFactor(), 1.0)
     st = geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                                geometry.BoundaryType.PERIODIC)
     self.assertEqual(st.symmetryFactor(), 3.0)
     st = geometry.SymmetryType(geometry.DomainType.QUARTER_CORE,
                                geometry.BoundaryType.REFLECTIVE)
     self.assertEqual(st.symmetryFactor(), 4.0)
     st = geometry.SymmetryType(geometry.DomainType.EIGHTH_CORE,
                                geometry.BoundaryType.REFLECTIVE)
     self.assertEqual(st.symmetryFactor(), 8.0)
     st = geometry.SymmetryType(geometry.DomainType.SIXTEENTH_CORE,
                                geometry.BoundaryType.REFLECTIVE)
     self.assertEqual(st.symmetryFactor(), 16.0)
Ejemplo n.º 5
0
 def testReadReactor(self):
     reactor = test_reactors.buildOperatorOfEmptyHexBlocks().r
     reactor.core.symmetry = geometry.SymmetryType(
         geometry.DomainType.THIRD_CORE, geometry.BoundaryType.PERIODIC)
     geom = SystemLayoutInput.fromReactor(reactor)
     self.assertEqual(geom.assemTypeByIndices[(2, 1)], "fuel")
     self.assertEqual(str(geom.geomType), geometry.HEX)
Ejemplo n.º 6
0
    def __init__(
        self,
        name=None,
        geom=geometry.HEX,
        latticeMap=None,
        symmetry=str(
            geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                                  geometry.BoundaryType.PERIODIC)),
        gridContents=None,
        gridBounds=None,
    ):
        """
        A Grid blueprint.

        Notes
        -----
        yamlize does not call an __init__ method, instead it uses __new__ and setattr
        this is only needed for when you want to make this object from a non-YAML
        source.

        .. warning:: This is a Yamlize object, so ``__init__`` never really gets called.
        Only ``__new__`` does.

        """
        self.name = name
        self.geom = str(geom)
        self.latticeMap = latticeMap
        self.symmetry = str(symmetry)
        self.gridContents = gridContents
        self.gridBounds = gridBounds
Ejemplo n.º 7
0
    def expandToFull(self):
        """
        Unfold the blueprints to represent full symmetry.

        .. note:: This relatively rudimentary, and copies entries from the
            currently-represented domain to their corresponding locations in full
            symmetry.  This may not produce the desired behavior for some scenarios,
            such as when expanding fuel shuffling paths or the like. Future work may
            make this more sophisticated.
        """
        if (geometry.SymmetryType.fromAny(
                self.symmetry).domain == geometry.DomainType.FULL_CORE):
            # No need!
            return

        grid = self.construct()

        newContents = copy.copy(self.gridContents)
        for idx, contents in self.gridContents.items():
            equivs = grid.getSymmetricEquivalents(idx)
            for idx2 in equivs:
                newContents[idx2] = contents
        self.gridContents = newContents
        split = geometry.THROUGH_CENTER_ASSEMBLY in self.symmetry
        self.symmetry = str(
            geometry.SymmetryType(
                geometry.DomainType.FULL_CORE,
                geometry.BoundaryType.NO_SYMMETRY,
                throughCenterAssembly=split,
            ))
Ejemplo n.º 8
0
    def growToFullCore(self):
        """
        Convert geometry input to full core.

        Notes
        -----
        This only works for Hex 1/3rd core geometry inputs.
        """
        if self.symmetry.domain == geometry.DomainType.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.domain != geometry.DomainType.THIRD_CORE
            or self.symmetry.boundary != geometry.BoundaryType.PERIODIC
        ):
            raise ValueError(
                "Cannot convert shape `{}` to full core, must be {}".format(
                    self.symmetry.domain,
                    str(
                        geometry.SymmetryType(
                            geometry.DomainType.THIRD_CORE,
                            geometry.BoundaryType.PERIODIC,
                        )
                    ),
                ),
            )

        grid = grids.HexGrid.fromPitch(1.0)
        grid._symmetry: str = str(self.symmetry)

        # need to cast to a list because we will modify during iteration
        for (ring, pos), specifierID in list(self.assemTypeByIndices.items()):
            indices = grids.HexGrid.getIndicesFromRingAndPos(ring, pos)
            for symmetricI, symmetricJ in grid.getSymmetricEquivalents(indices):
                symmetricRingPos = grids.HexGrid.indicesToRingPos(
                    symmetricI, symmetricJ
                )
                self.assemTypeByIndices[symmetricRingPos] = specifierID

        self.symmetry = geometry.SymmetryType(
            geometry.DomainType.FULL_CORE,
            geometry.BoundaryType.NO_SYMMETRY,
        )
Ejemplo n.º 9
0
 def testLabel(self):
     st = geometry.SymmetryType(geometry.DomainType.FULL_CORE,
                                geometry.BoundaryType.NO_SYMMETRY)
     self.assertEqual(st.domain.label, "Full")
     self.assertEqual(st.boundary.label, "No Symmetry")
     st = geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                                geometry.BoundaryType.PERIODIC)
     self.assertEqual(st.domain.label, "Third")
     self.assertEqual(st.boundary.label, "Periodic")
     st = geometry.SymmetryType(geometry.DomainType.QUARTER_CORE,
                                geometry.BoundaryType.REFLECTIVE)
     self.assertEqual(st.domain.label, "Quarter")
     self.assertEqual(st.boundary.label, "Reflective")
     st = geometry.SymmetryType(geometry.DomainType.EIGHTH_CORE,
                                geometry.BoundaryType.REFLECTIVE)
     self.assertEqual(st.domain.label, "Eighth")
     st = geometry.SymmetryType(geometry.DomainType.SIXTEENTH_CORE,
                                geometry.BoundaryType.REFLECTIVE)
     self.assertEqual(st.domain.label, "Sixteenth")
Ejemplo n.º 10
0
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.HexGrid.fromPitch(1.0)
    reactor.core.spatialGrid.symmetry = geometry.SymmetryType(
        geometry.DomainType.THIRD_CORE, geometry.BoundaryType.PERIODIC)
    reactor.core.spatialGrid.geomType = geometry.HEX
    reactor.core.spatialGrid.armiObject = reactor.core
    return reactor
Ejemplo n.º 11
0
    def test_getSymmetricIdenticalsThird(self):
        grid = grids.HexGrid.fromPitch(1.0)
        grid.symmetry = str(
            geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                                  geometry.BoundaryType.PERIODIC))
        self.assertEqual(grid.getSymmetricEquivalents((3, -2)), [(-1, 3),
                                                                 (-2, -1)])
        self.assertEqual(grid.getSymmetricEquivalents((2, 1)), [(-3, 2),
                                                                (1, -3)])

        symmetrics = grid.getSymmetricEquivalents(
            grid.getIndicesFromRingAndPos(5, 3))
        self.assertEqual([(5, 11), (5, 19)],
                         [grid.getRingPos(indices) for indices in symmetrics])
Ejemplo n.º 12
0
 def setUp(self):
     bp = blueprints.Blueprints()
     r = reactors.Reactor("zonetest", bp)
     r.add(reactors.Core("Core"))
     r.core.spatialGrid = grids.HexGrid.fromPitch(1.0)
     r.core.spatialGrid.symmetry = geometry.SymmetryType(
         geometry.DomainType.THIRD_CORE, geometry.BoundaryType.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
Ejemplo n.º 13
0
def getEmptyCartesianReactor(pitch=(10.0, 16.0)):
    """Return an empty Cartesian 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.CartesianGrid.fromRectangle(*pitch)
    reactor.core.spatialGrid.symmetry = geometry.SymmetryType(
        geometry.DomainType.QUARTER_CORE,
        geometry.BoundaryType.REFLECTIVE,
        throughCenterAssembly=True,
    )
    reactor.core.spatialGrid.geomType = geometry.CARTESIAN
    reactor.core.spatialGrid.armiObject = reactor.core
    return reactor
Ejemplo n.º 14
0
def createDummyReactor():
    """
    Create a dummy reactor with a single fuel assembly and a single fuel block.

    Often, a reactor model like this is built directly from input files rather
    than from code as done here.
    """
    bp = blueprints.Blueprints()
    cs = settings.Settings()

    r = reactors.Reactor("Reactor", bp)
    r.add(reactors.Core("Core"))
    r.core.spatialGrid = grids.HexGrid.fromPitch(1.0)
    r.core.spatialGrid.symmetry = geometry.SymmetryType(
        geometry.DomainType.THIRD_CORE, geometry.BoundaryType.PERIODIC)
    r.core.spatialGrid.geomType = geometry.GeomType.HEX
    r.core.spatialGrid.armiObject = r.core
    r.core.setOptionsFromCs(cs)

    # Create a single fuel assembly
    a = assemblies.HexAssembly("fuel assembly")
    a.spatialGrid = grids.axialUnitGrid(1)
    a.spatialLocator = r.core.spatialGrid[1, 0, 0]

    # Create a single fuel block
    b = blocks.HexBlock("fuel block")
    b.setType("fuel")

    # Create a single fuel component with UZr fuel.
    dims = {"Tinput": 20, "Thot": 900, "id": 0.0, "od": 2.9, "mult": 7}
    c = Circle("fuel", uZr.UZr(), **dims)
    b.add(c)

    # Create a single structure component with HT9.
    dims = {"Tinput": 20, "Thot": 600, "op": 16.0, "ip": 15.0, "mult": 1}
    c = Hexagon("structure", ht9.HT9(), **dims)
    b.add(c)

    # Fill in the rest of the block with sodium coolant.
    dims = {"Tinput": 600, "Thot": 600}
    c = DerivedShape("coolant", sodium.Sodium(), **dims)
    b.add(c)

    a.add(b)
    r.core.add(a)
    _addFlux(b)
    return r
Ejemplo n.º 15
0
    def testFromAny(self):
        st = geometry.SymmetryType.fromAny(
            "eighth reflective through center assembly")
        self.assertTrue(st.isThroughCenterAssembly)
        self.assertEqual(st.domain, geometry.DomainType.EIGHTH_CORE)
        self.assertEqual(st.boundary, geometry.BoundaryType.REFLECTIVE)

        st = geometry.SymmetryType(geometry.DomainType.EIGHTH_CORE,
                                   geometry.BoundaryType.REFLECTIVE, True)
        self.assertTrue(st.isThroughCenterAssembly)
        self.assertEqual(st.domain, geometry.DomainType.EIGHTH_CORE)
        self.assertEqual(st.boundary, geometry.BoundaryType.REFLECTIVE)

        newST = geometry.SymmetryType.fromAny(st)
        self.assertTrue(newST.isThroughCenterAssembly)
        self.assertEqual(newST.domain, geometry.DomainType.EIGHTH_CORE)
        self.assertEqual(newST.boundary, geometry.BoundaryType.REFLECTIVE)
Ejemplo n.º 16
0
 def _getGeomTypeAndSymmetryFromXml(self, root):
     """Read the geometry type and symmetry."""
     try:
         self.geomType = geometry.GeomType.fromStr(
             str(root.attrib[INP_GEOM]).lower())
     except ValueError:
         # will not execute if the geom was specified as thetarz, cartesian or anything else specific
         runLog.warning(
             "Could not find geometry type. Assuming hex geometry with third core periodic symmetry."
         )
         self.geomType = geometry.GeomType.HEX
         self.symmetry = geometry.SymmetryType(
             geometry.DomainType.THIRD_CORE,
             geometry.BoundaryType.PERIODIC,
         )
     else:
         inputString = str(root.attrib[INP_SYMMETRY]).lower()
         self.symmetry = geometry.SymmetryType.fromStr(inputString)
Ejemplo n.º 17
0
 def test_skipGrowToFullCoreWhenAlreadyFullCore(self):
     """Test that hex core is not modified when third core to full core changer is called on an already full core geometry."""
     # Check the initialization of the third core model and convert to a full core
     self.assertFalse(self.r.core.isFullCore)
     self.assertEqual(
         self.r.core.symmetry,
         geometry.SymmetryType(
             geometry.DomainType.THIRD_CORE, geometry.BoundaryType.PERIODIC
         ),
     )
     changer = geometryConverters.ThirdCoreHexToFullCoreChanger(self.o.cs)
     changer.convert(self.r)
     # Check that the changer does not affect the full core model on converting and restoring
     initialNumBlocks = len(self.r.core.getBlocks())
     self.assertEqual(self.r.core.symmetry.domain, geometry.DomainType.FULL_CORE)
     changer = geometryConverters.ThirdCoreHexToFullCoreChanger(self.o.cs)
     changer.convert(self.r)
     self.assertEqual(self.r.core.symmetry.domain, geometry.DomainType.FULL_CORE)
     self.assertEqual(initialNumBlocks, len(self.r.core.getBlocks()))
     changer.restorePreviousGeometry(self.o.cs, self.r)
     self.assertEqual(initialNumBlocks, len(self.r.core.getBlocks()))
     self.assertEqual(self.r.core.symmetry.domain, geometry.DomainType.FULL_CORE)
Ejemplo n.º 18
0
class GridBlueprint(yamlize.Object):
    """
    A grid input blueprint.

    These directly build Grid objects and contain information about
    how to populate the Grid with child ArmiObjects for the Reactor Model.

    The grids get origins either from a parent block (for pin lattices)
    or from a System (for Cores, SFPs, and other components).

    Attributes
    ----------
    name : str
        The grid name
    geom : str
        The geometry of the grid (e.g. 'cartesian')
    latticeMap : str
        An asciimap representation of the lattice contents
    latticeDimensions : Triplet
        An x/y/z Triplet with grid dimensions in cm. This is used to specify a uniform
        grid, such as Cartesian or Hex. Mutually exclusive with gridBounds.
    gridBounds : dict
        A dictionary containing explicit grid boundaries. Specific keys used will depend
        on the type of grid being defined. Mutually exclusive with latticeDimensions.
    symmetry : str
        A string defining the symmetry mode of the grid
    gridContents : dict
        A {(i,j): str} dictionary mapping spatialGrid indices
        in 2-D to string specifiers of what's supposed to be in the grid.

    """

    name = yamlize.Attribute(key="name", type=str)
    geom = yamlize.Attribute(key="geom", type=str, default=geometry.HEX)
    latticeMap = yamlize.Attribute(key="lattice map", type=str, default=None)
    latticeDimensions = yamlize.Attribute(key="lattice pitch",
                                          type=Triplet,
                                          default=None)
    gridBounds = yamlize.Attribute(key="grid bounds", type=dict, default=None)
    symmetry = yamlize.Attribute(
        key="symmetry",
        type=str,
        default=str(
            geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                                  geometry.BoundaryType.PERIODIC)),
    )
    # gridContents is the final form of grid contents information;
    # it is set regardless of how the input is read. This is how all
    # grid contents information is written out.
    gridContents = yamlize.Attribute(key="grid contents",
                                     type=dict,
                                     default=None)

    @gridContents.validator
    def gridContents(self, value):  # pylint: disable=method-hidden
        if value is None:
            return True
        if not all(isinstance(key, tuple) for key in value.keys()):
            raise InputError(
                "Keys need to be presented as [i, j]. Check the blueprints.")

    def __init__(
        self,
        name=None,
        geom=geometry.HEX,
        latticeMap=None,
        symmetry=str(
            geometry.SymmetryType(geometry.DomainType.THIRD_CORE,
                                  geometry.BoundaryType.PERIODIC)),
        gridContents=None,
        gridBounds=None,
    ):
        """
        A Grid blueprint.

        Notes
        -----
        yamlize does not call an __init__ method, instead it uses __new__ and setattr
        this is only needed for when you want to make this object from a non-YAML
        source.

        .. warning:: This is a Yamlize object, so ``__init__`` never really gets called.
        Only ``__new__`` does.

        """
        self.name = name
        self.geom = str(geom)
        self.latticeMap = latticeMap
        self.symmetry = str(symmetry)
        self.gridContents = gridContents
        self.gridBounds = gridBounds

    def construct(self):
        """Build a Grid from a grid definition."""
        self._readGridContents()
        grid = self._constructSpatialGrid()
        return grid

    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 in (geometry.HEX, geometry.HEX_CORNERS_UP):
            pitch = self.latticeDimensions.x if self.latticeDimensions else 1.0
            # add 2 for potential dummy assems
            spatialGrid = grids.HexGrid.fromPitch(
                pitch,
                numRings=maxIndex + 2,
                pointedEndUp=geom == geometry.HEX_CORNERS_UP,
            )
        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.CartesianGrid.fromRectangle(xw,
                                                            yw,
                                                            numRings=maxIndex +
                                                            1,
                                                            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: str = str(self.geom)
        spatialGrid._symmetry: str = str(self.symmetry)
        return spatialGrid

    def _getMaxIndex(self):
        """
        Find the max index in the grid contents.

        Used to limit the size of the spatialGrid. Used to be
        called maxNumRings.
        """
        if self.gridContents:
            return max(itertools.chain(*zip(*self.gridContents.keys())))
        else:
            return 6

    def expandToFull(self):
        """
        Unfold the blueprints to represent full symmetry.

        .. note:: This relatively rudimentary, and copies entries from the
            currently-represented domain to their corresponding locations in full
            symmetry.  This may not produce the desired behavior for some scenarios,
            such as when expanding fuel shuffling paths or the like. Future work may
            make this more sophisticated.
        """
        if (geometry.SymmetryType.fromAny(
                self.symmetry).domain == geometry.DomainType.FULL_CORE):
            # No need!
            return

        grid = self.construct()

        newContents = copy.copy(self.gridContents)
        for idx, contents in self.gridContents.items():
            equivs = grid.getSymmetricEquivalents(idx)
            for idx2 in equivs:
                newContents[idx2] = contents
        self.gridContents = newContents
        split = geometry.THROUGH_CENTER_ASSEMBLY in self.symmetry
        self.symmetry = str(
            geometry.SymmetryType(
                geometry.DomainType.FULL_CORE,
                geometry.BoundaryType.NO_SYMMETRY,
                throughCenterAssembly=split,
            ))

    def _readGridContents(self):
        """
        Read the specifiers as a function of grid position.

        The contents can either be provided as:

        * A dict mapping indices to specifiers (default output of this)
        * An asciimap

        The output will always be stored in ``self.gridContents``.
        """
        if self.gridContents:
            return
        elif self.latticeMap:
            self._readGridContentsLattice()

        if self.gridContents is None:
            # Make sure we have at least something; clients shouldn't have to worry
            # about whether gridContents exist at all.
            self.gridContents = dict()

    def _readGridContentsLattice(self):
        """Read an ascii map of grid contents.

        This update the gridContents attribute, which is a dict mapping grid i,j,k
        indices to textual specifiers (e.g. ``IC``))
        """
        latticeCls = asciimaps.asciiMapFromGeomAndSym(self.geom, self.symmetry)
        asciimap = latticeCls()
        asciimap.readAscii(self.latticeMap)
        self.gridContents = dict()

        for (i, j), spec in asciimap.items():
            if spec == "-":
                # skip placeholders
                continue
            self.gridContents[i, j] = spec

    def getLocators(self, spatialGrid: grids.Grid, latticeIDs: list):
        """
        Return spatialLocators in grid corresponding to lattice IDs.

        This requires a fully-populated ``gridContents`` attribute.
        """
        if latticeIDs is None:
            return []
        if self.gridContents is None:
            return []
        # tried using yamlize to coerce ints to strings but failed
        # after much struggle, so we just auto-convert here to deal
        # with int-like specifications.
        # (yamlize.StrList fails to coerce when ints are provided)
        latticeIDs = [str(i) for i in latticeIDs]
        locators = []
        for (i, j), spec in self.gridContents.items():
            locator = spatialGrid[i, j, 0]
            if spec in latticeIDs:
                locators.append(locator)
        return locators

    def getMultiLocator(self, spatialGrid, latticeIDs):
        """Create a MultiIndexLocation based on lattice IDs."""
        spatialLocator = grids.MultiIndexLocation(grid=spatialGrid)
        spatialLocator.extend(self.getLocators(spatialGrid, latticeIDs))
        return spatialLocator
Ejemplo n.º 19
0
    def setUp(self):
        self.name = "A0015"
        self.assemNum = 15
        self.height = 10
        self.cs = settings.getMasterCs()
        # Print nothing to the screen that would normally go to the log.
        runLog.setVerbosity("error")

        self.r = tests.getEmptyHexReactor()
        self.r.core.symmetry = geometry.SymmetryType(
            geometry.DomainType.THIRD_CORE, geometry.BoundaryType.PERIODIC)

        self.assembly = makeTestAssembly(NUM_BLOCKS, self.assemNum, r=self.r)
        self.r.core.add(self.assembly)

        # Use these if they are needed
        self.blockParams = {
            "height": self.height,
            "avgFuelTemp": 873.0,
            "bondRemoved": 0.0,
            "bu": 15.1,
            "buGroupNum": 0,
            "buLimit": 35,
            "buRate": 0.0,
            "eqRegion": -1,
            "id": 212.0,
            "pdens": 10.0,
            "percentBu": 25.3,
            "power": 100000.0,
            "residence": 4.0,
            "smearDensity": 0.6996721711791459,
            "timeToLimit": 2.7e5,
            "xsTypeNum": 40,
            "zbottom": 97.3521,
            "ztop": 111.80279999999999,
        }

        self.blockSettings = {
            "axMesh": 1,
            "baseBu": 0.0,
            "basePBu": 0.0,
            "bondBOL": 0.0028698019026172574,
            "buGroup": "A",
            "height": 14.4507,
            "molesHmAtBOL": 65.8572895758245,
            "nHMAtBOL": 0.011241485251783766,
            "nPins": 169.0,
            "name": "B0011F",
            "newDPA": 0.0,
            "pitch": 16.79,
            "regName": False,
            "topIndex": 5,
            "tsIndex": 0,
            "type": "igniter fuel",
            "xsType": "C",
            "z": 104.57745,
        }
        # add some blocks with a component
        self.blockList = []
        for i in range(NUM_BLOCKS):
            b = blocks.HexBlock("TestHexBlock")
            b.setHeight(self.height)

            self.hexDims = {
                "Tinput": 273.0,
                "Thot": 273.0,
                "op": 0.76,
                "ip": 0.0,
                "mult": 1.0,
            }
            h = components.Hexagon("fuel", "UZr", **self.hexDims)

            # non-flaggy name important for testing
            b.setType("igniter fuel unitst")
            b.add(h)
            b.parent = self.assembly
            b.setName(b.makeName(self.assembly.getNum(), i))
            self.assembly.add(b)
            self.blockList.append(b)

        self.assembly.calculateZCoords()
Ejemplo n.º 20
0
    def testSymmetry(self):
        # PERIODIC, no split
        grid = grids.CartesianGrid.fromRectangle(
            1.0,
            1.0,
            symmetry=str(
                geometry.SymmetryType(geometry.DomainType.QUARTER_CORE,
                                      geometry.BoundaryType.PERIODIC)),
        )

        expected = {
            (0, 0): {(-1, 0), (-1, -1), (0, -1)},
            (1, 0): {(-1, 1), (-2, -1), (0, -2)},
            (2, 1): {(-2, 2), (-3, -2), (1, -3)},
            (2, 2): {(-3, 2), (-3, -3), (2, -3)},
            (0, 1): {(-2, 0), (-1, -2), (1, -1)},
            (-2, 2): {(-3, -2), (1, -3), (2, 1)},
        }

        for idx, expectedEq in expected.items():
            equivalents = {i for i in grid.getSymmetricEquivalents(idx)}

            self.assertEqual(expectedEq, equivalents)

        # PERIODIC, split
        grid = grids.CartesianGrid.fromRectangle(
            1.0,
            1.0,
            symmetry=geometry.SymmetryType(
                geometry.DomainType.QUARTER_CORE,
                geometry.BoundaryType.PERIODIC,
                throughCenterAssembly=True,
            ),
        )

        expected = {
            (0, 0): set(),
            (1, 0): {(0, 1), (-1, 0), (0, -1)},
            (2, 2): {(-2, 2), (-2, -2), (2, -2)},
            (2, 1): {(-1, 2), (-2, -1), (1, -2)},
            (-1, 3): {(-3, -1), (1, -3), (3, 1)},
            (0, 2): {(-2, 0), (0, -2), (2, 0)},
        }

        for idx, expectedEq in expected.items():
            equivalents = {i for i in grid.getSymmetricEquivalents(idx)}

            self.assertEqual(expectedEq, equivalents)

        # REFLECTIVE, no split
        grid = grids.CartesianGrid.fromRectangle(
            1.0,
            1.0,
            symmetry=geometry.SymmetryType(geometry.DomainType.QUARTER_CORE,
                                           geometry.BoundaryType.REFLECTIVE),
        )

        expected = {
            (0, 0): {(-1, 0), (-1, -1), (0, -1)},
            (1, 0): {(-2, 0), (-2, -1), (1, -1)},
            (-2, 2): {(-2, -3), (1, -3), (1, 2)},
        }

        for idx, expectedEq in expected.items():
            equivalents = {i for i in grid.getSymmetricEquivalents(idx)}

            self.assertEqual(expectedEq, equivalents)

        # REFLECTIVE, split
        grid = grids.CartesianGrid.fromRectangle(
            1.0,
            1.0,
            symmetry=geometry.SymmetryType(
                geometry.DomainType.QUARTER_CORE,
                geometry.BoundaryType.REFLECTIVE,
                throughCenterAssembly=True,
            ),
        )

        expected = {
            (0, 0): set(),
            (1, 0): {(-1, 0)},
            (-1, 2): {(-1, -2), (1, -2), (1, 2)},
            (-2, 0): {(2, 0)},
            (0, -2): {(0, 2)},
        }

        for idx, expectedEq in expected.items():
            equivalents = {i for i in grid.getSymmetricEquivalents(idx)}

            self.assertEqual(expectedEq, equivalents)

        # Full core
        grid = grids.CartesianGrid.fromRectangle(
            1.0,
            1.0,
            symmetry=geometry.FULL_CORE,
        )
        self.assertEqual(grid.getSymmetricEquivalents((5, 6)), [])

        # 1/8 core not supported yet
        grid = grids.CartesianGrid.fromRectangle(
            1.0,
            1.0,
            symmetry=geometry.SymmetryType(
                geometry.DomainType.EIGHTH_CORE,
                geometry.BoundaryType.REFLECTIVE,
            ),
        )
        with self.assertRaises(NotImplementedError):
            grid.getSymmetricEquivalents((5, 6))