Example #1
0
 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
Example #2
0
 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
Example #3
0
    def _updateMassFractionsFromParamValues(reactor, blockParamNames,
                                            blockList):
        """
        Set the block densities based on the already-updated n block-params.

        The DB reads in params that represent the nuclide densities on each block,
        but they cannot be applied to the component until the temperatures are updated.

        """
        runLog.info("Updating component mass fractions from DB params")
        # Set all number densities on a block at a time so we don't have to compute volume fractions N times.
        allNucNamesInProblem = set(reactor.blueprints.allNuclidesInProblem)
        allNucBasesInProblem = {
            nuclideBases.byName[nucName]
            for nucName in allNucNamesInProblem
        }
        nucBasesInBlockParams = {
            nb
            for nb in allNucBasesInProblem
            if nb.getDatabaseName() in blockParamNames
        }

        if settings.getMasterCs()["zeroOutNuclidesNotInDB"]:
            nucBasesNotInBlockParams = allNucBasesInProblem - nucBasesInBlockParams
            zeroOut = {
                nb.getDatabaseName(): 0.0
                for nb in nucBasesNotInBlockParams
            }
            if zeroOut:
                runLog.important(
                    "Zeroing out {0} because they are not in the db.".format(
                        nucBasesNotInBlockParams))
        else:
            zeroOut = {}

        for b in blockList:
            ndens = {
                nuc.name: b.p[nuc.getDatabaseName()]
                for nuc in nucBasesInBlockParams
            }
            ndens.update(zeroOut)
            # apply all non-zero number densities no matter what.
            # zero it out if it was already there and is now set to zero.
            ndens = {
                name: val
                for name, val in ndens.items()
                if val or name in set(b.getNuclides())
            }
            b.setNumberDensities(ndens)

        allNucsNamesInDB = {
            nuclideBases.nucNameFromDBName(paramName)
            for paramName in blockParamNames.intersection(
                nuclideBases.byDBName.keys())
        }
        nucNamesInDataBaseButNotProblem = allNucsNamesInDB - allNucNamesInProblem
        for nucName in nucNamesInDataBaseButNotProblem:
            runLog.warning(
                "Nuclide {0} exists in the database but not the problem. It is being ignored"
                "".format(nucName))
Example #4
0
    def _resetWorker(self):
        """
        Clear out the reactor on the workers to start anew.

        Notes
        -----
        This was made to help minimize the amount of RAM that is used during some
        gigantic long-running cases. Resetting after building copies of reactors
        or transforming their geometry is one approach. We hope to implement
        more efficient solutions in the future.

        .. warning:: This should build empty non-core systems too.
        """

        xsGroups = self.getInterface("xsGroups")
        if xsGroups:
            xsGroups.clearRepresentativeBlocks()
        cs = settings.getMasterCs()
        bp = self.r.blueprints
        spatialGrid = self.r.core.spatialGrid
        self.detach()
        self.r = reactors.Reactor(cs.caseTitle, bp)
        core = reactors.Core("Core")
        self.r.add(core)
        core.spatialGrid = spatialGrid
        self.reattach(self.r, cs)
Example #5
0
    def writeToDB(self, reactor, statePointName=None):
        """
        Puts self.r in the database.

        Parameters
        ----------
        statePointName: str, optional
            explicit name of the state point to be written. A state point is not
            necessarily a cycle or time node, it may make the most sense to simply think
            of it as a label for the current state.
        """
        if self._initDatabaseContact:
            self._createDBSchema(reactor)
            self._initDatabaseContact = False

        if statePointName:
            statePointName = statePointName
        else:
            # check for None instead of truth since these may be 0
            cycle = reactor.p.cycle
            node = reactor.p.timeNode
            statePointName = utils.getTimeStepNum(cycle, node, settings.getMasterCs())

        self._writeReactorParams(reactor, statePointName)
        self._writeAssemblyParams(reactor, statePointName)
        self._writeBlockParams(reactor, statePointName)
        self._writeComponentParams(reactor, statePointName)

        self._numTimeSteps = -1  # update numTimeSteps attribute
