From 6b34896e0a5112abeea362acd13ec794613b7307 Mon Sep 17 00:00:00 2001 From: John Stilley <1831479+john-science@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:59:15 -0700 Subject: [PATCH] Cleaning out the overly-specific methods in ArmiObject (#1667) --- .../lumpedFissionProduct.py | 17 ---- .../tests/test_lumpedFissionProduct.py | 5 - armi/reactor/assemblies.py | 4 + armi/reactor/blocks.py | 46 ++++++--- armi/reactor/components/__init__.py | 17 +++- armi/reactor/composites.py | 98 ------------------- armi/reactor/tests/test_assemblies.py | 25 +---- armi/reactor/tests/test_blocks.py | 29 +----- armi/reactor/tests/test_composites.py | 4 - doc/release/0.3.rst | 13 +++ 10 files changed, 68 insertions(+), 190 deletions(-) diff --git a/armi/physics/neutronics/fissionProductModel/lumpedFissionProduct.py b/armi/physics/neutronics/fissionProductModel/lumpedFissionProduct.py index 0a3f849ad..4a5c1ce75 100644 --- a/armi/physics/neutronics/fissionProductModel/lumpedFissionProduct.py +++ b/armi/physics/neutronics/fissionProductModel/lumpedFissionProduct.py @@ -180,23 +180,6 @@ def getMassFracDenom(self): massFracDenom += self[nuc] * nuc.weight return massFracDenom - def printDensities(self, lfpDens): - """ - Print number densities of nuclides within the lumped fission product. - - Parameters - ---------- - lfpDens : float - Number density (atom/b-cm) of the lumped fission product - - Notes - ----- - This multiplies the provided number density for the lumped fission - product by the yield of each nuclide. - """ - for n in sorted(self.keys()): - runLog.info("{0:6s} {1:.7E}".format(n.name, lfpDens * self[n])) - class LumpedFissionProductCollection(dict): """ diff --git a/armi/physics/neutronics/fissionProductModel/tests/test_lumpedFissionProduct.py b/armi/physics/neutronics/fissionProductModel/tests/test_lumpedFissionProduct.py index 4c8651099..9d5f7f796 100644 --- a/armi/physics/neutronics/fissionProductModel/tests/test_lumpedFissionProduct.py +++ b/armi/physics/neutronics/fissionProductModel/tests/test_lumpedFissionProduct.py @@ -118,11 +118,6 @@ def test_gaseousYieldFraction(self): # data for these tests. self.assertEqual(lfp.getGaseousYieldFraction(), 8.9000e-05) - def test_printDensities(self): - _ = nuclideBases.fromName("XE135") - lfp = self.fpd.createSingleLFPFromFile("LFP38") - lfp.printDensities(10.0) - def test_isGas(self): """Tests that a nuclide is a gas or not at STP based on its chemical phase.""" nb = nuclideBases.byName["H1"] diff --git a/armi/reactor/assemblies.py b/armi/reactor/assemblies.py index 35360e7d9..83237d31d 100644 --- a/armi/reactor/assemblies.py +++ b/armi/reactor/assemblies.py @@ -1274,6 +1274,10 @@ def rotate(self, rad): for b in self.getBlocks(): b.rotate(rad) + def isOnWhichSymmetryLine(self): + grid = self.parent.spatialGrid + return grid.overlapsWhichSymmetryLine(self.spatialLocator.getCompleteIndices()) + class HexAssembly(Assembly): """Placeholder, so users can explicitly define a hex-based Assembly.""" diff --git a/armi/reactor/blocks.py b/armi/reactor/blocks.py index 02865b7d3..e6cc08092 100644 --- a/armi/reactor/blocks.py +++ b/armi/reactor/blocks.py @@ -28,6 +28,7 @@ from armi import nuclideBases from armi import runLog from armi.bookkeeping import report +from armi.nucDirectory import elements from armi.physics.neutronics import GAMMA from armi.physics.neutronics import NEUTRON from armi.reactor import blockParameters @@ -628,17 +629,6 @@ def setBuLimitInfo(self): def getMaxArea(self): raise NotImplementedError - def getMaxVolume(self): - """ - The maximum volume of this object if it were totally full. - - Returns - ------- - vol : float - volume in cm^3. - """ - return self.getMaxArea() * self.getHeight() - def getArea(self, cold=False): """ Return the area of a block for a full core or a 1/3 core model. @@ -727,11 +717,6 @@ def getSymmetryFactor(self): """ return 1.0 - def isOnWhichSymmetryLine(self): - """Block symmetry lines are determined by the reactor, not the parent.""" - grid = self.core.spatialGrid - return grid.overlapsWhichSymmetryLine(self.spatialLocator.getCompleteIndices()) - def adjustDensity(self, frac, adjustList, returnMass=False): """ adjusts the total density of each nuclide in adjustList by frac. @@ -1648,6 +1633,35 @@ def getPinCoordinates(self): coords.append(clad.spatialLocator.getLocalCoordinates()) return coords + def getBoronMassEnrich(self): + """Return B-10 mass fraction.""" + b10 = self.getMass("B10") + b11 = self.getMass("B11") + total = b11 + b10 + if total == 0.0: + return 0.0 + return b10 / total + + def getPuMoles(self): + """Returns total number of moles of Pu isotopes.""" + nucNames = [nuc.name for nuc in elements.byZ[94].nuclides] + puN = sum(self.getNuclideNumberDensities(nucNames)) + + return ( + puN + / units.MOLES_PER_CC_TO_ATOMS_PER_BARN_CM + * self.getVolume() + * self.getSymmetryFactor() + ) + + def getUraniumMassEnrich(self): + """Returns U-235 mass fraction assuming U-235 and U-238 only.""" + u5 = self.getMass("U235") + if u5 < 1e-10: + return 0.0 + u8 = self.getMass("U238") + return u5 / (u8 + u5) + class HexBlock(Block): """ diff --git a/armi/reactor/components/__init__.py b/armi/reactor/components/__init__.py index ccb1b8c22..931adec2b 100644 --- a/armi/reactor/components/__init__.py +++ b/armi/reactor/components/__init__.py @@ -341,6 +341,17 @@ def computeVolume(self): """ return self._deriveVolumeAndArea() + def getMaxVolume(self): + """ + The maximum volume of the parent Block. + + Returns + ------- + vol : float + volume in cm^3. + """ + return self.parent.getMaxArea() * self.parent.getHeight() + def _deriveVolumeAndArea(self): """ Derive the volume and area of a ``DerivedShape``. @@ -383,7 +394,7 @@ def _deriveVolumeAndArea(self): except: # noqa: bare-except siblingArea = None - remainingVolume = self.parent.getMaxVolume() - siblingVolume + remainingVolume = self.getMaxVolume() - siblingVolume if siblingArea: remainingArea = self.parent.getMaxArea() - siblingArea @@ -393,8 +404,8 @@ def _deriveVolumeAndArea(self): f"The component areas in {self.parent} exceed the maximum " "allowable volume based on the geometry. Check that the " "geometry is defined correctly.\n" - f"Maximum allowable volume: {self.parent.getMaxVolume()} cm^3\n" - f"Volume of all non-derived shape components: {siblingVolume} cm^3\n" + f"Maximum allowable volume: {self.getMaxVolume()} " + f"cm^3\nVolume of all non-derived shape components: {siblingVolume} cm^3\n" ) runLog.error(msg) raise ValueError( diff --git a/armi/reactor/composites.py b/armi/reactor/composites.py index f0a7baf4e..633789e21 100644 --- a/armi/reactor/composites.py +++ b/armi/reactor/composites.py @@ -898,17 +898,6 @@ def getMaxArea(self): """ raise NotImplementedError() - def getMaxVolume(self): - """ - The maximum volume of this object if it were totally full. - - Returns - ------- - vol : float - volume in cm^3. - """ - raise NotImplementedError() - def getMass(self, nuclideNames=None): """ Determine the mass in grams of nuclide(s) and/or elements in this object. @@ -1765,23 +1754,6 @@ def getFissileMassEnrich(self): else: return 0.0 - def getBoronMassEnrich(self): - """Return B-10 mass fraction.""" - b10 = self.getMass("B10") - b11 = self.getMass("B11") - total = b11 + b10 - if total == 0.0: - return 0.0 - return b10 / total - - def getUraniumMassEnrich(self): - """Returns U-235 mass fraction assuming U-235 and U-238 only.""" - u5 = self.getMass("U235") - if u5 < 1e-10: - return 0.0 - u8 = self.getMass("U238") - return u5 / (u8 + u5) - def getUraniumNumEnrich(self): """Returns U-235 number fraction.""" u8 = self.getNumberDensity("U238") @@ -1790,20 +1762,6 @@ def getUraniumNumEnrich(self): u5 = self.getNumberDensity("U235") return u5 / (u8 + u5) - def getPuN(self): - """Returns total number density of Pu isotopes.""" - nucNames = [nuc.name for nuc in elements.byZ[94].nuclides] - return sum(self.getNuclideNumberDensities(nucNames)) - - def getPuMoles(self): - """Returns total number of moles of Pu isotopes.""" - return ( - self.getPuN() - / units.MOLES_PER_CC_TO_ATOMS_PER_BARN_CM - * self.getVolume() - * self.getSymmetryFactor() - ) - def calcTotalParam( self, param, @@ -2145,48 +2103,6 @@ def getHMDens(self): hmDens = sum(self.getNuclideNumberDensities(hmNuclides)) return hmDens - def getPuMass(self): - """Get the mass of Pu in this object in grams.""" - nucs = [] - for nucName in [nuc.name for nuc in elements.byZ[94].nuclides]: - nucs.append(nucName) - pu = self.getMass(nucs) - return pu - - def getPuFrac(self): - """ - Compute the Pu/HM mass fraction in this object. - - Returns - ------- - puFrac : float - The pu mass fraction in heavy metal in this assembly - """ - hm = self.getHMMass() - pu = self.getPuMass() - if hm == 0.0: - return 0.0 - else: - return pu / hm - - def getZrFrac(self): - """Return the total zr/(hm+zr) fraction in this assembly.""" - hm = self.getHMMass() - zrNucs = [nuc.name for nuc in elements.bySymbol["ZR"].nuclides] - zr = self.getMass(zrNucs) - if hm + zr > 0: - return zr / (hm + zr) - else: - return 0.0 - - def getMaxUraniumMassEnrich(self): - maxV = 0 - for child in self: - v = child.getUraniumMassEnrich() - if v > maxV: - maxV = v - return maxV - def getFPMass(self): """Returns mass of fission products in this block in grams.""" nucs = [] @@ -2597,16 +2513,6 @@ def setComponentDimensionsReport(self): return reportGroups - def printDensities(self, expandFissionProducts=False): - """Get lines that have the number densities of a object.""" - numberDensities = self.getNumberDensities( - expandFissionProducts=expandFissionProducts - ) - lines = [] - for nucName, nucDens in numberDensities.items(): - lines.append("{0:6s} {1:.7E}".format(nucName, nucDens)) - return lines - def expandAllElementalsToIsotopics(self): reactorNucs = self.getNuclides() for elemental in nuclideBases.where( @@ -3310,10 +3216,6 @@ def printContents(self, includeNuclides=True): for c in self.getChildren(): c.printContents(includeNuclides=includeNuclides) - def isOnWhichSymmetryLine(self): - grid = self.parent.spatialGrid - return grid.overlapsWhichSymmetryLine(self.spatialLocator.getCompleteIndices()) - def _genChildByLocationLookupTable(self): """Update the childByLocation lookup table.""" runLog.extra("Generating location-to-child lookup table.") diff --git a/armi/reactor/tests/test_assemblies.py b/armi/reactor/tests/test_assemblies.py index 5eaed62e7..1481d3b73 100644 --- a/armi/reactor/tests/test_assemblies.py +++ b/armi/reactor/tests/test_assemblies.py @@ -270,6 +270,10 @@ def setUp(self): self.assembly.calculateZCoords() + def test_isOnWhichSymmetryLine(self): + line = self.assembly.isOnWhichSymmetryLine() + self.assertEqual(line, 2) + def test_notesParameter(self): self.assertEqual(self.assembly.p.notes, "") @@ -488,18 +492,6 @@ def test_getFissileMass(self): ref = sum(bi.getMass(["U235", "PU239"]) for bi in self.assembly) self.assertAlmostEqual(cur, ref) - def test_getPuFrac(self): - puAssem = self.assembly.getPuFrac() - fuelBlock = self.assembly[1] - puBlock = fuelBlock.getPuFrac() - self.assertAlmostEqual(puAssem, puBlock) - - # - fuelComp = fuelBlock.getComponent(Flags.FUEL) - fuelComp.setNumberDensity("PU239", 0.012) - self.assertGreater(self.assembly.getPuFrac(), puAssem) - self.assertGreater(fuelBlock.getPuFrac(), puAssem) - def test_getMass(self): mass0 = self.assembly.getMass("U235") mass1 = sum(bi.getMass("U235") for bi in self.assembly) @@ -514,15 +506,6 @@ def test_getMass(self): fuelBlock.setMass("U238", 0.0) self.assertAlmostEqual(blockU35Mass * 2, fuelBlock.getMass("U235")) - def test_getZrFrac(self): - self.assertAlmostEqual(self.assembly.getZrFrac(), 0.1) - - def test_getMaxUraniumMassEnrich(self): - baseEnrich = self.assembly[0].getUraniumMassEnrich() - self.assertAlmostEqual(self.assembly.getMaxUraniumMassEnrich(), baseEnrich) - self.assembly[2].setNumberDensity("U235", 2e-1) - self.assertGreater(self.assembly.getMaxUraniumMassEnrich(), baseEnrich) - def test_getAge(self): res = 5.0 for b in self.assembly: diff --git a/armi/reactor/tests/test_blocks.py b/armi/reactor/tests/test_blocks.py index f21447e06..92dfe3734 100644 --- a/armi/reactor/tests/test_blocks.py +++ b/armi/reactor/tests/test_blocks.py @@ -1052,16 +1052,6 @@ def test_getPu(self): } fuel.setNumberDensities({nuc: v / vFrac for nuc, v in refDict.items()}) - # test number density - cur = self.block.getPuN() - ndens = 0.0 - for nucName in refDict.keys(): - if nucName in ["PU238", "PU239", "PU240", "PU241", "PU242"]: - ndens += self.block.getNumberDensity(nucName) - ref = ndens - places = 6 - self.assertAlmostEqual(cur, ref, places=places) - # test moles cur = self.block.getPuMoles() ndens = 0.0 @@ -1074,16 +1064,7 @@ def test_getPu(self): * self.block.getVolume() * self.block.getSymmetryFactor() ) - places = 6 - self.assertAlmostEqual(cur, ref, places=places) - - # test mass - cur = self.block.getPuMass() - pu = 0.0 - for nucName in refDict.keys(): - if nucName in ["PU238", "PU239", "PU240", "PU241", "PU242"]: - pu += self.block.getMass(nucName) - self.assertAlmostEqual(cur, pu) + self.assertAlmostEqual(cur, ref, places=6) def test_adjustDensity(self): u235Dens = 0.003 @@ -1098,12 +1079,11 @@ def test_adjustDensity(self): cur = self.block.getNumberDensity("U235") ref = densAdj * u235Dens - places = 6 - self.assertAlmostEqual(cur, ref, places=places) + self.assertAlmostEqual(cur, ref, places=9) cur = self.block.getNumberDensity("U238") ref = densAdj * u238Dens - self.assertAlmostEqual(cur, ref, places=places) + self.assertAlmostEqual(cur, ref, places=9) self.assertAlmostEqual(mass2 - mass1, massDiff) @@ -1954,9 +1934,6 @@ def test_symmetryFactor(self): self.assertEqual(v0 / 3.0, self.HexBlock.getVolume()) self.assertAlmostEqual(m0 / 3.0, self.HexBlock.getMass()) - symmetryLine = self.HexBlock.isOnWhichSymmetryLine() - self.assertEqual(grids.BOUNDARY_CENTER, symmetryLine) - def test_retainState(self): """Ensure retainState restores params and spatialGrids.""" self.HexBlock.spatialGrid = grids.HexGrid.fromPitch(1.0) diff --git a/armi/reactor/tests/test_composites.py b/armi/reactor/tests/test_composites.py index 203e71ab5..d783794f6 100644 --- a/armi/reactor/tests/test_composites.py +++ b/armi/reactor/tests/test_composites.py @@ -762,10 +762,6 @@ def test_dimensionReport(self): report = self.obj.setComponentDimensionsReport() self.assertEqual(len(report), len(self.obj)) - def test_printDensities(self): - lines = self.obj.printDensities() - self.assertEqual(len(lines), len(self.obj.getNuclides())) - def test_getAtomicWeight(self): weight = self.obj.getAtomicWeight() self.assertTrue(50 < weight < 100) diff --git a/doc/release/0.3.rst b/doc/release/0.3.rst index c8ccd89ec..bb58d291d 100644 --- a/doc/release/0.3.rst +++ b/doc/release/0.3.rst @@ -19,6 +19,19 @@ API Changes #. Removed unused methods: ``Reactor.getAllNuclidesIn()``, ``plotTriangleFlux()``. (`PR#1656 `_) #. Removed ``armi.utils.dochelpers``; not relevant to nuclear modeling. (`PR#1662 `_) #. Removing old tools created to help people convert to the current database format: ``armi.bookkeeping.db.convertDatabase()`` and ``ConvertDB``. (`PR#1658 `_) +#. Removing extraneous ``ArmiOjbect`` methods. (`PR#1667 `_) + * Moving ``ArmiObject.getBoronMassEnrich()`` to ``Block``. + * Moving ``ArmiObject.getPuMoles()`` to ``Block``. + * Moving ``ArmiObject.getUraniumMassEnrich()`` to ``Block``. + * Removing ``ArmiObject.getMaxUraniumMassEnrich.()``. + * Removing ``ArmiObject.getMaxVolume()`` & ``Block.getMaxVolume()``. + * Removing ``ArmiObject.getPuFrac()``. + * Removing ``ArmiObject.getPuMass()``. + * Removing ``ArmiObject.getPuN()``. + * Removing ``ArmiObject.getZrFrac()``. + * Removing ``ArmiObject.printDensities()``. + * Moving ``Composite.isOnWhichSymmetryLine()`` to ``Assembly``. + * Removing ``Block.isOnWhichSymmetryLine()``. #. TBD Bug Fixes