def _makeBlockMesh(self, r: reactors.Reactor, indexMap) -> ET.Element: cycle = r.p.cycle node = r.p.timeNode blks = r.getChildren(deep=True, predicate=lambda o: isinstance(o, blocks.Block)) blks = sorted(blks, key=lambda b: indexMap[b.p.serialNum]) groupName = "c{}n{}".format(cycle, node) # VTK stuff turns out to be pretty flexible blockMesh = utils.VtkMesh.empty() for b in blks: blockMesh.append(utils.createBlockMesh(b)) verts = blockMesh.vertices verticesInH5 = groupName + "/blk_vertices" self._meshH5[verticesInH5] = verts topoValues = numpy.array([], dtype=numpy.int32) offset = 0 for b in blks: nVerts, cellTopo = _getTopologyFromShape(b, offset) topoValues = numpy.append(topoValues, cellTopo) offset += nVerts topoInH5 = groupName + "/blk_topology" self._meshH5[topoInH5] = topoValues return self._makeGenericMesh("Blocks", len(blks), self._meshH5[verticesInH5], self._meshH5[topoInH5])
def _makeAssemblyMesh(self, r: reactors.Reactor, indexMap) -> ET.Element: cycle = r.p.cycle node = r.p.timeNode asys = r.getChildren( deep=True, predicate=lambda o: isinstance(o, assemblies.Assembly)) asys = sorted(asys, key=lambda b: indexMap[b.p.serialNum]) groupName = "c{}n{}".format(cycle, node) # VTK stuff turns out to be pretty flexible assemMesh = utils.VtkMesh.empty() for assem in asys: assemMesh.append(utils.createAssemMesh(assem)) verts = assemMesh.vertices verticesInH5 = groupName + "/asy_vertices" self._meshH5[verticesInH5] = verts topoValues = numpy.array([], dtype=numpy.int32) offset = 0 for a in asys: nVerts, cellTopo = _getTopologyFromShape(a[0], offset) topoValues = numpy.append(topoValues, cellTopo) offset += nVerts topoInH5 = groupName + "/asy_topology" self._meshH5[topoInH5] = topoValues return self._makeGenericMesh("Assemblies", len(asys), self._meshH5[verticesInH5], self._meshH5[topoInH5])
def dumpState( self, r: reactors.Reactor, includeParams: Optional[Set[str]] = None, excludeParams: Optional[Set[str]] = None, ): """ Produce a ``<Grid>`` for a single timestep, as well as supporting HDF5 datasets. """ cycle = r.p.cycle node = r.p.timeNode timeGroupName = database3.getH5GroupName(cycle, node) dbVersion = self._inputDb.version # careful here! we are trying to use the database datasets as the source of hard # data without copying, so the order that we make the mesh needs to be the same # order as the data in the database. There is no guarantee that the way a loaded # reactor is ordered is the same way that it was ordered in the database (though # perhaps we should do some work to specify that better). We need to look at the # layout in the input database to re-order the objects. with self._inputDb as db: layout = db.getLayout(cycle, node) snToIdx = { sn: i for i, sn in zip(layout.indexInData, layout.serialNum) } blks = r.getChildren(deep=True, predicate=lambda o: isinstance(o, blocks.Block)) blks = sorted(blks, key=lambda b: snToIdx[b.p.serialNum]) assems = r.getChildren( deep=True, predicate=lambda o: isinstance(o, assemblies.Assembly)) assems = sorted(assems, key=lambda a: snToIdx[a.p.serialNum]) blockGrid = self._makeBlockMesh(r, snToIdx) self._collectObjectData(blks, timeGroupName, blockGrid) assemGrid = self._makeAssemblyMesh(r, snToIdx) self._collectObjectData(assems, timeGroupName, assemGrid) self._blockGrids.append(blockGrid) self._assemGrids.append(assemGrid) self._times.append(r.p.time)
def createReactorAssemMesh(r: reactors.Reactor) -> VtkMesh: mesh = VtkMesh.empty() assems = r.getChildren( deep=True, predicate=lambda o: isinstance(o, assemblies.Assembly)) for a in assems: mesh.append(createAssemMesh(a)) return mesh
def createReactorBlockMesh(r: reactors.Reactor) -> VtkMesh: mesh = VtkMesh.empty() blks = r.getChildren(deep=True, predicate=lambda o: isinstance(o, blocks.Block)) for b in blks: mesh.append(createBlockMesh(b)) return mesh
def initNewReactor(sourceReactor): """Build a new, yet empty, reactor with the same settings as sourceReactor Parameters ---------- sourceReactor : :py:class:`Reactor <armi.reactor.reactors.Reactor>` object. original reactor to be copied """ # developer note: deepcopy on the blueprint object ensures that all relevant blueprints # attributes are set. Simply calling blueprints.loadFromCs() just initializes # a blueprints object and may not set all necessary attributes. E.g., some # attributes are set when assemblies are added in coreDesign.construct(), however # since we skip that here, they never get set; therefore the need for the deepcopy. bp = copy.deepcopy(sourceReactor.blueprints) newReactor = Reactor(sourceReactor.o.cs.caseTitle, bp) coreDesign = bp.systemDesigns["core"] coreDesign.construct(sourceReactor.o.cs, bp, newReactor, loadAssems=False) newReactor.core.lib = sourceReactor.core.lib newReactor.core.setPitchUniform(sourceReactor.core.getAssemblyPitch()) return newReactor
def dumpState( self, r: reactors.Reactor, includeParams: Optional[Set[str]] = None, excludeParams: Optional[Set[str]] = None, ): """ Dump a reactor to a VTK file. Parameters ---------- r : reactors.Reactor The reactor state to visualize includeParams : list of str, optional A list of parameter names to include in the viz file. Defaults to all params. excludeParams : list of str, optional A list of parameter names to exclude from the output. Defaults to no params. """ cycle = r.p.cycle timeNode = r.p.timeNode # you never know... assert cycle < 1000 assert timeNode < 1000 # We avoid using cXnY, since VisIt doesn't support .pvd files, but *does* know # to lump data with similar file names and integers at the end. blockPath = "{}_blk_{:0>3}{:0>3}".format(self._baseName, cycle, timeNode) assemPath = "{}_asy_{:0>3}{:0>3}".format(self._baseName, cycle, timeNode) # include and exclude params are mutually exclusive if includeParams is not None and excludeParams is not None: raise ValueError( "includeParams and excludeParams can not both be used at the same time" ) blks = r.getChildren(deep=True, predicate=lambda o: isinstance(o, blocks.Block)) assems = r.getChildren( deep=True, predicate=lambda o: isinstance(o, assemblies.Assembly)) blockMesh = utils.createReactorBlockMesh(r) assemMesh = utils.createReactorAssemMesh(r) # collect param data blockData = _collectObjectData(blks, includeParams, excludeParams) assemData = _collectObjectData(assems, includeParams, excludeParams) # block number densities are special, since they arent stored as params blockNdens = database3.collectBlockNumberDensities(blks) # we need to copy the number density vectors to guarantee unit stride, which # pyevtk requires. Kinda seems like something it could do for us, but oh well. blockNdens = { key: numpy.array(value) for key, value in blockNdens.items() } blockData.update(blockNdens) fullPath = blockMesh.write(blockPath, blockData) self._blockFiles.append((fullPath, r.p.time)) fullPath = assemMesh.write(assemPath, assemData) self._assemFiles.append((fullPath, r.p.time))