Example #6
0
    def __init__(self, r, cs):
        r"""
        Construct an interface.

        The ``r`` and ``cs`` arguments are required, but may be ``None``, where
        appropriate for the specific ``Interface`` implementation.

        Parameters
        ----------
        r : Reactor
            A reactor to attach to
        cs : Settings
            Settings object to use

        Raises
        ------
        RuntimeError
            Interfaces derived from Interface must define their name
        """
        if self.name is None:
            raise RuntimeError("Interfaces derived from Interface must define "
                               "their name ({}).".format(type(self).__name__))
        self._enabled = True
        self.reverseAtEOL = False
        self._bolForce = False  # override disabled flag in interactBOL if true.
        self.cs = settings.getMasterCs() if cs is None else cs
        self.r = r
        self.o = r.o if r else None
Example #7
0
def buildOperatorOfEmptyHexBlocks(customSettings=None):
    """
    Builds a operator w/ a reactor object with some hex assemblies and blocks, but all are empty

    Doesn't depend on inputs and loads quickly.

    Params
    ------
    customSettings : dict
        Dictionary of off-default settings to update
    """
    settings.setMasterCs(None)  # clear
    cs = settings.getMasterCs()  # fetch new
    cs["db"] = False  # stop use of database
    if customSettings is not None:
        cs.update(customSettings)
    r = tests.getEmptyHexReactor()
    r.core.setOptionsFromCs(cs)
    o = operators.Operator(cs)
    o.initializeInterfaces(r)

    a = assemblies.HexAssembly("fuel")
    a.spatialGrid = grids.axialUnitGrid(1)
    b = blocks.HexBlock("TestBlock")
    b.setType("fuel")
    dims = {"Tinput": 600, "Thot": 600, "op": 16.0, "ip": 1, "mult": 1}
    c = Hexagon("fuel", uZr.UZr(), **dims)
    b.add(c)
    a.add(b)
    a.spatialLocator = r.core.spatialGrid[1, 0, 0]
    o.r.core.add(a)
    return o
 def setUp(self):
     self.o, self.r = loadTestReactor(TEST_ROOT)
     self.cs = settings.getMasterCs()
     runLog.setVerbosity("extra")
     self._expandReactor = False
     self._massScaleFactor = 1.0
     if not self._expandReactor:
         self._massScaleFactor = 3.0
Example #9
0
 def setUp(self):
     self.o, self.r = loadTestReactor(TEST_ROOT, {"circularRingMode": True})
     self.cs = settings.getMasterCs()
     runLog.setVerbosity("info")
     self._expandReactor = False
     self._massScaleFactor = 1.0
     if not self._expandReactor:
         self._massScaleFactor = 3.0
Example #10
0
 def __init__(self, r=None, externalCodeInterface=None, fName=None):
     self.externalCodeInterface = externalCodeInterface
     self.eci = self.externalCodeInterface
     self.r = r
     self.cs = settings.getMasterCs()
     if fName:
         self.output = textProcessors.TextProcessor(fName)
     else:
         self.output = None
     self.fName = fName
Example #11
0
def xsHistoryVsTime(reactor):
    r"""
    Plot cross section history vs. time.

    Parameters
    ----------
    reactor : armi.reactor.reactors object

    """
    history = reactor.o.getInterface("history")
    if not history or not history.xsHistory:
        return
    colors = itertools.cycle(["b", "g", "r", "c", "m", "y", "k"])
    plt.figure()
    maxbu = 0.0
    for typeNum, dataList in history.xsHistory.items():
        times = [d[0] for d in dataList]
        burnups = [d[1] for d in dataList]
        maxb = max(burnups)
        if maxb > maxbu:
            maxbu = maxb
        xsType = crossSectionGroupManager.getXSTypeLabelFromNumber(typeNum)
        color = next(colors)
        plt.plot(times,
                 burnups,
                 color + ".",
                 label="Type {0} XS".format(xsType))

    for upperBu in [0.0] + settings.getMasterCs()["buGroups"]:
        # draw a hline at the limits of each burnup group
        plt.axhline(y=upperBu)

    plt.legend()
    plt.title("Block burnups used to generate XS for {0}".format(reactor.name))
    plt.xlabel("Time (years)")
    plt.ylabel("Burnup (% FIMA)")

    plt.ylim(0, maxbu * 1.05)
    figName = (reactor.name + ".bugroups." +
               settings.getMasterCs()["outputFileExtension"])
    plt.savefig(figName)
    plt.close(1)
    report.setData("Xs Plot", os.path.abspath(figName), report.XS_PLOT)
