Skip to content

Commit

Permalink
Merge c2cd59d into 08f8c1d
Browse files Browse the repository at this point in the history
  • Loading branch information
albeanth committed Apr 22, 2024
2 parents 08f8c1d + c2cd59d commit 32d28ec
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 200 deletions.
6 changes: 3 additions & 3 deletions armi/mpiActions.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def _mpiOperationHelper(self, obj, mpiFunction):
self.o = self.r = self.cs = None
try:
return mpiFunction(obj, root=0)
except (cPickle.PicklingError) as error:
except cPickle.PicklingError as error:
runLog.error("Failed to {} {}.".format(mpiFunction.__name__, obj))
runLog.error(error)
raise
Expand Down Expand Up @@ -553,8 +553,8 @@ def invokeHook(self):
self.r.core.regenAssemblyLists()

# check to make sure that everything has been properly reattached
if self.r.core.getFirstBlock().r is not self.r:
raise RuntimeError("Block.r is not self.r. Reattach the blocks!")
if self.r.core.getFirstBlock().core.r is not self.r:
raise RuntimeError("Block.core.r is not self.r. Reattach the blocks!")

beforeCollection = timeit.default_timer()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,8 @@ def test_calcReactionRates(self):
"""
b = test_blocks.loadTestBlock()
test_blocks.applyDummyData(b)
self.assertEqual(b.p.rateAbs, 0.0)
globalFluxInterface.calcReactionRates(b, 1.01, b.r.core.lib)
self.assertAlmostEqual(b.p.rateAbs, 0.0)
globalFluxInterface.calcReactionRates(b, 1.01, b.core.lib)
self.assertGreater(b.p.rateAbs, 0.0)
vfrac = b.getComponentAreaFrac(Flags.FUEL)
self.assertEqual(b.p.fisDens, b.p.rateFis / vfrac)
Expand Down
22 changes: 12 additions & 10 deletions armi/physics/neutronics/tests/test_crossSectionManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
class TestBlockCollection(unittest.TestCase):
def setUp(self):
self.blockList = makeBlocks()
self.bc = BlockCollection(self.blockList[0].r.blueprints.allNuclidesInProblem)
self.bc = BlockCollection(
self.blockList[0].core.r.blueprints.allNuclidesInProblem
)
self.bc.extend(self.blockList)

def test_add(self):
Expand Down Expand Up @@ -88,7 +90,7 @@ def setUp(self):
b.p.percentBu = bi / 4.0 * 100
self.blockList[0], self.blockList[2] = self.blockList[2], self.blockList[0]
self.bc = MedianBlockCollection(
self.blockList[0].r.blueprints.allNuclidesInProblem
self.blockList[0].core.r.blueprints.allNuclidesInProblem
)
self.bc.extend(self.blockList)

Expand Down Expand Up @@ -125,7 +127,7 @@ def setUpClass(cls):

def setUp(self):
self.bc = AverageBlockCollection(
self.blockList[0].r.blueprints.allNuclidesInProblem
self.blockList[0].core.r.blueprints.allNuclidesInProblem
)
self.bc.extend(self.blockList)
self.bc.averageByComponent = True
Expand Down Expand Up @@ -160,7 +162,7 @@ def test_createRepresentativeBlock(self):
# check that a new block collection of the representative block has right temperatures
# this is required for Doppler coefficient calculations
newBc = AverageBlockCollection(
self.blockList[0].r.blueprints.allNuclidesInProblem
self.blockList[0].core.r.blueprints.allNuclidesInProblem
)
newBc.append(avgB)
newBc.calcAvgNuclideTemperatures()
Expand Down Expand Up @@ -199,7 +201,7 @@ def test_createRepresentativeBlockDissimilar(self):

# U35 has different average temperature because blocks have different U235 content
newBc = AverageBlockCollection(
self.blockList[0].r.blueprints.allNuclidesInProblem
self.blockList[0].core.r.blueprints.allNuclidesInProblem
)
newBc.append(avgB)
newBc.calcAvgNuclideTemperatures()
Expand Down Expand Up @@ -251,7 +253,7 @@ def setUpClass(cls):

def setUp(self):
self.bc = AverageBlockCollection(
self.blockList[0].r.blueprints.allNuclidesInProblem
self.blockList[0].core.r.blueprints.allNuclidesInProblem
)
blockCopies = [copy.deepcopy(b) for b in self.blockList]
self.bc.extend(blockCopies)
Expand Down Expand Up @@ -675,7 +677,7 @@ def setUpClass(cls):

def setUp(self):
self.bc = FluxWeightedAverageBlockCollection(
self.blockList[0].r.blueprints.allNuclidesInProblem
self.blockList[0].core.r.blueprints.allNuclidesInProblem
)
self.bc.extend(self.blockList)

Expand All @@ -696,7 +698,7 @@ class TestCrossSectionGroupManager(unittest.TestCase):
def setUp(self):
cs = settings.Settings()
self.blockList = makeBlocks(20)
self.csm = CrossSectionGroupManager(self.blockList[0].r, cs)
self.csm = CrossSectionGroupManager(self.blockList[0].core.r, cs)
for bi, b in enumerate(self.blockList):
b.p.percentBu = bi / 19.0 * 100
self.csm._setBuGroupBounds([3, 10, 30, 100])
Expand Down Expand Up @@ -858,7 +860,7 @@ def test_interactBOL(self):
:tests: R_ARMI_XSGM_FREQ
"""
self.assertFalse(self.csm.representativeBlocks)
self.blockList[0].r.p.timeNode = 0
self.blockList[0].core.r.p.timeNode = 0
self.csm.cs[CONF_LATTICE_PHYSICS_FREQUENCY] = "BOL"
self.csm.interactBOL()
self.assertTrue(self.csm.representativeBlocks)
Expand All @@ -871,7 +873,7 @@ def test_interactBOC(self):
:tests: R_ARMI_XSGM_FREQ
"""
self.assertFalse(self.csm.representativeBlocks)
self.blockList[0].r.p.timeNode = 0
self.blockList[0].core.r.p.timeNode = 0
self.csm.cs[CONF_LATTICE_PHYSICS_FREQUENCY] = "BOC"
self.csm.interactBOL()
self.csm.interactBOC()
Expand Down
159 changes: 120 additions & 39 deletions armi/reactor/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from armi.utils import units
from armi.utils.plotting import plotBlockFlux
from armi.utils.units import TRACE_NUMBER_DENSITY
from armi.nuclearDataIO import xsCollections

PIN_COMPONENTS = [
Flags.CONTROL,
Expand Down Expand Up @@ -176,42 +177,6 @@ def core(self):
c = self.getAncestor(lambda c: isinstance(c, Core))
return c

@property
def r(self):
"""
Look through the ancestors of the Block to find a Reactor, and return it.
Notes
-----
Typical hierarchy: Reactor <- Core <- Assembly <- Block
A block should only have a reactor through a parent assembly.
It may make sense to try to factor out usage of ``b.r``.
Returns
-------
core.parent : armi.reactor.reactors.Reactor
ARMI reactor object that is an ancestor of the block.
Raises
------
ValueError
If the parent of the block's ``core`` is not an ``armi.reactor.reactors.Reactor``.
"""
from armi.reactor.reactors import Reactor

core = self.core
if core is None:
return self.getAncestor(lambda o: isinstance(o, Reactor))

if not isinstance(core.parent, Reactor):
raise TypeError(
"Parent of Block ({}) core is not a Reactor. Got {} instead".format(
core.parent, type(core.parent)
)
)

return core.parent

def makeName(self, assemNum, axialIndex):
"""
Generate a standard block from assembly number.
Expand Down Expand Up @@ -748,7 +713,6 @@ def adjustDensity(self, frac, adjustList, returnMass=False):
numDensities = self.getNuclideNumberDensities(adjustList)

