def getSimpleDBOperator(cs): """ Return a very simple operator that covers most of the database interactions. Notes ----- This reactor has only 1 assembly with 1 type of block. It's used to make the db unit tests run very quickly. """ cs["loadingFile"] = "refOneBlockReactor.yaml" cs["verbosity"] = "important" cs["db"] = True cs["runType"] = "Standard" cs["geomFile"] = "geom1Assem.xml" cs["nCycles"] = 2 genDBCase = case.Case(cs) settings.setMasterCs(cs) runLog.setVerbosity("info") o = genDBCase.initializeOperator() o.interfaces = [ interface for interface in o.interfaces if interface.name in ["database", "main"] ] return o
def loadFromString(self, string, handleInvalids=True): """Read in settings from a string. Supports two xml formats, the newer (tags are the key, etc.) and the former (tags are the type, etc.) Passes the reader back out in case you want to know something about how the reading went like for knowing if a file contained deprecated settings, etc. """ if self._failOnLoad: raise exceptions.StateError( "Cannot load settings after processing of command " "line options begins.\nYou may be able to fix this by " "reordering the command line arguments.") reader = settingsIO.SettingsReader(self) reader.readFromStream(io.StringIO(string), handleInvalids=handleInvalids) if armi.MPI_RANK == 0: runLog.setVerbosity(self["verbosity"]) else: runLog.setVerbosity(self["branchVerbosity"]) return reader
def test_invalidSetVerbosityByString(self): """Test that the log verbosity setting fails if the integer is invalid.""" with self.assertRaises(KeyError): runLog.setVerbosity("taco") with self.assertRaises(TypeError): runLog.setVerbosity(["debug"])
def _applyReadSettings(self, path=None): if armi.MPI_RANK == 0: runLog.setVerbosity(self["verbosity"]) else: runLog.setVerbosity(self["branchVerbosity"]) if path: self.path = path # can't set this before a chance to fail occurs
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
def test_setVerbosityFromString(self): """Test that the log verbosity can be set with a string.""" log = runLog._RunLog(1) expectedStrVerbosity = "error" verbosityRank = log.getLogVerbosityRank(expectedStrVerbosity) runLog.setVerbosity(expectedStrVerbosity) self.assertEqual(verbosityRank, runLog.getVerbosity()) self.assertEqual(verbosityRank, logging.ERROR)
def test_setVerbosityFromInteger(self): """Test that the log verbosity can be set with an integer.""" log = runLog._RunLog(1) expectedStrVerbosity = "debug" verbosityRank = log.getLogVerbosityRank(expectedStrVerbosity) runLog.setVerbosity(verbosityRank) self.assertEqual(verbosityRank, runLog.getVerbosity()) self.assertEqual(verbosityRank, logging.DEBUG)
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
def initLogVerbosity(self): """Central location to init logging verbosity""" if armi.MPI_RANK == 0: runLog.setVerbosity(self["verbosity"]) else: runLog.setVerbosity(self["branchVerbosity"]) self.setModuleVerbosities(force=True)
def test_verbosityOutOfRange(self): """Test that the log verbosity setting resets to a canonical value when it is out of range""" runLog.setVerbosity(-50) self.assertEqual(runLog.LOG.logger.level, min([v[0] for v in runLog.LOG.logLevels.values()])) runLog.setVerbosity(5000) self.assertEqual(runLog.LOG.logger.level, max([v[0] for v in runLog.LOG.logLevels.values()]))
def invoke(self): from armi.nuclearDataIO import isotxs from armi.nuclearDataIO import xsLibraries runLog.setVerbosity(0) refIsotxs = isotxs.readBinary(self.args.reference) for fname in self.args.comparisonFiles: cmpIsotxs = isotxs.readBinary(fname) xsLibraries.compare(refIsotxs, cmpIsotxs)
def invoke(self): from armi.nuclearDataIO import isotxs from armi.nuclearDataIO import xsLibraries runLog.setVerbosity(0) refIsotxs = isotxs.readBinary(self.args.reference) # flux = read_broad_group_flux(refIsotxs.neutronEnergyGroups) for fname in self.args.comparisonFiles: cmpIsotxs = isotxs.readBinary(fname) xsLibraries.compare(refIsotxs, cmpIsotxs) # , flux)
def convertDatabase( inputDBName: str, outputDBName: Optional[str] = None, outputVersion: Optional[str] = None, ): """ Convert database files between different versions. Parameters ---------- inputDB name of the complete hierarchy database outputDB name of the output database that should be consistent with XTView outputVersion version of the database to convert to. Defaults to latest version """ dbIn = databaseFactory(inputDBName, permission=Permissions.READ_ONLY_FME) if dbIn.version == outputVersion: runLog.important( "The input database ({}) appears to already be in the desired " "format ({})".format(inputDBName, dbIn.version) ) return outputDBName = outputDBName or "-converted".join(os.path.splitext(inputDBName)) dbOut = databaseFactory( outputDBName, permission=Permissions.CREATE_FILE_TIE, version=outputVersion ) # each DB load resets the verbosity to that of the run. Here we allow # conversion users to overpower it. conversionVerbosity = runLog.getVerbosity() runLog.extra(f"Converting {dbIn} to DB version {outputVersion}") with dbIn, dbOut: # Making the bold assumption that we are working with HDF5 h5In = _getH5File(dbIn) h5Out = _getH5File(dbOut) dbOut.writeInputsToDB(None, *dbIn.readInputsFromDB()) for cycle, timeNode in dbIn.genTimeSteps(): runLog.extra(f"Converting cycle={cycle}, timeNode={timeNode}") r = dbIn.load(cycle, timeNode) runLog.setVerbosity(conversionVerbosity) dbOut.writeToDB(r) for auxPath in dbIn.genAuxiliaryData((cycle, timeNode)): name = next(reversed(auxPath.split("/"))) auxOutPath = dbOut.getAuxiliaryDataPath((cycle, timeNode), name) runLog.important( "Copying auxiliary data for time ({}, {}): {} -> {}".format( cycle, timeNode, auxPath, auxOutPath ) ) h5In.copy(auxPath, h5Out, name=auxOutPath)
def initLogVerbosity(self): """ Central location to init logging verbosity NOTE: This means that creating a Settings object sets the global logging level of the entire code base. """ if context.MPI_RANK == 0: runLog.setVerbosity(self["verbosity"]) else: runLog.setVerbosity(self["branchVerbosity"]) self.setModuleVerbosities(force=True)
def _distributeSettings(self): if armi.MPI_RANK == 0: runLog.debug("Sending the settings object") self.cs = cs = self.broadcast(self.o.cs) if isinstance(cs, settings.Settings): runLog.setVerbosity(cs["verbosity"] if armi.MPI_RANK == 0 else cs["branchVerbosity"]) runLog.debug("Received settings object") else: raise RuntimeError( "Failed to transmit settings, received: {}".format(cs)) if armi.MPI_RANK != 0: settings.setMasterCs(cs) self.o.cs = cs return cs
def setUp(self): self.cs = settings.Settings() runLog.setVerbosity("error") container = DummyComposite("inner test fuel") for i in range(5): leaf = DummyLeaf("duct {}".format(i)) leaf.setType("duct") container.add(leaf) nested = DummyComposite("clad") nested.setType("clad") self.secondGen = DummyComposite("liner") self.thirdGen = DummyLeaf("pin 77") self.secondGen.add(self.thirdGen) nested.add(self.secondGen) container.add(nested) self.container = container
def run(self): """ Run an ARMI case. This initializes an ``Operator``, a ``Reactor`` and invokes :py:meth:`Operator.operate`! It also activates supervisory things like code coverage checking, profiling, or tracing, if requested by users during debugging. Notes ----- Room for improvement: The coverage, profiling, etc. stuff can probably be moved out of here to a more elegant place (like a context manager?). """ # Start the log here so that the verbosities for the head and workers # can be configured based on the user settings for the rest of the # run. runLog.LOG.startLog(self.cs.caseTitle) if context.MPI_RANK == 0: runLog.setVerbosity(self.cs["verbosity"]) else: runLog.setVerbosity(self.cs["branchVerbosity"]) cov = None if self.cs["coverage"]: cov = coverage.Coverage(config_file=os.path.join( context.RES, "coveragerc"), debug=["dataio"]) if context.MPI_SIZE > 1: # interestingly, you cannot set the parallel flag in the constructor # without auto-specifying the data suffix. This should enable # parallel coverage with auto-generated data file suffixes and # combinations. cov.config.parallel = True cov.start() profiler = None if self.cs["profile"]: profiler = cProfile.Profile() profiler.enable(subcalls=True, builtins=True) self.checkInputs() o = self.initializeOperator() with o: if self.cs["trace"] and context.MPI_RANK == 0: # only trace master node. tracer = trace.Trace(ignoredirs=[sys.prefix, sys.exec_prefix], trace=1) tracer.runctx("o.operate()", globals(), locals()) else: o.operate() if profiler is not None: profiler.disable() profiler.dump_stats("profiler.{:0>3}.stats".format( context.MPI_RANK)) statsStream = six.StringIO() summary = pstats.Stats(profiler, stream=statsStream).sort_stats("cumulative") summary.print_stats() if context.MPI_SIZE > 0: allStats = context.MPI_COMM.gather(statsStream.getvalue(), root=0) if context.MPI_RANK == 0: for rank, statsString in enumerate(allStats): # using print statements because the logger has been turned off print("=" * 100) print("{:^100}".format( " Profiler statistics for RANK={} ".format(rank))) print(statsString) print("=" * 100) else: print(statsStream.getvalue()) if cov is not None: cov.stop() cov.save() if context.MPI_SIZE > 1: context.MPI_COMM.barrier( ) # force waiting for everyone to finish if context.MPI_RANK == 0 and context.MPI_SIZE > 1: # combine all the parallel coverage data files into one and make # the XML and HTML reports for the whole run. combinedCoverage = coverage.Coverage( config_file=os.path.join(context.RES, "coveragerc"), debug=["dataio"], ) combinedCoverage.config.parallel = True # combine does delete the files it merges combinedCoverage.combine() combinedCoverage.save() combinedCoverage.html_report() combinedCoverage.xml_report()
def test_invalidSetVerbosityByRank(self): """Test that the log verbosity setting fails if the integer is invalid.""" with self.assertRaises(KeyError): runLog.setVerbosity(5000)
def test_setVerbosityFromString(self): """Test that the log verbosity can be set with a string.""" expectedStrVerbosity = runLog.getLogVerbosityLevels()[0] verbosityRank = runLog.getLogVerbosityRank(expectedStrVerbosity) runLog.setVerbosity(expectedStrVerbosity) self.assertEqual(verbosityRank, runLog.getVerbosity())
def parse_args(self, args): self.parser.parse_args(args, namespace=self.args) runLog.setVerbosity(self.cs["verbosity"])
def loadTestReactor(inputFilePath=TEST_ROOT, customSettings=None, inputFileName="armiRun.yaml"): r""" Loads a test reactor. Can be used in other test modules. Parameters ---------- inputFilePath : str Path to the directory of the armiRun.yaml input file. customSettings : dict with str keys and values of any type For each key in customSettings, the cs which is loaded from the armiRun.yaml will be overwritten to the value given in customSettings for that key. Returns ------- o : Operator r : Reactor """ # TODO: it would be nice to have this be more stream-oriented. Juggling files is # devilishly difficult. global TEST_REACTOR fName = os.path.join(inputFilePath, inputFileName) customSettings = customSettings or {} isPickeledReactor = fName == ARMI_RUN_PATH and customSettings == {} assemblies.resetAssemNumCounter() if isPickeledReactor and TEST_REACTOR: # return test reactor only if no custom settings are needed. o, r, assemNum = cPickle.loads(TEST_REACTOR) assemblies.setAssemNumCounter(assemNum) settings.setMasterCs(o.cs) o.reattach(r, o.cs) return o, r cs = settings.Settings(fName=fName) # Overwrite settings if desired if customSettings: for settingKey, settingVal in customSettings.items(): cs[settingKey] = settingVal if "verbosity" not in customSettings: runLog.setVerbosity("error") settings.setMasterCs(cs) cs["stationaryBlocks"] = [] cs["nCycles"] = 3 o = operators.factory(cs) r = reactors.loadFromCs(cs) o.initializeInterfaces(r) # put some stuff in the SFP too. for a in range(10): a = o.r.blueprints.constructAssem(o.cs, name="feed fuel") o.r.core.sfp.add(a) o.r.core.regenAssemblyLists() if isPickeledReactor: # cache it for fast load for other future tests # protocol=2 allows for classes with __slots__ but not __getstate__ to be pickled TEST_REACTOR = cPickle.dumps((o, o.r, assemblies.getAssemNum()), protocol=2) return o, o.r
def convertDatabase( inputDBName: str, outputDBName: Optional[str] = None, outputVersion: Optional[str] = None, nodes: Optional[List[Tuple[int, int]]] = None, ): """ Convert database files between different versions. Parameters ---------- inputDB name of the complete hierarchy database outputDB name of the output database that should be consistent with XTView outputVersion version of the database to convert to. Defaults to latest version nodes optional list of specific (cycle,node)s to convert """ dbIn = databaseFactory(inputDBName, permission=Permissions.READ_ONLY_FME) if dbIn.version == outputVersion: runLog.important( "The input database ({}) appears to already be in the desired " "format ({})".format(inputDBName, dbIn.version) ) return outputDBName = outputDBName or "-converted".join(os.path.splitext(inputDBName)) dbOut = databaseFactory( outputDBName, permission=Permissions.CREATE_FILE_TIE, version=outputVersion ) # each DB load resets the verbosity to that of the run. Here we allow # conversion users to overpower it. conversionVerbosity = runLog.getVerbosity() runLog.extra(f"Converting {dbIn} to DB version {outputVersion}") with dbIn, dbOut: dbNodes = list(dbIn.genTimeSteps()) if nodes is not None and any(node not in dbNodes for node in nodes): raise RuntimeError( "Some of the requested nodes are not in the source database.\n" "Requested: {}\n" "Present: {}".format(nodes, dbNodes) ) # Making the bold assumption that we are working with HDF5 h5In = _getH5File(dbIn) h5Out = _getH5File(dbOut) dbOut.writeInputsToDB(None, *dbIn.readInputsFromDB()) for cycle, timeNode in dbNodes: if nodes is not None and (cycle, timeNode) not in nodes: continue runLog.extra(f"Converting cycle={cycle}, timeNode={timeNode}") timeStepsInOutDB = set(dbOut.genTimeSteps()) r = dbIn.load(cycle, timeNode) if (r.p.cycle, r.p.timeNode) in timeStepsInOutDB: runLog.warning( "Time step ({}, {}) is already in the output DB. This " "is probably due to repeated cycle/timeNode in the source DB; " "deleting the existing time step and re-writing".format( r.p.cycle, r.p.timeNode ) ) del dbOut[r.p.cycle, r.p.timeNode, None] runLog.setVerbosity(conversionVerbosity) dbOut.writeToDB(r) for auxPath in dbIn.genAuxiliaryData((cycle, timeNode)): name = next(reversed(auxPath.split("/"))) auxOutPath = dbOut.getAuxiliaryDataPath((cycle, timeNode), name) runLog.important( "Copying auxiliary data for time ({}, {}): {} -> {}".format( cycle, timeNode, auxPath, auxOutPath ) ) h5In.copy(auxPath, h5Out, name=auxOutPath)