Example #12
0
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
Example #13
0
def createSIMPLE_HEXZ_NHFLUX(runVariant=False):
    """
    Create NHFLUX file for storage into *fixtures* directory.

    In order to test the reading of NHFLUX file, there is a need to provide one such
    file for testing. This function runs the provided DIF3D input, and generates an
    NHFLUX file. The DIF3D input is a modified version of test case 01 from the DIF3D
    code package. It uses the 4-group cross sections located in the last part of the
    input. The modification includes:

    1) reduce the geometry to 3 rows of assemblies in full core geometry;
    2) reduce the fuel assembly to contain 6 nodes only;
    3) change the dimension to be whole numbers.

    In this way, the produced NHFLUX file is fairly small in size that makes it suitable
    for testing purposes. Another benefit of the simplified input is the trivial
    computer running time. It should take < 10 seconds to generate the NHFLUX file.
    Nevertheless, since the diffusion approximation is likely to be invalid for such a
    small-size core, results are not meant for physics benchmarking or other realistic
    applications.

    .. important::
        This requires both DIF3D and the TerraPower's DIF3D ARMI plugin in order to run.
        The latest output is shipped with the test, but regenerating or updating it will
        require these extra dependencies. Also, if you don't have them you can ask
        someone that does and maybe they can hook you up.
    """
    DIF3D_EXE = settings.getMasterCs()["dif3d"]

    runDir = tempfile.mkdtemp()
    tempInputPath = os.path.join(runDir, "input")
    shutil.copy(SIMPLE_HEXZ_INP, tempInputPath)

    # If running VARIANT, include a Card 12 on A.DIF3D. Runs P1P0 with isotropic cross
    # sections.
    if runVariant:
        with open(tempInputPath, "r") as fIn:
            dif3dInput = fIn.read()
        oldString = "UNFORM=A.NIP3"
        newString = "12  40601  10101  0  0  0  -1  0  0  0  1  0\n" + oldString
        dif3dInput = re.sub(oldString, newString, dif3dInput, count=1)
        with open(tempInputPath, "w") as fOut:
            fOut.write(dif3dInput)

    with open(tempInputPath, "r") as fIn:
        _process = subprocess.run(DIF3D_EXE,
                                  cwd=runDir,
                                  capture_output=True,
                                  stdin=fIn)

    copyName = SIMPLE_HEXZ_NHFLUX if not runVariant else SIMPLE_HEXZ_NHFLUX_VARIANT
    shutil.copy(os.path.join(runDir, "NHFLUX"), copyName)
    shutil.rmtree(runDir)
Example #14
0
    def _checkCsConsistency(self):
        """Debugging check to verify that CS objects are not unexpectedly multiplying."""
        cs = settings.getMasterCs()
        wrong = (self.cs is not cs) or any((i.cs is not cs) for i in self.interfaces)
        if wrong:
            msg = ["Master cs ID is {}".format(id(cs))]
            for i in self.interfaces:
                msg.append("{:30s} has cs ID: {:12d}".format(str(i), id(i.cs)))
            msg.append("{:30s} has cs ID: {:12d}".format(str(self), id(self.cs)))
            raise RuntimeError("\n".join(msg))

        runLog.debug(
            "Reactors, operators, and interfaces all share master cs: {}".format(id(cs))
        )
Example #15
0
    def test_changeOfCS(self):
        self.inspector.addQuery(
            lambda: self.inspector.cs["runType"] ==
            "banane",  # german for banana
            "babababa",
            "",
            self.inspector.NO_ACTION,
        )
        query = self.inspector.queries[0]
        self.assertFalse(query)

        newCS = settings.getMasterCs().duplicate()
        newCS["runType"] = "banane"
        self.inspector.cs = newCS
        self.assertTrue(query)
Example #16
0
    def _applyTemperaturesToComponents(reactor):
        """Update temperatures of block components now that densities have been set.

        Thermally expand them if there's coupled TH

        Useful only if the case is being loaded from did NOT have coupled T/H.

        See Also
        --------
        _setInputComponentTemperatures : deals with loading from coupled TH cases

        """
        from terrapower.physics.thermalHydraulics import thutils

        if (settings.getMasterCs()["useInputTemperaturesOnDBLoad"]
                and reactor.o.couplingIsActive()):
            thutils.applyTemperaturesToComponents(reactor)