for nuclideName, dens in zip(adjustList, numDensities):

if not dens:
# don't modify zeros.
continue
Expand All @@ -773,7 +737,7 @@ def _updateDetailedNdens(self, frac, adjustList):
# BOL assems get expanded to a reference so the first check is needed so it
# won't call .blueprints on None since BOL assems don't have a core/r
return
if any(nuc in self.r.blueprints.activeNuclides for nuc in adjustList):
if any(nuc in self.core.r.blueprints.activeNuclides for nuc in adjustList):
self.p.detailedNDens *= frac
# Other power densities do not need to be updated as they are calculated in
# the global flux interface, which occurs after axial expansion from crucible
Expand Down Expand Up @@ -1633,6 +1597,124 @@ def getPinCoordinates(self):
coords.append(clad.spatialLocator.getLocalCoordinates())
return coords

def getTotalEnergyGenerationConstants(self):
"""
Get the total energy generation group constants for a block.
Gives the total energy generation rates when multiplied by the multigroup flux.
Returns
-------
totalEnergyGenConstant: numpy.array
Total (fission + capture) energy generation group constants (Joules/cm)
"""
return (
self.getFissionEnergyGenerationConstants()
+ self.getCaptureEnergyGenerationConstants()
)

def getFissionEnergyGenerationConstants(self):
"""
Get the fission energy generation group constants for a block.
Gives the fission energy generation rates when multiplied by the multigroup
flux.
Returns
-------
fissionEnergyGenConstant: numpy.array
Energy generation group constants (Joules/cm)
Raises
------
RuntimeError:
Reports if a cross section library is not assigned to a reactor.
"""
if not self.core.lib:
raise RuntimeError(
"Cannot compute energy generation group constants without a library"
". Please ensure a library exists."
)

