Esempio n. 1
0
 def __repr__(self):
     suffix = (" with Suffix:`{}`".format(self.xsLibrarySuffix)
               if self.xsLibrarySuffix else "")
     if self.generateExclusiveGammaXS:
         xsFlag = neutronics.GAMMA
     elif (neutronics.gammaXsAreRequested(self.cs)
           and self._isGammaXSGenerationEnabled):
         xsFlag = neutronics.NEUTRONGAMMA
     else:
         xsFlag = neutronics.NEUTRON
     return "<{} - XS ID {} ({} XS){}>".format(self.__class__.__name__,
                                               self.xsId, xsFlag, suffix)
Esempio n. 2
0
 def __init__(self, r, cs):
     interfaces.Interface.__init__(self, r, cs)
     self._updateBlockNeutronVelocities = True  # Set to True by default, but should be disabled when perturbed cross sections are generated.
     # Geometry options available through the lattice physics interfaces
     self._ZERO_DIMENSIONAL_GEOM = "0D"
     self._ONE_DIMENSIONAL_GEOM = "1D"
     self._TWO_DIMENSIONAL_GEOM = "2D"
     self._SLAB_MODEL = " slab"
     self._CYLINDER_MODEL = " cylinder"
     self._HEX_MODEL = " hex"
     self._burnupTolerance = self.cs["tolerateBurnupChange"]
     self._oldXsIdsAndBurnup = {}
     self.executablePath = self._getExecutablePath()
     self.executableRoot = os.path.dirname(self.executablePath)
     self.includeGammaXS = neutronics.gammaTransportIsRequested(
         cs
     ) or neutronics.gammaXsAreRequested(cs)
Esempio n. 3
0
 def __init__(
     self,
     representativeBlock,
     r=None,
     externalCodeInterface=None,
     xsLibrarySuffix="",
     generateExclusiveGammaXS=False,
 ):
     interfaces.InputWriter.__init__(
         self, r=r, externalCodeInterface=externalCodeInterface)
     self.cs = self.eci.cs
     self.block = representativeBlock
     if not isinstance(xsLibrarySuffix, str):
         raise TypeError(
             "xsLibrarySuffix should be a string; got {}".format(
                 type(xsLibrarySuffix)))
     self.xsLibrarySuffix = xsLibrarySuffix
     self.generateExclusiveGammaXS = generateExclusiveGammaXS
     if self.generateExclusiveGammaXS and not neutronics.gammaXsAreRequested(
             self.cs):
         raise ValueError(
             "Invalid `genXS` setting to generate gamma XS for {}.".format(
                 self.block))
     self.xsId = representativeBlock.getMicroSuffix()
     self.xsSettings = self.cs[CONF_CROSS_SECTION][self.xsId]
     self.mergeIntoClad = self.xsSettings.mergeIntoClad
     self.driverXsID = self.xsSettings.driverID
     self.numExternalRings = self.xsSettings.numExternalRings
     self.criticalBucklingSearchActive = self.xsSettings.criticalBuckling
     blockNeedsFPs = (
         representativeBlock.hasFlags(Flags.FUEL)
         and representativeBlock.getLumpedFissionProductCollection())
     self.modelFissionProducts = (blockNeedsFPs and
                                  self.cs["fpModel"] != "noFissionProducts")
     self.diluteFissionProducts = (blockNeedsFPs and self.cs["fpModel"]
                                   == "infinitelyDilute")
     self.minimumNuclideDensity = self.cs["minimumNuclideDensity"]
     self._unusedNuclides = set()
     self._allNuclideObjects = None