Example #17
0
def movesVsCycle(reactor, scalars):
    r"""
    make a bar chart showing the number of moves per cycle in the full core

    A move is defined as an assembly being picked up, moved, and put down. So if
    two assemblies are swapped, that is 2 moves. Note that it does not count
    temporary storage for such swaps. This is an approximation because in a chain of moves,
    only one out of the chain would have to be temporarily stored. So as the chains get longer,
    this approximation gets more accurate.

    Parameters
    ----------
    scalars : dict
        The reactor-level params for this case.

    See Also
    --------
    FuelHandler.outage : sets the number of moves in each cycle

    """
    cycles = []
    yvals = []
    for moves, cycle in zip(scalars["numMoves"], scalars["cycle"]):
        if moves is None:
            moves = 0.0
        if cycle not in cycles:  # only one move per cycle
            cycles.append(
                cycle
            )  # use the cycles scalar val in case burnSteps is dynamic
            yvals.append(moves)

    plt.figure(figsize=(12, 6))  # make it wide and short.
    plt.bar(cycles, yvals, align="center")
    if len(cycles) > 1:
        plt.xticks(cycles)
    plt.grid(color="0.70")
    plt.xlabel("Cycle")
    plt.ylabel("Number of Moves")
    plt.title("Fuel management rate for " + reactor.name)
    figName = reactor.name + ".moves." + settings.getMasterCs(
    )["outputFileExtension"]
    plt.savefig(figName)
    plt.close(1)

    report.setData("Moves Plot", os.path.abspath(figName), report.MOVES_PLOT)
Example #18
0
def buildOperatorOfEmptyCartesianBlocks(customSettings=None):
    """
    Builds a operator w/ a reactor object with some Cartesian assemblies and blocks, but all are empty

    Doesn't depend on inputs and loads quickly.

    Params
    ------
    customSettings : dict
        Dictionary of off-default settings to update
    """
    settings.setMasterCs(None)  # clear
    cs = settings.getMasterCs()  # fetch new

    if customSettings is None:
        customSettings = {}

    customSettings["db"] = False  # stop use of database
    cs = cs.modified(newSettings=customSettings)
    settings.setMasterCs(cs)  # reset

    r = tests.getEmptyCartesianReactor()
    r.core.setOptionsFromCs(cs)
    o = operators.Operator(cs)
    o.initializeInterfaces(r)

    a = assemblies.CartesianAssembly("fuel")
    a.spatialGrid = grids.axialUnitGrid(1)
    b = blocks.CartesianBlock("TestBlock")
    b.setType("fuel")
    dims = {
        "Tinput": 600,
        "Thot": 600,
        "widthOuter": 16.0,
        "lengthOuter": 10.0,
        "widthInner": 1,
        "lengthInner": 1,
        "mult": 1,
    }
    c = Rectangle("fuel", uZr.UZr(), **dims)
    b.add(c)
    a.add(b)
    a.spatialLocator = r.core.spatialGrid[1, 0, 0]
    o.r.core.add(a)
    return o
Example #19
0
def buVsTime(reactor, scalars):
    r"""
    produces a burnup and DPA vs. time plot for this case

    Will add a second axis containing DPA if the scalar column maxDPA exists.

    Parameters
    ----------
    scalars : dict
        Scalar values for this case


    """
    plt.figure()
    try:
        plt.plot(scalars["time"], scalars["maxBuI"], ".-", label="Driver")
    except ValueError:
        runLog.warning(
            "Incompatible axis length in burnup plot. Time has {0}, bu has {1}. Skipping"
            "".format(len(scalars["time"]), len(scalars["maxBuI"]))
        )
        plt.close(1)
        return
    plt.plot(scalars["time"], scalars["maxBuF"], ".-", label="Feed")
    plt.xlabel("Time (yr)")
    plt.ylabel("BU (%FIMA)")
    plt.grid(color="0.70")
    plt.legend(loc="lower left")
    title = "Maximum burnup"
    if scalars["maxDPA"]:
        plt.twinx()
        plt.plot(scalars["time"], scalars["maxDPA"], "r--", label="dpa")
        plt.legend(loc="lower right")
        plt.ylabel("dpa")
        title += " and DPA"
    title += " for " + reactor.name

    plt.title(title)
    plt.legend(loc="lower right")
    figName = reactor.name + ".bu." + settings.getMasterCs()["outputFileExtension"]
    plt.savefig(figName)
    plt.close(1)

    report.setData("Burnup Plot", os.path.abspath(figName), report.BURNUP_PLOT)