return xsCollections.computeFissionEnergyGenerationConstants(
self.getNumberDensities(), self.core.lib, self.getMicroSuffix()
)

def getCaptureEnergyGenerationConstants(self):
"""
Get the capture energy generation group constants for a block.
Gives the capture energy generation rates when multiplied by the multigroup
flux.
Returns
-------
fissionEnergyGenConstant: numpy.array
Energy generation group constants (Joules/cm)
Raises
------
RuntimeError:
Reports if a cross section library is not assigned to a reactor.
"""
if not self.core.lib:
raise RuntimeError(
"Cannot compute energy generation group constants without a library"
". Please ensure a library exists."
)

return xsCollections.computeCaptureEnergyGenerationConstants(
self.getNumberDensities(), self.core.lib, self.getMicroSuffix()
)

def getNeutronEnergyDepositionConstants(self):
"""
Get the neutron energy deposition group constants for a block.
Returns
-------
energyDepConstants: numpy.array
Neutron energy generation group constants (in Joules/cm)
Raises
------
RuntimeError:
Reports if a cross section library is not assigned to a reactor.
"""
if not self.core.lib:
raise RuntimeError(
"Cannot get neutron energy deposition group constants without "
"a library. Please ensure a library exists."
)

return xsCollections.computeNeutronEnergyDepositionConstants(
self.getNumberDensities(), self.core.lib, self.getMicroSuffix()
)

def getGammaEnergyDepositionConstants(self):
"""
Get the gamma energy deposition group constants for a block.
Returns
-------
energyDepConstants: numpy.array
Energy generation group constants (in Joules/cm)
Raises
------
RuntimeError:
Reports if a cross section library is not assigned to a reactor.
"""
if not self.core.lib:
raise RuntimeError(
"Cannot get gamma energy deposition group constants without "
"a library. Please ensure a library exists."
)

return xsCollections.computeGammaEnergyDepositionConstants(
self.getNumberDensities(), self.core.lib, self.getMicroSuffix()
)

def getBoronMassEnrich(self):
"""Return B-10 mass fraction."""
b10 = self.getMass("B10")
Expand Down Expand Up @@ -2527,7 +2609,6 @@ def getHydraulicDiameter(self):


class CartesianBlock(Block):

PITCH_DIMENSION = "widthOuter"
PITCH_COMPONENT_TYPE = components.Rectangle

Expand Down

0 comments on commit 32d28ec

Please sign in to comment.