def setUpClass(cls): cls.td = directoryChangers.TemporaryDirectoryChanger() cls.td.__enter__() # The database writes the settings object to the DB rather # than the original input file. This allows settings to be # changed in memory like this and survive for testing. newSettings = {"verbosity": "extra"} newSettings["nCycles"] = 2 newSettings["burnSteps"] = 3 o, _r = test_reactors.loadTestReactor(customSettings=newSettings) settings.setMasterCs(o.cs) o.interfaces = [i for i in o.interfaces if isinstance(i, (DatabaseInterface))] dbi = o.getInterface("database") dbi.enabled(True) dbi.initDB() # Main Interface normally does this # update a few parameters def writeFlux(cycle, node): for bi, b in enumerate(o.r.core.getBlocks()): b.p.flux = 1e6 * bi + cycle * 100 + node b.p.mgFlux = numpy.repeat(b.p.flux / 33, 33) o.interfaces.insert(0, MockInterface(o.r, o.cs, writeFlux)) with o: o.operate() cls.cs = o.cs cls.bp = o.r.blueprints cls.dbName = o.cs.caseTitle + ".h5" # needed for test_readWritten cls.r = o.r
def setUp(self): self.cs = settings.Settings(fName=ARMI_RUN_PATH) settings.setMasterCs(self.cs) self.o = OperatorMPI(self.cs) self.action = DistributeStateAction() self.action.o = self.o self.action.r = self.o.r
def setUp(self): cs = settings.Settings(f"{CASE_TITLE}.yaml") newSettings = {} newSettings["db"] = True newSettings["reloadDBName"] = pathlib.Path( f"{CASE_TITLE}.h5").absolute() newSettings["loadStyle"] = "fromDB" newSettings["detailAssemLocationsBOL"] = ["001-001"] newSettings["startNode"] = 1 cs = cs.modified(newSettings=newSettings) self.td = directoryChangers.TemporaryDirectoryChanger() self.td.__enter__() c = case.Case(cs) case2 = c.clone(title="armiRun") settings.setMasterCs(case2.cs) self.o = case2.initializeOperator() self.r = self.o.r self.o.getInterface("main").interactBOL() dbi = self.o.getInterface("database") # Get to the database state at the end of stack of time node 1. # The end of the interface stack is when history tracker tends to run. dbi.loadState(0, 1)
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 bootstrapArmiTestEnv(): """ Perform ARMI config appropriate for running unit tests .. tip:: This can be imported and run from other ARMI applications for test support. """ from armi.nucDirectory import nuclideBases cs = caseSettings.Settings() context.Mode.setMode(context.Mode.BATCH) settings.setMasterCs(cs) # Need to init burnChain. # see armi.cases.case.Case._initBurnChain with open(cs["burnChainFileName"]) as burnChainStream: nuclideBases.imposeBurnChain(burnChainStream) # turn on a non-interactive mpl backend to minimize errors related to # initializing Tcl in parallel tests matplotlib.use("agg") # set and create a test-specific FAST_PATH for parallel unit testing # Not all unit tests have operators, and operators are usually # responsible for making FAST_PATH, so we make it here. # It will be deleted by the atexit hook. context.activateLocalFastPath() if not os.path.exists(context.getFastPath()): os.makedirs(context.getFastPath()) # some tests need to find the TEST_ROOT via an env variable when they're # filling in templates with ``$ARMITESTBASE`` in them or opening # input files use the variable in an `!include` tag. Thus # we provide it here. os.environ["ARMITESTBASE"] = TEST_ROOT
def createReportFromSettings(cs): """ Create BEGINNING reports, given a settings file. This will construct a reactor from the given settings and create BOL reports for that reactor/settings. """ # not sure if this is necessary, but need to investigate more to understand possible # side-effects before removing. Probably better to get rid of all uses of # getMasterCs(), then we can remove all setMasterCs() calls without worrying. settings.setMasterCs(cs) blueprint = blueprints.loadFromCs(cs) r = reactors.factory(cs, blueprint) report = reports.ReportContent("Overview") pm = getPluginManagerOrFail() report.title = r.name with directoryChangers.ForcedCreationDirectoryChanger("{}-reports".format( cs.caseTitle)): _ = pm.hook.getReportContents( r=r, cs=cs, report=report, stage=reports.ReportStage.Begin, blueprint=blueprint, ) site = report.writeReports() return site
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 pytest_sessionstart(session): import armi from armi import apps print("Initializing generic ARMI Framework application") armi.configure(apps.App()) cs = caseSettings.Settings() settings.setMasterCs(cs)
def setUp(self): self.cs = settings.Settings(fName=ARMI_RUN_PATH) bp = blueprints.loadFromCs(self.cs) settings.setMasterCs(self.cs) self.o = OperatorMPI(self.cs) self.o.r = reactors.factory(self.cs, bp) self.action = DistributeStateAction() self.action.o = self.o self.action.r = self.o.r
def pytest_sessionstart(session): import armi from armi import apps from armi.nucDirectory import nuclideBases print("Initializing generic ARMI Framework application") armi.configure(apps.App()) cs = caseSettings.Settings() settings.setMasterCs(cs) # Need to init burnChain. # see armi.cases.case.Case._initBurnChain with open(cs["burnChainFileName"]) as burnChainStream: nuclideBases.imposeBurnChain(burnChainStream)
def load(self, cycle, node, cs=None, bp=None, geom=None): cs = cs or self.loadCS() settings.setMasterCs(cs) bp = bp or self.loadBlueprints() geom = geom or self.loadGeometry() if self._reactor is None: self._reactor = reactors.factory(cs, bp, geom) dbTimeStep = utils.getTimeStepNum(cycle, node, cs) self.updateFromDB(self._reactor, dbTimeStep) return self._reactor
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 __init__(self): if self.name is None: raise AttributeError( "Subclasses of EntryPoint must define a `name` class attribute" ) self.parser = argparse.ArgumentParser( prog="armi {}".format(self.name), description=self.description or self.__doc__, ) self.args = argparse.Namespace() self.cs = settings.Settings() settings.setMasterCs(self.cs) self.settingsProvidedOnCommandLine = []
def summarizeDesign(self, generateFullCoreMap=True, showBlockAxialMesh=True): """Uses the ReportInterface to create a fancy HTML page describing the design inputs.""" settings.setMasterCs(self.cs) o = self.initializeOperator() with DirectoryChanger(self.cs.inputDirectory): # There are global variables that are modified when a report is # generated, so reset it all six.moves.reload_module(report) # pylint: disable=too-many-function-args self.cs.setSettingsReport() rpi = o.getInterface("report") if rpi is None: rpi = reportInterface.ReportInterface(o.r, o.cs) rpi.generateDesignReport(generateFullCoreMap, showBlockAxialMesh) report.DESIGN.writeHTML() runLog.important("Design report summary was successfully generated")
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
def buildCase(): """Build input components and a case.""" bp = blueprints.Blueprints() bp.customIsotopics = isotopicOptions.CustomIsotopics() bp.nuclideFlags = isotopicOptions.genDefaultNucFlags() components = buildComponents() bp.blockDesigns = buildBlocks(components) bp.assemDesigns = buildAssemblies(bp.blockDesigns) bp.gridDesigns = buildGrids() bp.systemDesigns = buildSystems() cs = caseSettings.Settings() settings.setMasterCs(cs) # remove once we eliminate masterCs cs.path = None cs.caseTitle = "scripted-case" case = cases.Case(cs=cs, bp=bp) return case
def init(choice=None, fName=None, cs=None): """ Scan a directory for armi inputs and load one to interact with. Parameters ---------- choice : int, optional Automatically run with this item out of the menu that would be produced of existing xml files. fName : str, optional An actual case name to load. e.g. ntTwr1.xml cs : object, optional If supplied, supercede the other case input methods and use the object directly Examples -------- >>> o = armi.init() """ from armi import cases from armi import settings if cs is None: if fName is None: fName = settings.promptForSettingsFile(choice) cs = settings.Settings(fName) # clear out any old masterCs objects settings.setMasterCs(cs) armiCase = cases.Case(cs=cs) armiCase.checkInputs() try: return armiCase.initializeOperator() except: # Catch any and all errors. Naked exception on purpose. # Concatenate errors to the master log file. runLog.LOG.close() raise
def setUp(self): cs = settings.Settings(os.path.join(TUTORIAL_DIR, f"{CASE_TITLE}.yaml")) cs["db"] = True cs["reloadDBName"] = os.path.join(TUTORIAL_DIR, f"{CASE_TITLE}.h5") cs["loadStyle"] = "fromDB" cs["detailAssemLocationsBOL"] = ["A1001"] cs["startNode"] = 1 self.td = directoryChangers.TemporaryDirectoryChanger() self.td.__enter__() c = case.Case(cs) case2 = c.clone(title="armiRun") settings.setMasterCs(case2.cs) self.o = case2.initializeOperator() self.r = self.o.r self.o.getInterface("main").interactBOL() dbi = self.o.getInterface("database") # Get to the database state at the end of stack of time node 1. # The end of the interface stack is when history tracker tends to run. dbi.loadState(0, 1)
def setUp(self): self.cs = settings.Settings() newSettings = {"xsKernel": "MC2v2"} # don't try to expand elementals self.cs = self.cs.modified(newSettings=newSettings) settings.setMasterCs(self.cs) bp = blueprints.Blueprints() self.r = reactors.Reactor("test", bp) self.r.add(reactors.Core("Core")) inputStr = """blocks: ann fuel: &block_ann_fuel gap: shape: Circle material: Void Tinput: 20.0 Thot: 435.0 id: 0.0 mult: fuel.mult od: fuel.id fuel: shape: Circle material: UZr Tinput: 20.0 Thot: 600.0 id: 0.1 mult: 127 od: 0.8 gap1: shape: Circle material: Void Tinput: 20.0 Thot: 435.0 id: fuel.od mult: fuel.mult od: clad.id clad: shape: Circle material: HT9 Tinput: 20.0 Thot: 435.0 id: .85 mult: fuel.mult od: .95 duct: &component_type2_fuel_duct shape: Hexagon material: HT9 Tinput: 20.0 Thot: 435.0 ip: 13.00 op: 13.9 mult: 1 intercoolant: &component_type2_fuel_intercoolant shape: Hexagon material: Sodium Tinput: 435.0 Thot: 435.0 ip: duct.op mult: 1 op: 16 coolant: &component_type2_fuel_coolant shape: DerivedShape material: Sodium Tinput: 435.0 Thot: 435.0 assemblies: heights: &standard_heights [30.0] axial mesh points: &standard_axial_mesh_points [2] ann fuel: specifier: FA blocks: &inner_igniter_fuel_blocks [*block_ann_fuel] height: *standard_heights axial mesh points: *standard_axial_mesh_points hotChannelFactors: TWRPclad xs types: &inner_igniter_fuel_xs_types [D] """ self.blueprints = blueprints.Blueprints.load(inputStr) self.blueprints._prepConstruction(self.cs)
def buildTestAssemblies(): """ Build some assembly objects that will be used in testing. This builds 2 HexBlocks: * One with half UZr pins and half UTh pins * One with all UThZr pins """ caseSetting = settings.Settings() settings.setMasterCs(caseSetting) temperature = 273.0 fuelID = 0.0 fuelOD = 1.0 cladOD = 1.1 # generate a reactor with assemblies # generate components with materials nPins = 100 fuelDims = { "Tinput": temperature, "Thot": temperature, "od": fuelOD, "id": fuelID, "mult": nPins, } fuelUZr = components.Circle("fuel", "UZr", **fuelDims) fuelUTh = components.Circle("fuel UTh", "ThU", **fuelDims) fuelDims2nPins = { "Tinput": temperature, "Thot": temperature, "od": fuelOD, "id": fuelID, "mult": 2 * nPins, } fuelUThZr = components.Circle("fuel B", "UThZr", **fuelDims2nPins) cladDims = { "Tinput": temperature, "Thot": temperature, "od": cladOD, "id": fuelOD, "mult": 2 * nPins, } clad = components.Circle("clad", "HT9", **cladDims) interDims = { "Tinput": temperature, "Thot": temperature, "op": 16.8, "ip": 16.0, "mult": 1.0, } interSodium = components.Hexagon("interCoolant", "Sodium", **interDims) block = blocks.HexBlock("fuel") block2 = blocks.HexBlock("fuel") block.setType("fuel") block.setHeight(10.0) block.add(fuelUZr) block.add(fuelUTh) block.add(clad) block.add(interSodium) block.p.axMesh = 1 block.p.molesHmBOL = 1.0 block.p.molesHmNow = 1.0 block2.setType("fuel") block2.setHeight(10.0) block2.add(fuelUThZr) block2.add(clad) block2.add(interSodium) block2.p.axMesh = 1 block2.p.molesHmBOL = 2 block2.p.molesHmNow = 1.0 assemblieObjs = [] for numBlocks, blockTemplate in zip([1, 1, 5, 4], [block, block2, block, block]): assembly = assemblies.HexAssembly("testAssemblyType") assembly.spatialGrid = grids.axialUnitGrid(numBlocks) assembly.spatialGrid.armiObject = assembly for _i in range(numBlocks): newBlock = copy.deepcopy(blockTemplate) assembly.add(newBlock) assembly.calculateZCoords() assembly.reestablishBlockOrder() assemblieObjs.append(assembly) return assemblieObjs
def setUp(self): self.cs = settings.Settings(fName=ARMI_RUN_PATH) settings.setMasterCs(self.cs) self.o = OperatorMPI(cs=self.cs)
def loadOperator(pathToDb, loadCycle, loadNode): """ Return an operator given the path to a database. Parameters ---------- pathToDb : str The path of the database to load from. loadCycle : int The cycle to load the reactor state from. loadNode : int The time node to load the reactor from. See Also -------- armi.operator.Operator.loadState: A method for loading reactor state that is useful if you already have an operator and a reactor object. loadOperator varies in that it supplies these given only a database file. loadState should be used if you are in the middle of an ARMI calculation and need load a different time step. Notes ----- The operator will have a reactor attached that is loaded to the specified cycle and node. The operator will not be in the same state that it was at that cycle and node, only the reactor. Examples -------- >>> o = db.loadOperator(r"pathToDatabase", 0, 1) >>> r = o.r >>> cs = o.cs >>> r.p.timeNode 1 >>> r.getFPMass() # Note since it is loaded from step 1 there are fission products. 12345.67 """ # `import armi` doesn't work if imported at top from armi import cases from armi import settings if not os.path.exists(pathToDb): raise ValueError( f"Specified database at path {pathToDb} does not exist. \n\n" "Double check that escape characters were correctly processed.\n" "Consider sending the full path, or change directory to be the directory " "of the database." ) db = Database3(pathToDb, "r") with db: # init Case here as it keeps track of execution time and assigns a reactor # attribute. This attribute includes the time it takes to initialize the reactor # so creating a reactor from the database should be included. cs = db.loadCS() thisCase = cases.Case(cs) r = db.load(loadCycle, loadNode) settings.setMasterCs(cs) # Update the global assembly number because, if the user is loading a reactor from # blueprints and does not have access to an operator, it is unlikely that there is # another reactor that has alter the global assem num. Fresh cases typically want # this updated. database3.updateGlobalAssemblyNum(r) o = thisCase.initializeOperator(r=r) runLog.warning( "The operator provided is not in the same state as the operator was.\n" "When the reactor was at the prescribed cycle and node, it should have\n" "access to the same interface stack, but the interfaces will also not be in the " "same state.\n" "ARMI does not support loading operator states, as they are not stored." ) return o
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