Example #20
0
def valueVsTime(reactor, x, y, key, yaxis, title, ymin=None):
    r"""
    Plots a value vs. time with a standard graph format

    Parameters
    ----------
    reactor : armi.reactor.reactors object

    reportGroup : armi.bookkeeping.report.data.Group object

    x : iterable
        The x-axis values (the abscissa)
    y : iterable
        The y-axis values (the ordinate)
    key : str
        A key word to add the item to the report interface
    yaxis : str
        The y axis label
    title : str
        the plot title
    ymin : str, optional
        The minimum y-axis value. If any ordinates are less than this value,
        it will be ignored.

    """
    plt.figure()
    plt.plot(x, y, ".-")
    plt.xlabel("Time (yr)")
    plt.ylabel(yaxis)
    plt.grid(color="0.70")
    plt.title(title + " for {0}".format(reactor.name))

    if ymin is not None and all([yi > ymin for yi in y]):
        # set ymin all values are greater than it and it exists.
        ax = plt.gca()
        ax.set_ylim(bottom=ymin)

    figName = (
        reactor.name + "." + key + "." + settings.getMasterCs()["outputFileExtension"]
    )
    plt.savefig(figName)
    plt.close(1)

    report.setData("PlotTime", os.path.abspath(figName), report.TIME_PLOT)
Example #21
0
def keffVsTime(reactor, time, keff, keffUnc=None, ymin=None):
    r"""
    Plots core keff vs. time

    Parameters
    ----------
    time : list
        Time in years
    keff : list
        Keff in years
    keffUnc : list, optional
        Uncontrolled keff or None (will be plotted as secondary series)
    ymin : float, optional
        Minimum y-axis value to target.
    """
    plt.figure()
    if any(keffUnc):
        label1 = "Controlled k-eff"
        label2 = "Uncontrolled k-eff"
    else:
        label1 = None

    plt.plot(time, keff, ".-", label=label1)
    if any(keffUnc):
        plt.plot(time, keffUnc, ".-", label=label2)
        plt.legend()
    plt.xlabel("Time (yr)")
    plt.ylabel("k-eff")
    plt.grid(color="0.70")
    plt.title("k-eff vs. time" + " for {0}".format(reactor.name))

    if ymin is not None and all([yi > ymin for yi in keff]):
        # set ymin all values are greater than it and it exists.
        ax = plt.gca()
        ax.set_ylim(bottom=ymin)

    figName = reactor.name + ".keff." + settings.getMasterCs(
    )["outputFileExtension"]
    plt.savefig(figName)
    plt.close(1)

    report.setData("K-Eff", os.path.abspath(figName), report.KEFF_PLOT)
Example #22
0
def distortionVsTime(reactor, scalars):
    r"""plots max distortion vs. time if the distortion interface is attached"""
    dd = reactor.o.getInterface("ductDistortion")
    if not dd or not "maxSwelling" in dd.__dict__:
        return  # skip plotting

    plt.figure()
    plt.plot(scalars["time"], dd.maxTotal, label="Total")
    plt.plot(scalars["time"], dd.maxCreep, label="Creep")
    plt.plot(scalars["time"], dd.maxSwelling, label="Swelling")
    plt.xlabel("Time (yr)")
    plt.ylabel("Distortion (mm)")
    plt.grid(color="0.70")
    plt.legend(loc="lower right")
    plt.title("Maximum duct distortion for " + reactor.name)
    figName = reactor.name + ".duct." + settings.getMasterCs()["outputFileExtension"]
    plt.savefig(figName)
    plt.close(1)

    report.setData("Distortion Plot", os.path.abspath(figName), report.DISTORTION_PLOT)
Example #23
0
    def test_exposeInterfaces(self):
        """Make sure that the exposeInterfaces hook is properly implemented"""
        if self.plugin is None:
            return
        if not hasattr(self.plugin, "exposeInterfaces"):
            return

        cs = settings.getMasterCs()
        results = self.plugin.exposeInterfaces(cs)
        # each plugin should return a list
        self.assertIsInstance(results, list)
        for result in results:
            # Make sure that all elements in the list satisfy the constraints of the
            # hookspec
            self.assertIsInstance(result, tuple)
            self.assertEqual(len(result), 3)

            order, interface, kwargs = result

            self.assertIsInstance(order, (int, float))
            self.assertTrue(issubclass(interface, interfaces.Interface))
            self.assertIsInstance(kwargs, dict)
