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 test_pluginSettings(self): pm = armi.getPluginManagerOrFail() pm.register(DummyPlugin1) # We have a setting; this should be fine cs = caseSettings.Settings() self.assertEqual(cs["extendableOption"], "DEFAULT") # We shouldn't have any settings from the other plugin, so this should be an # error. with self.assertRaises(vol.error.MultipleInvalid): newSettings = {"extendableOption": "PLUGIN"} cs = cs.modified(newSettings=newSettings) pm.register(DummyPlugin2) cs = caseSettings.Settings() self.assertEqual(cs["extendableOption"], "PLUGIN") # Now we should have the option from plugin 2; make sure that works cs = cs.modified(newSettings=newSettings) cs["extendableOption"] = "PLUGIN" self.assertIn("extendableOption", cs.keys()) pm.unregister(DummyPlugin2) pm.unregister(DummyPlugin1) # Now try the same, but adding the plugins in a different order. This is to make # sure that it doesnt matter if the Setting or its Options come first pm.register(DummyPlugin2) pm.register(DummyPlugin1) cs = caseSettings.Settings() self.assertEqual(cs["extendableOption"], "PLUGIN")
def getActiveInterfaceInfo(cs): """ Return a list containing information for all of the Interface classes that are present. This creates a list of tuples, each containing an Interface subclass and appropriate kwargs for adding them to an Operator stack, given case settings. There should be entries for all Interface classes that are returned from implementations of the describeInterfaces() function in modules present in the passed list of packages. The list is sorted by the ORDER specified by the module in which the specific Interfaces are described. Parameters ---------- cs : CaseSettings The case settings that activate relevant Interfaces """ interfaceInfo = [] # pylint: disable = no-member for info in armi.getPluginManagerOrFail().hook.exposeInterfaces(cs=cs): interfaceInfo += info interfaceInfo = [(iInfo.interfaceCls, iInfo.kwargs) for iInfo in sorted(interfaceInfo, key=lambda x: x.order)] return interfaceInfo
def _configureGeomOptions(): blockTypes = dict() pm = getPluginManagerOrFail() for pluginBlockTypes in pm.hook.defineBlockTypes(): for compType, blockType in pluginBlockTypes: blockTypes[compType] = blockType return blockTypes
def _configureAssemblyTypes(): assemTypes = dict() pm = getPluginManagerOrFail() for pluginAssemTypes in pm.hook.defineAssemblyTypes(): for blockType, assemType in pluginAssemTypes: assemTypes[blockType] = assemType return assemTypes
def test_ReportContents(self): with directoryChangers.TemporaryDirectoryChanger(): reportTest = newReports.ReportContent("Test") getPluginManagerOrFail().hook.getReportContents( r=self.r, cs=self.o.cs, report=reportTest, stage=newReports.ReportStage.Begin, blueprint=self.r.blueprints, ) self.assertTrue( isinstance(reportTest.sections, collections.OrderedDict)) self.assertIn("Comprehensive Report", reportTest.sections) self.assertIn("Neutronics", reportTest.sections) self.assertTrue( isinstance(reportTest.tableOfContents(), htmltree.HtmlElement))
def _prepConstruction(self, cs): """ This method initializes a bunch of information within a Blueprints object such as assigning assembly and block type numbers, resolving the nuclides in the problem, and pre-populating assemblies. Ideally, it would not be necessary at all, but the ``cs`` currently contains a bunch of information necessary to create the applicable model. If it were possible, it would be terrific to override the Yamlizable.from_yaml method to run this code after the instance has been created, but we need additional information in order to build the assemblies that is not within the YAML file. This method should not be called directly, but it is used in testing. """ if not self._prepped: self._assignTypeNums() for func in self._resolveFunctions: func(self, cs) self._resolveNuclides(cs) self._assembliesBySpecifier.clear() self.assemblies.clear() for aDesign in self.assemDesigns: a = aDesign.construct(cs, self) self._assembliesBySpecifier[aDesign.specifier] = a self.assemblies[aDesign.name] = a self._checkAssemblyAreaConsistency(cs) runLog.header( "=========== Verifying Assembly Configurations ===========") # pylint: disable=no-member armi.getPluginManagerOrFail().hook.afterConstructionOfAssemblies( assemblies=self.assemblies.values(), cs=cs) self._prepped = True
def test_addingOptions(self): # load in the plugin with extra, added options pm = getPluginManagerOrFail() pm.register(PluginAddsOptions) # modify the default/text settings YAML file to include neutronicsKernel fin = os.path.join(TEST_ROOT, "armiRun.yaml") txt = open(fin, "r").read() txt = txt.replace("\n nodeGroup:", "\n neutronicsKernel: MCNP\n nodeGroup:") fout = "test_addingOptions.yaml" open(fout, "w").write(txt) # this settings file should load fine, and test some basics cs = settings.Settings(fout) self.assertEqual(cs["burnSteps"], 2) self.assertEqual(cs["neutronicsKernel"], "MCNP")
def getOperatorClassFromSettings(cs): # pylint: disable=too-many-return-statements """Choose a operator class based on user settings (possibly from plugin). Parameters ---------- cs : Settings Returns ------- Operator : Operator Raises ------ ValueError If the Operator class cannot be determined from the settings. """ runType = cs["runType"] if runType == RunTypes.STANDARD: if armi.MPI_SIZE == 1: return Operator else: return OperatorMPI elif runType == RunTypes.SNAPSHOTS: return OperatorSnapshots plugInOperator = None for (potentialOperator ) in armi.getPluginManagerOrFail().hook.getOperatorClassFromRunType( runType=runType): if plugInOperator: raise ValueError( "More than one Operator class was " f"recognized for runType `{runType}`: " f"{plugInOperator} and {potentialOperator}. " "This is not allowed. Please adjust plugin config.") plugInOperator = potentialOperator if plugInOperator: return plugInOperator raise ValueError(f"No valid operator was found for runType: `{runType}`. " "Please adjust settings or plugin configuration.")
def __init__(self, cs): """ Construct an inspector. Parameters ---------- cs : Settings """ self.queries = [] self.cs = cs self.geomType = None self.coreSymmetry = None self._inspectBlueprints() self._setGeomType() self._inspectSettings() # Gather and attach validators from all plugins # This runs on all registered plugins, not just active ones. pluginQueries = getPluginManagerOrFail().hook.defineSettingsValidators( inspector=self) for queries in pluginQueries: self.queries.extend(queries)
def _resolveSystemType(typ: str): # Loop over all plugins that could be attached and determine if any # tell us how to build a specific systems attribute. Sub-optimial # as this check is called for each system (e.g., core, spent fuel pool). # It is assumed that the number of systems is currently low enough to justify # this structure. manager = getPluginManagerOrFail() # Only need this to handle the case we don't find the system we expect seen = set() for options in manager.hook.defineSystemBuilders(): for key, builder in options.items(): # Take the first match we find. This would allow other plugins to # define a new core builder before finding those defined by the # ReactorPlugin if key == typ: return builder seen.add(key) raise ValueError( "Could not determine an appropriate class for handling a " "system of type `{}`. Supported types are {}.".format( typ, sorted(seen)))
def test_kineticsParameterAssignment(self): """Test that the delayed neutron fraction and precursor decay constants are applied from settings.""" def _getModifiedSettings(customSettings): cs = settings.Settings() newSettings = {} for key, val in customSettings.items(): newSettings[key] = val return cs.modified(newSettings=newSettings) r = tests.getEmptyHexReactor() self.assertIsNone(r.core.p.beta) self.assertIsNone(r.core.p.betaComponents) self.assertIsNone(r.core.p.betaDecayConstants) # Test that the group-wise beta and decay constants are assigned # together given that they are the same length. r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={ "beta": [0.0] * 6, "decayConstants": [0.0] * 6, }) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) r.core.setOptionsFromCs(cs) self.assertEqual(r.core.p.beta, sum(cs["beta"])) self.assertListEqual(list(r.core.p.betaComponents), cs["beta"]) self.assertListEqual(list(r.core.p.betaDecayConstants), cs["decayConstants"]) # Test the assignment of total beta as a float r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={"beta": 0.00670}, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) self.assertEqual(r.core.p.beta, cs["beta"]) self.assertIsNone(r.core.p.betaComponents) self.assertIsNone(r.core.p.betaDecayConstants) # Test that nothing is assigned if the beta is specified as a list # without a corresponding decay constants list. r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={ "beta": [0.0] * 6, }, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) self.assertIsNone(r.core.p.beta) self.assertIsNone(r.core.p.betaComponents) self.assertIsNone(r.core.p.betaDecayConstants) # Test that 1 group beta components and decay constants can be assigned. # Since beta is a list, ensure that it's assigned to the `betaComponents` # parameter. r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={ "beta": [0.0], "decayConstants": [0.0] }, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) self.assertEqual(r.core.p.beta, sum(cs["beta"])) self.assertListEqual(list(r.core.p.betaComponents), cs["beta"]) self.assertListEqual(list(r.core.p.betaDecayConstants), cs["decayConstants"]) # Test that decay constants are not assigned without a corresponding # group-wise beta input. r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={"decayConstants": [0.0] * 6}, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) self.assertIsNone(r.core.p.beta) self.assertIsNone(r.core.p.betaComponents) self.assertIsNone(r.core.p.betaDecayConstants) # Test that decay constants are not assigned without a corresponding # group-wise beta input. This also demonstrates that the total beta # is still assigned. r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={ "decayConstants": [0.0] * 6, "beta": 0.0 }, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) self.assertEqual(r.core.p.beta, cs["beta"]) self.assertIsNone(r.core.p.betaComponents) self.assertIsNone(r.core.p.betaDecayConstants) # Test the demonstrates that None values are acceptable # and that nothing is assigned. r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={ "decayConstants": None, "beta": None }, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) self.assertEqual(r.core.p.beta, cs["beta"]) self.assertIsNone(r.core.p.betaComponents) self.assertIsNone(r.core.p.betaDecayConstants) # Test that an error is raised if the decay constants # and group-wise beta are inconsistent sizes with self.assertRaises(ValueError): r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={ "decayConstants": [0.0] * 6, "beta": [0.0] }, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) # Test that an error is raised if the decay constants # and group-wise beta are inconsistent sizes with self.assertRaises(ValueError): r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={ "decayConstants": [0.0] * 6, "beta": [0.0] * 5 }, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) # The following tests check the voluptuous schema definition. This # ensures that anything except NoneType, [float], float are not valid # inputs. with self.assertRaises(vol.AnyInvalid): r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={"decayConstants": [1]}, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) with self.assertRaises(vol.AnyInvalid): r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={"beta": [1]}, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) with self.assertRaises(vol.AnyInvalid): r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={"beta": 1}, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs) with self.assertRaises(vol.AnyInvalid): r = tests.getEmptyHexReactor() cs = _getModifiedSettings(customSettings={"beta": (1, 2, 3)}, ) getPluginManagerOrFail().hook.onProcessCoreLoading(core=r.core, cs=cs)
def invoke(self): nodes = self.args.nodes if self.args.h5db is None: # Just do begining stuff, no database is given... if self.cs is not None: site = createReportFromSettings(cs) if self.args.view: webbrowser.open(site) else: raise RuntimeError( "No Settings with Blueprint or Database, cannot gerenate a report" ) else: report = reports.ReportContent("Overview") pm = getPluginManagerOrFail() db = databaseFactory(self.args.h5db, "r") if self.args.bp is not None: blueprint = self.args.bp with db: with directoryChangers.ForcedCreationDirectoryChanger( "reportsOutputFiles"): dbNodes = list(db.genTimeSteps()) cs = db.loadCS() if self.args.bp is None: blueprint = db.loadBlueprints() r = reactors.factory(cs, blueprint) report.title = r.name pluginContent = getPluginManagerOrFail( ).hook.getReportContents( r=r, cs=cs, report=report, stage=reports.ReportStage.Begin, blueprint=blueprint, ) stage = reports.ReportStage.Standard for cycle, node in dbNodes: if nodes is not None and (cycle, node) not in nodes: continue if (self.args.min_node is not None and (cycle, node) < self.args.min_node): continue if (self.args.max_node is not None and (cycle, node) > self.args.max_node): continue r = db.load(cycle, node) cs = db.loadCS() pluginContent = pm.hook.getReportContents( r=r, cs=cs, report=report, stage=stage, blueprint=blueprint) stage = reports.ReportStage.End pluginContent = pm.hook.getReportContents( r=r, cs=cs, report=report, stage=stage, blueprint=blueprint) site = report.writeReports() if self.args.view: webbrowser.open(site)