def _loadAssemblies(self, cs, container, gridDesign, gridContents, bp): runLog.header( "=========== Adding Assemblies to {} ===========".format(container) ) badLocations = set() for locationInfo, aTypeID in gridContents.items(): newAssembly = bp.constructAssem(gridDesign.geom, cs, specifier=aTypeID) i, j = locationInfo loc = container.spatialGrid[i, j, 0] if ( container.symmetry == geometry.THIRD_CORE + geometry.PERIODIC and not container.spatialGrid.isInFirstThird( loc, includeTopEdge=True ) ): badLocations.add(loc) container.add(newAssembly, loc) if badLocations: raise ValueError( "Geometry core map xml had assemblies outside the " "first third core, but had third core symmetry. \n" "Please update symmetry to be `full core` or " "remove assemblies outside the first third. \n" "The locations outside the first third are {}".format(badLocations) )
def initializeInterfaces(self, r): """ Attach the reactor to the operator and initialize all interfaces. This does not occur in `__init__` so that the ARMI operator can be initialized before a reactor is created, which is useful for summarizing the case information quickly. Parameters ---------- r : Reactor The Reactor object to attach to this Operator. """ self.r = r r.o = self # TODO: this is only necessary for fuel-handler hacking with self.timer.getTimer("Interface Creation"): self.createInterfaces() self._processInterfaceDependencies() if armi.MPI_RANK == 0: runLog.header( "=========== Interface Stack Summary ===========") runLog.info(reportingUtils.getInterfaceStackSummary(self)) self.interactAllInit() else: self._attachInterfaces() self._loadRestartData()
def _writeCaseInformation(o, cs): """Create a table that contains basic case information.""" caseInfo = [ (strings.Operator_CaseTitle, cs.caseTitle), ( strings.Operator_CaseDescription, "{0}".format( textwrap.fill(cs["comment"], break_long_words=False)), ), ( strings.Operator_TypeOfRun, "{} - {}".format(cs["runType"], o.__class__.__name__), ), (strings.Operator_CurrentUser, armi.USER), (strings.Operator_ArmiCodebase, armi.ROOT), (strings.Operator_WorkingDirectory, os.getcwd()), (strings.Operator_PythonInterperter, sys.version), (strings.Operator_MasterMachine, os.environ.get("COMPUTERNAME", "?")), (strings.Operator_NumProcessors, armi.MPI_SIZE), (strings.Operator_Date, armi.START_TIME), ] runLog.header("=========== Case Information ===========") runLog.info(tabulate.tabulate(caseInfo, tablefmt="armi"))
def summarizeMaterialData(container): """ Create a summary of the material objects and source data for a reactor container. Parameters ---------- container : Core object Any Core object with Blocks and Components defined. """ def _getMaterialSourceData(materialObj): return (materialObj.DATA_SOURCE, materialObj.propertyRangeUpdated) runLog.header( "=========== Summarizing Source of Material Data for {} ===========". format(container)) materialNames = set() materialData = [] for c in container.iterComponents(): if c.material.name in materialNames: continue sourceLocation, wasModified = _getMaterialSourceData(c.material) materialData.append((c.material.name, sourceLocation, wasModified)) materialNames.add(c.material.name) materialData = sorted(materialData) runLog.info( tabulate.tabulate( tabular_data=materialData, headers=[ "Material Name", "Source Location", "Property Data was Modified\nfrom the Source?", ], tablefmt="armi", )) return materialData
def _loadAssemblies(self, cs, container, gridContents, bp): runLog.header("=========== Adding Assemblies to {} ===========".format( container)) badLocations = set() for locationInfo, aTypeID in gridContents.items(): newAssembly = bp.constructAssem(cs, specifier=aTypeID) if not cs["inputHeightsConsideredHot"]: if not newAssembly.hasFlags(Flags.CONTROL): self.axialExpChngr.setAssembly(newAssembly) self.axialExpChngr.expansionData.computeThermalExpansionFactors( ) self.axialExpChngr.axiallyExpandAssembly(thermal=True) i, j = locationInfo loc = container.spatialGrid[i, j, 0] try: container.add(newAssembly, loc) except LookupError: badLocations.add(loc) if badLocations: raise ValueError( "Geometry core map xml had assemblies outside the " "first third core, but had third core symmetry. \n" "Please update symmetry to be `full core` or " "remove assemblies outside the first third. \n" "The locations outside the first third are {}".format( badLocations))
def printInterfaceSummary(self, interface, interactionName, statePointIndex, *args): """ Log which interaction point is about to be executed. This looks better as multiple lines but it's a lot easier to grep as one line. We leverage newlines instead of long banners to save disk space. """ nodeInfo = self._expandCycleAndTimeNodeArgs(*args) line = "=========== {:02d} - {:30s} {:15s} ===========".format( statePointIndex, interface.name, interactionName + nodeInfo) runLog.header(line)
def _interactAll(self, interactionName, activeInterfaces, *args): """ Loop over the supplied activeInterfaces and perform the supplied interaction on each. Notes ----- This is the base method for the other ``interactAll`` methods. """ interactMethodName = "interact{}".format(interactionName) printMemUsage = self.cs["verbosity"] == "debug" and self.cs["debugMem"] if self.cs["debugDB"]: self._debugDB(interactionName, "start", 0) halt = False cycleNodeTag = self._expandCycleAndTimeNodeArgs(*args) runLog.header("=========== Triggering {} Event ===========".format( interactionName + cycleNodeTag)) for statePointIndex, interface in enumerate(activeInterfaces, start=1): self.printInterfaceSummary(interface, interactionName, statePointIndex, *args) # maybe make this a context manager if printMemUsage: memBefore = memoryProfiler.PrintSystemMemoryUsageAction() memBefore.broadcast() memBefore.invoke(self, self.r, self.cs) interactionMessage = " {} interacting with {} ".format( interactionName, interface.name) with self.timer.getTimer(interactionMessage): interactMethod = getattr(interface, interactMethodName) halt = halt or interactMethod(*args) if self.cs["debugDB"]: self._debugDB(interactionName, interface.name, statePointIndex) if printMemUsage: memAfter = memoryProfiler.PrintSystemMemoryUsageAction() memAfter.broadcast() memAfter.invoke(self, self.r, self.cs) memAfter -= memBefore memAfter.printUsage("after {:25s} {:15s} interaction".format( interface.name, interactionName)) self._checkCsConsistency() runLog.header("=========== Completed {} Event ===========\n".format( interactionName + cycleNodeTag)) return halt
def _writeInputFileInformation(cs): """Create a table that contains basic input file information.""" inputFileData = [] for (label, fileName, shaHash) in _listInputFiles(cs): inputFileData.append((label, fileName, shaHash)) runLog.header("=========== Input File Information ===========") runLog.info( tabulate.tabulate( inputFileData, headers=["Input Type", "Path", "SHA-1 Hash"], tablefmt="armi", ))
def checkInputs(self): """ Checks ARMI inputs for consistency. Returns ------- bool True if the inputs are all good, False otherwise """ with DirectoryChanger(self.cs.inputDirectory): operatorClass = operators.getOperatorClassFromSettings(self.cs) inspector = operatorClass.inspector(self.cs) inspectorIssues = [query for query in inspector.queries if query] if armi.CURRENT_MODE == armi.Mode.Interactive: # if interactive, ask user to deal with settings issues inspector.run() else: # when not interactive, just print out the info in the stdout queryData = [] for i, query in enumerate(inspectorIssues, start=1): queryData.append(( i, textwrap.fill(query.statement, width=50, break_long_words=False), textwrap.fill(query.question, width=50, break_long_words=False), query.autoResolved, )) if queryData: runLog.header("=========== Input Queries ===========") runLog.info( tabulate.tabulate( queryData, headers=[ "Number", "Statement", "Question", "Auto-resolved", ], tablefmt="armi", )) return not any(inspectorIssues)
def _writeReactorCycleInformation(o, cs): """Verify that all the operating parameters are defined for the same number of cycles.""" operatingData = [ ("Reactor Thermal Power (MW):", cs["power"] / units.WATTS_PER_MW), ("Number of Cycles:", cs["nCycles"]), ] operatingParams = { "Cycle Lengths:": o.cycleLengths, "Availability Factors:": o.availabilityFactors, "Power Fractions:": o.powerFractions, } for name, param in operatingParams.items(): paramStr = [str(p) for p in param] operatingData.append((name, textwrap.fill(", ".join(paramStr)))) runLog.header("=========== Reactor Cycle Information ===========") runLog.info(tabulate.tabulate(operatingData, tablefmt="armi"))
def _modifyGeometry(self, container, gridDesign): """Perform post-load geometry conversions like full core, edge assems.""" # all cases should have no edge assemblies. They are added ephemerally when needed from armi.reactor.converters import geometryConverters # circular imports runLog.header( "=========== Applying Geometry Modifications ===========") converter = geometryConverters.EdgeAssemblyChanger() converter.removeEdgeAssemblies(container) # now update the spatial grid dimensions based on the populated children # (unless specified on input) if not gridDesign.latticeDimensions: runLog.info( "Updating spatial grid pitch data for {} geometry".format( container.geomType)) if container.geomType == geometry.HEX: container.spatialGrid.changePitch(container[0][0].getPitch()) elif container.geomType == geometry.CARTESIAN: xw, yw = container[0][0].getPitch() container.spatialGrid.changePitch(xw, yw)
def _writeMachineInformation(): """Create a table that contains basic machine and rank information.""" if armi.MPI_SIZE > 1: processorNames = armi.MPI_NODENAMES uniqueNames = set(processorNames) nodeMappingData = [] for uniqueName in uniqueNames: matchingProcs = [ str(rank) for rank, procName in enumerate(processorNames) if procName == uniqueName ] numProcessors = str(len(matchingProcs)) nodeMappingData.append( (uniqueName, numProcessors, ", ".join(matchingProcs))) runLog.header("=========== Machine Information ===========") runLog.info( tabulate.tabulate( nodeMappingData, headers=["Machine", "Number of Processors", "Ranks"], tablefmt="armi", ))
def _loadAssemblies(self, cs, container, gridDesign, gridContents, bp): runLog.header("=========== Adding Assemblies to {} ===========".format( container)) badLocations = set() for locationInfo, aTypeID in gridContents.items(): newAssembly = bp.constructAssem(cs, specifier=aTypeID) i, j = locationInfo loc = container.spatialGrid[i, j, 0] try: container.add(newAssembly, loc) except exceptions.SymmetryError: badLocations.add(loc) if badLocations: raise ValueError( "Geometry core map xml had assemblies outside the " "first third core, but had third core symmetry. \n" "Please update symmetry to be `full core` or " "remove assemblies outside the first third. \n" "The locations outside the first third are {}".format( badLocations))
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 _loadAssemblies(self, cs, container, gridDesign, gridContents, bp): runLog.header("=========== Adding Assemblies to {} ===========".format( container)) badLocations = set() for locationInfo, aTypeID in gridContents.items(): newAssembly = bp.constructAssem(gridDesign.geom, cs, specifier=aTypeID) if gridDesign.geom in [geometry.RZT, geometry.RZ]: # in RZ, TRZ, locationInfo are upper and lower bounds in R and Theta. # We want to convert these into spatialLocator indices in the reactor's spatialGrid rad0, rad1, theta0, theta1, numAzi, numRadial = locationInfo loc = container.spatialGrid[ container.spatialGrid.indicesOfBounds( rad0, rad1, theta0, theta1)] newAssembly.p.AziMesh = numAzi newAssembly.p.RadMesh = numRadial else: ring, pos = locationInfo i, j = container.spatialGrid.getIndicesFromRingAndPos( ring, pos) loc = container.spatialGrid[i, j, 0] if (container.symmetry == geometry.THIRD_CORE + geometry.PERIODIC and not container.spatialGrid.isInFirstThird( loc, includeTopEdge=True)): badLocations.add(loc) container.add(newAssembly, loc) if badLocations: raise ValueError( "Geometry core map xml had assemblies outside the " "first third core, but had third core symmetry. \n" "Please update symmetry to be `full core` or " "remove assemblies outside the first third. \n" "The locations outside the first third are {}".format( badLocations))