diff --git a/armi/bookkeeping/db/database3.py b/armi/bookkeeping/db/database3.py index 425214f7d..ba9b5c4da 100644 --- a/armi/bookkeeping/db/database3.py +++ b/armi/bookkeeping/db/database3.py @@ -99,6 +99,7 @@ from armi.bookkeeping.db import database from armi.reactor import geometry from armi.utils.textProcessors import resolveMarkupInclusions +from armi.nucDirectory import nuclideBases from armi.settings.fwSettings.databaseSettings import CONF_SYNC_AFTER_WRITE @@ -1147,6 +1148,39 @@ def _writeParams(self, h5group, comps): "{}".format(paramDef.name, data) ) raise + if isinstance(c, Block): + self._addHomogenizedNumberDensityParams(comps, g) + + @staticmethod + def _addHomogenizedNumberDensityParams(blocks, h5group): + """ + Create on-the-fly block homog. number density params for XTVIEW viewing. + + Long ago, composition was stored on block params. No longer; they are on the component + numberDensity params. These block-level params, are still useful to see compositions + in some visualization tools. Rather than keep them on the reactor model, we + dynamically compute them here and slap them in the database. These are ignored + upon reading and will not affect the results. + + Remove this once a better viz tool can view composition distributions. + Also remove the try/except in ``_readParams`` + """ + nucNames = sorted( + list(set(nucName for b in blocks for nucName in b.getNuclides())) + ) + nucBases = [nuclideBases.byName[nn] for nn in nucNames] + # it's faster to loop over blocks first and get all number densities from each + # than it is to get one nuclide at a time from each block because of area fraction + # calculations. So we use some RAM here instead. + nucDensityMatrix = [] + for block in blocks: + nucDensityMatrix.append(block.getNuclideNumberDensities(nucNames)) + nucDensityMatrix = numpy.array(nucDensityMatrix) + for ni, nb in enumerate(nucBases): + # the nth column is a vector of nuclide densities for this nuclide across all blocks + h5group.create_dataset( + nb.getDatabaseName(), data=nucDensityMatrix[:, ni], compression="gzip" + ) @staticmethod def _readParams(h5group, compTypeName, comps): @@ -1163,7 +1197,15 @@ def _readParams(h5group, compTypeName, comps): while paramName in renames: paramName = renames[paramName] - pDef = pDefs[paramName] + try: + pDef = pDefs[paramName] + except KeyError: + if re.match(r"^n[A-Z][a-z]?\d*", paramName): + # This is a temporary viz param made by _addHomogenizedNumberDensities + # ignore it safely + continue + else: + raise data = dataSet[:] attrs = _resolveAttrs(dataSet.attrs, h5group) diff --git a/armi/bookkeeping/db/tests/test_database3.py b/armi/bookkeeping/db/tests/test_database3.py index 1cc2120ca..0d563d52f 100644 --- a/armi/bookkeeping/db/tests/test_database3.py +++ b/armi/bookkeeping/db/tests/test_database3.py @@ -17,11 +17,9 @@ import numpy import h5py -from armi.bookkeeping import db from armi.bookkeeping.db import database3 from armi.reactor import grids from armi.reactor.tests import test_reactors -from armi.settings import caseSettings from armi.tests import TEST_ROOT diff --git a/armi/bookkeeping/db/tests/test_xtviewdb.py b/armi/bookkeeping/db/tests/test_xtviewdb.py index aca206b04..c1a0b7927 100644 --- a/armi/bookkeeping/db/tests/test_xtviewdb.py +++ b/armi/bookkeeping/db/tests/test_xtviewdb.py @@ -277,7 +277,7 @@ def test_readAPI(self): self.r.p.cycle = 0 self.r.p.timeNode = 0 self.db.writeToDB(self.r) - data = self.db.readBlockParam("nU235", 0) + data = self.db.readBlockParam("enrichmentBOL", 0) self.assertTrue(data is not None) data = self.db.readBlockParam("spaghetti carbonara", 0) diff --git a/armi/physics/fuelPerformance/utils.py b/armi/physics/fuelPerformance/utils.py index 88a476fb8..ce0c27252 100644 --- a/armi/physics/fuelPerformance/utils.py +++ b/armi/physics/fuelPerformance/utils.py @@ -98,7 +98,6 @@ def applyFuelDisplacement(block, displacementInCm): fuel.setDimension("od", newHotODInCm, retainLink=True, cold=False) # reduce number density of fuel to conserve number of atoms (and mass) fuel.changeNDensByFactor(originalHotODInCm ** 2 / newHotODInCm ** 2) - block.buildNumberDensityParams() def gasConductivityCorrection(tempInC: float, porosity: float, morphology: int = 2): diff --git a/armi/reactor/blockParameters.py b/armi/reactor/blockParameters.py index a2ea1da9c..4c3b8c6ef 100644 --- a/armi/reactor/blockParameters.py +++ b/armi/reactor/blockParameters.py @@ -1608,22 +1608,6 @@ def xsTypeNum(self, value): # pylint: disable=method-hidden location=ParamLocation.AVERAGE, ) - # TODO: this should be replaced with a number density vector (array) and a list of - # nuclides on the Reactor - with pDefs.createBuilder( - location=ParamLocation.AVERAGE, default=0.0, categories=["number densities"] - ) as pb: - assert nuclideBases.instances, ( - "Nuclide Bases have not been instantiated yet; cannot produce parameters " - "for them." - ) - for nuc in nuclideBases.instances: - pb.defParam( - nuc.getDatabaseName(), - units="#/barn-cm", - description="{} number density".format(nuc.name), - ) - with pDefs.createBuilder(location=ParamLocation.AVERAGE) as pb: pb.defParam("distortionReactivity", units="?", description="?") diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index 2e832cfe8..1f78d92f1 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -562,71 +562,6 @@ def getMicroSuffix(self): else: return xsType + bu - def setNumberDensity(self, nucName, newHomogNDens): - """ - Adds an isotope to the material or changes an existing isotope's number density - - Parameters - ---------- - nuc : str - a nuclide name like U235, PU240, FE - newHomogNDens : float - number density to set in units of atoms/barn-cm, which are equal to - atoms/cm^3*1e24 - - See Also - -------- - getNumberDensity : gets the density of a nuclide - """ - composites.Composite.setNumberDensity(self, nucName, newHomogNDens) - self.setNDensParam(nucName, newHomogNDens) - - def setNumberDensities(self, numberDensities): - """ - Update number densities. - - Any nuclide in the block but not in numberDensities will be set to zero. - - Special behavior for blocks: update block-level params for DB viewing/loading. - """ - composites.Composite.setNumberDensities(self, numberDensities) - for nucName in self.getNuclides(): - # make sure to clear out any non-listed number densities - self.setNDensParam(nucName, numberDensities.get(nucName, 0.0)) - - def updateNumberDensities(self, numberDensities): - """Set one or more multiple number densities. Leaves unlisted number densities alone.""" - composites.Composite.updateNumberDensities(self, numberDensities) - for nucName, ndens in numberDensities.items(): - self.setNDensParam(nucName, ndens) - - def buildNumberDensityParams(self, nucNames=None): - """ - Copy homogenized density onto self.p for storing in the DB. - - Notes - ----- - Recall that actual number densities are not the same as the number - density params (they're really stored on the components). These - params are still useful for plotting block-level number density - information in database viewers, etc. - """ - if nucNames is None: - nucNames = self.getNuclides() - nucBases = [nuclideBases.byName[nn] for nn in nucNames] - nucDensities = self.getNuclideNumberDensities(nucNames) - for nb, ndens in zip(nucBases, nucDensities): - self.p[nb.getDatabaseName()] = ndens - - def setNDensParam(self, nucName, ndens): - """ - Set a block-level param with the homog. number density of a nuclide. - - This can be read by the database in restart runs. - """ - n = nuclideBases.byName[nucName] - self.p[n.getDatabaseName()] = ndens - def setMass(self, nucName, mass, **kwargs): """ Sets the mass in a block and adjusts the density of the nuclides in the block. @@ -787,8 +722,6 @@ def adjustUEnrich(self, newEnrich): self.setNumberDensity("U235", tU * newEnrich) self.setNumberDensity("U238", tU * (1.0 - newEnrich)) - # fix up the params and burnup tracking. - self.buildNumberDensityParams() self.completeInitialLoading() def adjustSmearDensity(self, value, bolBlock=None): @@ -842,7 +775,6 @@ def adjustSmearDensity(self, value, bolBlock=None): fuel.setDimension("od", newOD) # update things like hm at BOC and smear density parameters. - self.buildNumberDensityParams() self.completeInitialLoading(bolBlock=bolBlock) def adjustCladThicknessByOD(self, value): @@ -1917,7 +1849,7 @@ def getLargestComponent(self, dimension): largestComponent = c return largestComponent - def setPitch(self, val, updateBolParams=False, updateNumberDensityParams=True): + def setPitch(self, val, updateBolParams=False): """ Sets outer pitch to some new value. @@ -1943,9 +1875,6 @@ def setPitch(self, val, updateBolParams=False, updateNumberDensityParams=True): if updateBolParams: self.completeInitialLoading() - if updateNumberDensityParams: - # may not want to do this if you will do it shortly thereafter. - self.buildNumberDensityParams() def getMfp(self, gamma=False): r"""calculates the mean free path for neutron or gammas in this block. @@ -2748,7 +2677,7 @@ def getMaxArea(self): xw, yw = self.getPitch() return xw * yw - def setPitch(self, val, updateBolParams=False, updateNumberDensityParams=True): + def setPitch(self, val, updateBolParams=False): raise NotImplementedError( "Directly setting the pitch of a cartesian block is currently not supported." ) diff --git a/armi/reactor/blueprints/blockBlueprint.py b/armi/reactor/blueprints/blockBlueprint.py index 66c17e142..fba526787 100644 --- a/armi/reactor/blueprints/blockBlueprint.py +++ b/armi/reactor/blueprints/blockBlueprint.py @@ -154,7 +154,6 @@ def construct( b.p.heightBOL = height # for fuel performance b.p.xsType = xsType b.setBuLimitInfo(cs) - b.buildNumberDensityParams(nucNames=blueprint.allNuclidesInProblem) b = self._mergeComponents(b) b.verifyBlockDims() b.spatialGrid = spatialGrid diff --git a/armi/reactor/reactors.py b/armi/reactor/reactors.py index dea04d320..a8809d8a6 100644 --- a/armi/reactor/reactors.py +++ b/armi/reactor/reactors.py @@ -2370,12 +2370,12 @@ def growToFullCore(self, cs): return converter - def setPitchUniform(self, pitchInCm, updateNumberDensityParams=True): + def setPitchUniform(self, pitchInCm): """ set the pitch in all blocks """ for b in self.getBlocks(): - b.setPitch(pitchInCm, updateNumberDensityParams=updateNumberDensityParams) + b.setPitch(pitchInCm) # have to update the 2-D reactor mesh too. self.spatialGrid.changePitch(pitchInCm) diff --git a/armi/reactor/tests/test_assemblies.py b/armi/reactor/tests/test_assemblies.py index 747ca95c6..e8ec1b8fe 100644 --- a/armi/reactor/tests/test_assemblies.py +++ b/armi/reactor/tests/test_assemblies.py @@ -208,22 +208,6 @@ def setUp(self): "buRate": 0.0, "eqRegion": -1, "id": 212.0, - "nC": 0.0002082939655729809, - "nCr": 0.002886865228214986, - "nFe": 0.018938452726904774, - "nMn55": 0.00013661373306056112, - "nMo": 0.0001303849595025718, - "nNa23": 0.009129000958507699, - "nNi": 0.00010656078341023939, - "nSi": 0.00017815341899661907, - "nU235": 0.0011370748450841566, - "nU238": 0.01010441040669961, - "nV": 6.138819542030269e-05, - "nW182": 9.01562910227868e-06, - "nW183": 4.868378420270543e-06, - "nW184": 1.042392172896758e-05, - "nW186": 9.671859458339502e-06, - "nZr": 0.003255278491569621, "pdens": 10.0, "percentBu": 25.3, "power": 100000.0, diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index 533810632..e5508fcc6 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -534,10 +534,6 @@ def test_setNumberDensities(self): ref = refDict[nuc] places = 6 self.assertAlmostEqual(cur, ref, places=places) - nucBase = nuclideBases.byName[nuc] - self.assertAlmostEqual( - b.p[nucBase.getDatabaseName()], ref - ) # required for DB viewing/loading # make sure U235 stayed fully contained in the fuel component fuelC = b.getComponent(Flags.FUEL)