Example #24
0
def createSIMPLE_HEXZ_NHFLUX():
    """
    Create NHFLUX file.

    In order to test the reading of NHFLUX file, there is a need to provide one such
    file for testing. This function runs the provided DIF3D input, and generates an
    NHFLUX file. The DIF3D input is a modified version of test case 01 from the DIF3D
    code package. It uses the 4-group cross sections located in the last part of the
    input. The modification includes:

    1) reduce the geometry to 3 rows of assemblies in full core geometry;
    2) reduce the fuel assembly to contain 6 nodes only;
    3) change the dimension to be whole numbers.

    In this way, the produced NHFLUX file is fairly small in size that makes it suitable
    for testing purposes. Another benefit of the simplified input is the trivial
    computer running time. It should take < 10 seconds to generate the NHFLUX file.
    Nevertheless, since the diffusion approximation is likely to be invalid for such a
    small-size core, results are not meant for physics benchmarking or other realistic
    applications.

    .. important::
        This requires both DIF3D and the TerraPower's DIF3D ARMI plugin in order to run.
        The latest output is shipped with the test, but regenerating or updating it will
        require these extra dependencies. Also, if you don't have them you can ask
        someone that does and maybe they can hook you up.
    """
    DIF3D_EXE = settings.getMasterCs().settings["dif3d"].value

    runDir = tempfile.mkdtemp()
    shutil.copy(SIMPLE_HEXZ_INP, os.path.join(runDir, "input"))
    process = subprocess.Popen(
        "{} < input > output".format(DIF3D_EXE), cwd=runDir, shell=True
    )
    process.communicate()
    shutil.copy(os.path.join(runDir, "NHFLUX"), SIMPLE_HEXZ_NHFLUX)
    shutil.rmtree(runDir)
Example #25
0
 def test_csWorks(self):
     """Ensure plugin settings become available and have defaults"""
     a = settings.getMasterCs()
     self.assertEqual(a["circularRingOrder"], "angle")
Example #26
0
 def loadUZrAssembly(self, materialModifications):
     yamlString = self.uZrInput + "\n" + materialModifications
     design = blueprints.Blueprints.load(yamlString)
     design._prepConstruction("hex", settings.getMasterCs())
     return design.assemblies["fuel a"]
Example #27
0
def writeStandardReportTemplate(f, report):
    f.write(r"<!DOCTYPE html>" + "\n")
    cs = settings.getMasterCs()
    with Html(f):

        with Head(f):
            f.write(r'<meta charset="UTF-8">' + "\n")
            with Title(f):
                f.write(cs.caseTitle)

        with Body(f):

            with Div(
                    f,
                    attrs={
                        "id": "navbar",
                        "class": "navbar navbar-default navbar-fixed-top",
                    },
            ):
                with Div(f, attrs={"class": "container"}):
                    with Div(f, attrs={"class": "navbar-header"}):

                        with Span(f,
                                  attrs={
                                      "class":
                                      "navbar-text navbar-version pull-left"
                                  }):
                            with Img(
                                    f,
                                    attrs={
                                        "src":
                                        encode64(
                                            os.path.join(
                                                armi.RES, "images",
                                                "armiicon.ico"))
                                    },
                            ):
                                pass

                        with A(
                                f,
                                attrs={
                                    "class": "navbar-brand",
                                    "href": "#",
                                    "style": "color: #d9230f;",
                                },
                        ):
                            with B(f):
                                f.write(cs.caseTitle)

                        with Span(f,
                                  attrs={
                                      "class":
                                      "navbar-text navbar-version pull-left"
                                  }):
                            with B(f):
                                f.write(armi.USER)

                        with Span(f,
                                  attrs={
                                      "class":
                                      "navbar-text navbar-version pull-left"
                                  }):
                            with B(f):
                                f.write(datetime.datetime.now().isoformat())

            with Div(f,
                     attrs={
                         "class": "container",
                         "style": "padding-top: 20px;"
                     }):

                with Div(f, attrs={"class": "page-header"}):
                    with H1(f):
                        f.write(report.title)
                    with P(f):
                        f.write(cs["comment"])

                report.writeGroupsHTML(f)

                with Footer(
                        f,
                        attrs=
                    {
                        "style":
                        "width: 100%; border-top: 1px solid #ccc; padding-top: 10px;"
                    },
                ):
                    with UL(f, attrs={"class": "list-unstyled"}):
                        with LI(f, attrs={"class": "pull-right"}):
                            with A(f, attrs={"href": "#top"}):
                                f.write("Back to top")
                        with LI(f):
                            with A(
                                    f,
                                    attrs={
                                        "href":
                                        "https://terrapower.github.io/armi/"
                                    },
                            ):
                                f.write("ARMI docs")
                    with P(f):
                        f.write("Automatically generated by ARMI")
 def setUp(self):
     self.o, self.r = loadTestReactor(TEST_ROOT)
     self.cs = settings.getMasterCs()