Esempio n. 4
0
    def _inspectSettings(self):
        """Check settings for inconsistencies."""
        # import here to avoid cyclic issues
        from armi import operators

        self.addQueryBadLocationWillLikelyFail("operatorLocation")

        self.addQuery(
            lambda: self.cs["outputFileExtension"] == "pdf" and self.cs[
                "genReports"],
            "Output files of '.pdf' format are not supported by the reporting HTML generator. '.pdf' "
            "images will not be included.",
            "Switch to '.png'?",
            lambda: self._assignCS("outputFileExtension", "png"),
        )

        self.addQuery(
            lambda: (self.cs[globalSettings.CONF_ZONING_STRATEGY] == "manual"
                     and not self.cs["zoneDefinitions"]),
            "`manual` zoningStrategy requires that `zoneDefinitions` setting be defined. Run will have "
            "no zones.",
            "",
            self.NO_ACTION,
        )
        self.addQuery(
            lambda: ((self.cs["beta"] and isinstance(self.cs["beta"], list) and
                      not self.cs["decayConstants"]) or
                     (self.cs["decayConstants"] and not self.cs["beta"])),
            "Both beta components and decay constants should be provided if either are "
            "being supplied.",
            "",
            self.NO_ACTION,
        ),

        self.addQuery(
            lambda: self.cs["skipCycles"] > 0 and not self.cs["reloadDBName"],
            "You have chosen to do a restart case without specifying a database to load from. "
            "Run will load from output files, if they exist but burnup, etc. will not be updated.",
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["runType"] != operators.RunTypes.SNAPSHOTS and self
            .cs["loadStyle"] == "fromDB" and self.cs[
                "startCycle"] == 0 and self.cs["startNode"] == 0,
            "Starting from cycle 0, and time node 0 was chosen. Restart runs load from "
            "the time node just before the restart. There is no time node to load from "
            "before cycle 0 node 0. Either switch to the snapshot operator, start from "
            "a different time step or load from inputs rather than database as "
            "`loadStyle`.",
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["runType"] == operators.RunTypes.SNAPSHOTS and
            not (self.cs["dumpSnapshot"] or self.cs["defaultSnapshots"]),
            "The Snapshots operator was specified, but no dump snapshots were chosen."
            "Please specify snapshot steps with the `dumpSnapshot` setting.",
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs.caseTitle.lower() == os.path.splitext(
                os.path.basename(self.cs["reloadDBName"].lower()))[0],
            "Snapshot DB ({0}) and main DB ({1}) cannot have the same name."
            "Change name of settings file and resubmit.".format(
                self.cs["reloadDBName"], self.cs.caseTitle),
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["reloadDBName"] != "" and not os.path.exists(
                self.cs["reloadDBName"]),
            "Reload database {} does not exist. \nPlease point to an existing DB, "
            "or set to empty and load from input.".format(
                self.cs["reloadDBName"]),
            "",
            self.NO_ACTION,
        )

        def _willBeCopiedFrom(fName):
            for copyFile in self.cs["copyFilesFrom"]:
                if fName == os.path.split(copyFile)[1]:
                    return True
            return False

        self.addQuery(
            lambda: self.cs["explicitRepeatShuffles"] and not self.
            _csRelativePathExists(self.cs["explicitRepeatShuffles"]) and
            not _willBeCopiedFrom(self.cs["explicitRepeatShuffles"]),
            "The specified repeat shuffle file `{0}` does not exist, and won't be copied from elsewhere. "
            "Run will crash.".format(self.cs["explicitRepeatShuffles"]),
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: not self.cs["power"],
            "No power level set. You must always start by importing a base settings file.",
            "",
            self.NO_ACTION,
        )

        # The gamma cross sections generated for MC2-3 by ANL were done with NJOY with
        # P3 scattering. MC2-3 would have to be modified and the gamma cross sections
        # re-generated with NJOY for MC2-3 to allow any other scattering order with
        # gamma cross sections enabled.
        self.addQuery(
            lambda:
            ("MC2v3" in self.cs["xsKernel"] and neutronics.gammaXsAreRequested(
                self.cs) and self.cs["xsScatteringOrder"] != 3),
            "MC2-3 will crash if a scattering order is not set to 3 when generating gamma XS.",
            "Would you like to set the `xsScatteringOrder` to 3?",
            lambda: self._assignCS("xsScatteringOrder", 3),
        )

        self.addQuery(
            lambda: self.cs["outputCacheLocation"] and not os.path.exists(
                self.cs["outputCacheLocation"]),
            "`outputCacheLocation` path {} does not exist. Please specify a location that exists."
            .format(self.cs["outputCacheLocation"]),
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["numCoupledIterations"] > 0,
            "You have {0} coupling iterations selected.".format(
                self.cs["numCoupledIterations"]),
            "1 coupling iteration doubles run time (2 triples, etc). Do you want to use 0 instead? ",
            lambda: self._assignCS("numCoupledIterations", 0),
        )

        self.addQuery(
            lambda: self.cs["nCycles"] in [0, None],
            "Cannot run 0 cycles. Set burnSteps to 0 to activate a single time-independent case.",
            "Set 1 cycle and 0 burnSteps for single time-independent case?",
            self._correctCyclesToZeroBurnup,
        )

        def _checkForBothSimpleAndDetailedCyclesInputs():
            """
            Note that we must bypass the `Settings` getter and reach directly
            into the underlying `__settings` dict to avoid triggering an error
            at this stage in the run. Otherwise an error will inherently be raised
            if the detailed cycles input is used because the simple cycles inputs
            have defaults. We don't care that those defaults are there, we only
            have a problem with those defaults being _used_, which will be caught
            later on.
            """
            bothCyclesInputTypesPresent = (
                self.cs._Settings__settings["cycleLength"]
                or self.cs._Settings__settings["cycleLengths"]
                or self.cs._Settings__settings["burnSteps"]
                or self.cs._Settings__settings["availabilityFactor"]
                or self.cs._Settings__settings["availabilityFactors"]
                or self.cs._Settings__settings["powerFractions"]
            ) and self.cs["cycles"] != []

            return bothCyclesInputTypesPresent

        self.addQuery(
            _checkForBothSimpleAndDetailedCyclesInputs,
            "If specifying detailed cycle history with `cycles`, you may not"
            " also use any of the simple cycle history inputs `cycleLength(s)`,"
            " `burnSteps`, `availabilityFactor(s)`, or `powerFractions`."
            " Using the detailed cycle history.",
            "",
            self.NO_ACTION,
        )

        def _factorsAreValid(factors, maxVal=1.0):
            try:
                expandedList = expandRepeatedFloats(factors)
            except (ValueError, IndexError):
                return False
            return (all(0.0 <= val <= maxVal for val in expandedList)
                    and len(expandedList) == self.cs["nCycles"])

        if self.cs["cycles"] == []:
            self.addQuery(
                lambda: (self.cs["availabilityFactors"] and
                         not _factorsAreValid(self.cs["availabilityFactors"])),
                "`availabilityFactors` was not set to a list compatible with the number of cycles. "
                "Please update input or use constant duration.",
                "Use constant availability factor specified in `availabilityFactor` setting?",
                lambda: self._assignCS("availabilityFactors", []),
            )

            self.addQuery(
                lambda: (self.cs["powerFractions"] and not _factorsAreValid(
                    self.cs["powerFractions"])),
                "`powerFractions` was not set to a compatible list. "
                "Please update input or use full power at all cycles.",
                "Use full power for all cycles?",
                lambda: self._assignCS("powerFractions", []),
            )

            self.addQuery(
                lambda: (self.cs["cycleLengths"] and not _factorsAreValid(
                    self.cs["cycleLengths"], maxVal=1e10)),
                "`cycleLengths` was not set to a list compatible with the number of cycles."
                " Please update input or use constant duration.",
                "Use constant cycle length specified in `cycleLength` setting?",
                lambda: self._assignCS("cycleLengths", []),
            )

            self.addQuery(
                lambda: (self.cs["runType"] == operators.RunTypes.STANDARD and
                         self.cs["burnSteps"] == 0 and (
                             (len(self.cs["cycleLengths"]) > 1
                              if self.cs["cycleLengths"] != None else False
                              ) or self.cs["nCycles"] > 1)),
                "Cannot run multi-cycle standard cases with 0 burnSteps per cycle. Please update settings.",
                "",
                self.NO_ACTION,
            )

            def decayCyclesHaveInputThatWillBeIgnored():
                """Check if there is any decay-related input that will be ignored."""
                try:
                    powerFracs = expandRepeatedFloats(
                        self.cs["powerFractions"])
                    availabilities = expandRepeatedFloats(
                        self.cs["availabilityFactors"]) or (
                            [self.cs["availabilityFactor"]] *
                            self.cs["nCycles"])
                except:  # pylint: disable=bare-except
                    return True

                for pf, af in zip(powerFracs, availabilities):
                    if pf > 0.0 and af == 0.0:
                        # this will be a full decay step and any power fraction will be ignored. May be ok, but warn.
                        return True
                return False

            self.addQuery(
                lambda: (self.cs["cycleLengths"] and self.cs["powerFractions"]
                         and decayCyclesHaveInputThatWillBeIgnored(
                         ) and not self.cs["cycles"]),
                "At least one cycle has a non-zero power fraction but an availability of zero. Please "
                "update the input.",
                "",
                self.NO_ACTION,
            )

        self.addQuery(
            lambda: self.cs["operatorLocation"] and self.cs[
                "runType"] != operators.RunTypes.STANDARD,
            "The `runType` setting is set to `{0}` but there is a `custom operator location` defined"
            .format(self.cs["runType"]),
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["operatorLocation"] and self.cs[
                "runType"] != operators.RunTypes.STANDARD,
            "The `runType` setting is set to `{0}` but there is a `custom operator location` defined"
            .format(self.cs["runType"]),
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["runType"] == operators.RunTypes.EQUILIBRIUM and
            self.cs["cycles"],
            "Equilibrium cases cannot use the `cycles` case setting to define detailed"
            " cycle information. Try instead using the simple cycle history inputs"
            " `cycleLength(s)`, `burnSteps`, `availabilityFactor(s)`, and/or `powerFractions`",
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["skipCycles"] > 0 and not os.path.exists(
                self.cs.caseTitle + ".restart.dat"),
            "This is a restart case, but the required restart file {0}.restart.dat is not found"
            .format(self.cs.caseTitle),
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["deferredInterfacesCycle"] > self.cs["nCycles"],
            "The deferred interface activation cycle exceeds set cycle occurrence. "
            "Interfaces will not be activated in this run!",
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: (self.cs["boundaries"] != neutronics.GENERAL_BC and self.
                     cs["bcCoefficient"]),
            "General neutronic boundary condition was not selected, but `bcCoefficient` was defined. "
            "Please enable `Generalized` neutronic boundary condition or disable `bcCoefficient`.",
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["geomFile"] and str(self.geomType) not in geometry.
            VALID_GEOMETRY_TYPE,
            "{} is not a valid geometry Please update geom type on the geom file. "
            "Valid (case insensitive) geom types are: {}".format(
                self.geomType, geometry.VALID_GEOMETRY_TYPE),
            "",
            self.NO_ACTION,
        )

        self.addQuery(
            lambda: self.cs["geomFile"] and not geometry.
            checkValidGeomSymmetryCombo(self.geomType, self.coreSymmetry),
            "{}, {} is not a valid geometry and symmetry combination. Please update "
            "either geometry or symmetry on the geom file.".format(
                str(self.geomType), str(self.coreSymmetry)),
            "",
            self.NO_ACTION,
        )