Example #29
0
 def __init__(self, r=None, externalCodeInterface=None, cs=None):
     self.externalCodeInterface = externalCodeInterface
     self.eci = externalCodeInterface
     self.r = r
     self.cs = cs or settings.getMasterCs()
Example #30
0
    def workerOperate(self):
        """
        The main loop on any worker MPI nodes.

        Notes
        -----
        This method is what worker nodes are in while they wait for instructions from
        the master node in a parallel run. The nodes will sit, waiting for a "worker
        command". When this comes (from a bcast from the master), a set of if statements
        are evaluated, with specific behaviors defined for each command. If the operator
        doesn't understand the command, it loops through the interface stack to see if
        any of the interfaces understand it.

        Originally, "magic strings" were broadcast, which were handled either here or in
        one of the interfaces' ``workerOperate`` methods. Since then, the
        :py:mod:`~armi.mpiActions` system has been devised which just broadcasts
        ``MpiAction`` objects. Both methods are still supported.

        See Also
        --------
        armi.mpiActions : MpiAction information
        armi.interfaces.workerOperate : interface-level handling of worker commands.

        """
        while True:
            # sit around waiting for a command from the master
            runLog.extra("Node {0} ready and waiting".format(armi.MPI_RANK))
            cmd = armi.MPI_COMM.bcast(None, root=0)
            runLog.extra("worker received command {0}".format(cmd))
            # got a command. go use it.
            if isinstance(cmd, mpiActions.MpiAction):
                cmd.invoke(self, self.r, self.cs)
            elif cmd == "quit":
                self.workerQuit()
                break  # If this break is removed, the program will remain in the while loop forever.
            elif cmd == "finished":
                runLog.warning(
                    "Received unexpected FINISHED command. Usually a QUIT command precedes this. "
                    "Skipping cleanup of temporary files.")
                break
            elif cmd == "sync":
                # wait around for a sync
                runLog.debug("Worker syncing")
                note = armi.MPI_COMM.bcast("wait", root=0)
                if note != "wait":
                    raise RuntimeError(
                        'did not get "wait". Got {0}'.format(note))
            else:
                # we don't understand the command on our own. check the interfaces
                # this allows all interfaces to have their own custom operation code.
                handled = False
                for i in self.interfaces:
                    handled = i.workerOperate(cmd)
                    if handled:
                        break
                if not handled:
                    if armi.MPI_RANK == 0:
                        print("Interfaces" + str(self.interfaces))
                    runLog.error(
                        "No interface understood worker command {0}\n check stdout for err\n"
                        "available interfaces:\n  {1}".format(
                            cmd,
                            "\n  ".join("name:{} typeName:{} {}".format(
                                i.name, i.function, i)
                                        for i in self.interfaces),
                        ))
                    raise RuntimeError(
                        "Failed to delegate worker command {} to an interface."
                        .format(cmd))

            if self._workersShouldResetAfter(cmd):
                # clear out the reactor on the workers to start anew.
                # Note: This should build empty non-core systems too.
                xsGroups = self.getInterface("xsGroups")
                if xsGroups:
                    xsGroups.clearRepresentativeBlocks()
                cs = settings.getMasterCs()
                bp = self.r.blueprints
                spatialGrid = self.r.core.spatialGrid
                self.detach()
                self.r = reactors.Reactor(cs, bp)
                core = reactors.Core("Core", cs)
                self.r.add(core)
                core.spatialGrid = spatialGrid
                self.reattach(self.r, cs)

            # might be an mpi action which has a reactor and everything, preventing
            # garbage collection
            del cmd
            gc.collect()