Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into drewj/improve-assem-a…
Browse files Browse the repository at this point in the history
…xial-linkage

* origin/main:
  Adding some missing nuclides to nuclides.dat (#1903)
  Improving efficiency of reaction rate calcs (#1887)
  Adding description of EOL time node in DB (#1967)
  • Loading branch information
drewj-tp committed Oct 24, 2024
2 parents ab9b61b + 3d6b1fe commit e2dc917
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 12 deletions.
4 changes: 2 additions & 2 deletions armi/nuclearDataIO/xsCollections.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
# they have some origin in the ISOTXS file format card 04 definition
# fmt: off
NGAMMA = "nGamma" # radiative capture
NAPLHA = "nalph" # (n, alpha)
NALPHA = "nalph" # (n, alpha)
NP = "np" # (n, proton)
ND = "nd" # (n, deuteron)
NT = "nt" # (n, triton)
Expand All @@ -59,7 +59,7 @@
NUSIGF = "nuSigF"
NU = "neutronsPerFission"
# fmt: on
CAPTURE_XS = [NGAMMA, NAPLHA, NP, ND, NT]
CAPTURE_XS = [NGAMMA, NALPHA, NP, ND, NT]

# Cross section types that are represented by 2-D matrices in the multigroup approximation
BASIC_SCAT_MATRIX = ["elasticScatter", "inelasticScatter", "n2nScatter"]
Expand Down
3 changes: 3 additions & 0 deletions armi/physics/neutronics/globalFlux/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
# limitations under the License.

"""Global flux solvers."""

RX_ABS_MICRO_LABELS = ["nGamma", "fission", "nalph", "np", "nd", "nt"]
RX_PARAM_NAMES = ["rateCap", "rateFis", "rateProdN2n", "rateProdFis", "rateAbs"]
4 changes: 1 addition & 3 deletions armi/physics/neutronics/globalFlux/globalFluxInterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from armi.physics import neutronics
from armi.reactor import geometry
from armi.reactor import reactors
from armi.physics.neutronics.globalFlux import RX_PARAM_NAMES, RX_ABS_MICRO_LABELS
from armi.reactor.blocks import Block
from armi.reactor.converters import geometryConverters
from armi.reactor.converters import uniformMesh
Expand All @@ -36,9 +37,6 @@

ORDER = interfaces.STACK_ORDER.FLUX

RX_ABS_MICRO_LABELS = ["nGamma", "fission", "nalph", "np", "nd", "nt"]
RX_PARAM_NAMES = ["rateCap", "rateFis", "rateProdN2n", "rateProdFis", "rateAbs"]


class GlobalFluxInterface(interfaces.Interface):
"""
Expand Down
27 changes: 27 additions & 0 deletions armi/reactor/converters/tests/test_uniformMesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
import os
import random
import unittest
import copy

from armi.nuclearDataIO.cccc import isotxs
from armi.physics.neutronics.settings import CONF_XS_KERNEL
from armi.settings.fwSettings.globalSettings import CONF_UNIFORM_MESH_MINIMUM_SIZE
from armi.reactor.converters import uniformMesh
from armi.reactor.flags import Flags
from armi.reactor.tests import test_assemblies
from armi.reactor.tests import test_blocks
from armi.reactor.tests.test_reactors import loadTestReactor, reduceTestReactorRings
from armi.tests import TEST_ROOT, ISOAA_PATH

Expand Down Expand Up @@ -498,6 +500,31 @@ def test_applyStateToOriginal(self):
self.assertTrue(b.p.rateCap)


class TestCalcReationRates(unittest.TestCase):
def test_calcReactionRatesBlockList(self):
"""
Test that the efficient reaction rate code executes and sets a param > 0.0.
.. test:: Return the reaction rates for a given list of ArmiObjects.
:id: T_ARMI_FLUX_RX_RATES_BY_XS_ID
:tests: R_ARMI_FLUX_RX_RATES
"""
b = test_blocks.loadTestBlock()
test_blocks.applyDummyData(b)
self.assertAlmostEqual(b.p.rateAbs, 0.0)
blockList = [copy.deepcopy(b) for _i in range(3)]
xsID = b.getMicroSuffix()
xsNucDict = {nuc: b.core.lib.getNuclide(nuc, xsID) for nuc in b.getNuclides()}
uniformMesh.UniformMeshGeometryConverter._calcReactionRatesBlockList(
blockList, 1.01, xsNucDict
)
for b in blockList:
self.assertGreater(b.p.rateAbs, 0.0)
vfrac = b.getComponentAreaFrac(Flags.FUEL)
self.assertEqual(b.p.fisDens, b.p.rateFis / vfrac)
self.assertEqual(b.p.fisDensHom, b.p.rateFis)


class TestGammaUniformMesh(unittest.TestCase):
"""
Tests gamma uniform mesh converter.
Expand Down
121 changes: 116 additions & 5 deletions armi/reactor/converters/uniformMesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@
from armi.reactor import parameters
from armi.reactor.reactors import Reactor
from armi.settings.fwSettings.globalSettings import CONF_UNIFORM_MESH_MINIMUM_SIZE
from armi.physics.neutronics.globalFlux import RX_PARAM_NAMES, RX_ABS_MICRO_LABELS


HEAVY_METAL_PARAMS = ["molesHmBOL", "massHmBOL"]

Expand Down Expand Up @@ -1100,13 +1102,42 @@ def _mapStateFromReactorToOther(
aDest,
self.paramMapper,
mapNumberDensities,
calcReactionRates=self.calcReactionRates,
calcReactionRates=False,
)

# If requested, the reaction rates will be calculated based on the
# mapped neutron flux and the XS library.
if self.calcReactionRates:
self._calculateReactionRatesEfficient(
destReactor.core, sourceReactor.core.p.keff
)

# Clear the cached data after it has been mapped to prevent issues with
# holding on to block data long-term.
self._cachedReactorCoreParamData = {}

@staticmethod
def _calculateReactionRatesEfficient(core, keff):
"""
First, sort blocks into groups by XS type. Then, we just need to grab micros for each XS type once.
Iterate over list of blocks with the given XS type; calculate reaction rates for these blocks
"""
xsTypeGroups = collections.defaultdict(list)
for b in core.getBlocks():
xsTypeGroups[b.getMicroSuffix()].append(b)

for xsID, blockList in xsTypeGroups.items():
nucSet = set()
for b in blockList:
nucSet.update(
nuc for nuc, ndens in b.getNumberDensities().items() if ndens > 0.0
)
xsNucDict = {nuc: core.lib.getNuclide(nuc, xsID) for nuc in nucSet}
UniformMeshGeometryConverter._calcReactionRatesBlockList(
blockList, keff, xsNucDict
)

@staticmethod
def _calculateReactionRates(lib, keff, assem):
"""
Expand All @@ -1130,6 +1161,87 @@ def _calculateReactionRates(lib, keff, assem):
continue
globalFluxInterface.calcReactionRates(b, keff, lib)

@staticmethod
def _calcReactionRatesBlockList(objList, keff, xsNucDict):
r"""
Compute 1-group reaction rates for the objects in objList (usually a block).
:meta public:
.. impl:: Return the reaction rates for a given ArmiObject
:id: I_ARMI_FLUX_RX_RATES_BY_XS_ID
:implements: R_ARMI_FLUX_RX_RATES
This is an alternative implementation of :need:`I_ARMI_FLUX_RX_RATES` that
is more efficient when computing reaction rates for a large set of blocks
that share a common set of microscopic cross sections.
For more detail on the reation rate calculations, see :need:`I_ARMI_FLUX_RX_RATES`.
Parameters
----------
objList : List[Block]
The list of objects to compute reaction rates on. Notionally this could be upgraded to be
any kind of ArmiObject but with params defined as they are it currently is only
implemented for a block.
keff : float
The keff of the core. This is required to get the neutron production rate correct
via the neutron balance statement (since nuSigF has a 1/keff term).
xsNucDict: Dict[str, XSNuclide]
Microscopic cross sections to use in computing the reaction rates. Keys are
nuclide names (e.g., "U235") and values are the associated XSNuclide objects
from the cross section library, which contain the microscopic cross section
data for a given nuclide in the current cross section group.
"""
for obj in objList:
rate = collections.defaultdict(float)

numberDensities = obj.getNumberDensities()
try:
mgFlux = np.array(obj.getMgFlux())
except TypeError:
continue

for nucName, numberDensity in numberDensities.items():
if numberDensity == 0.0:
continue
nucRate = collections.defaultdict(float)

micros = xsNucDict[nucName].micros

# absorption is fission + capture (no n2n here)
for name in RX_ABS_MICRO_LABELS:
volumetricRR = numberDensity * mgFlux.dot(micros[name])
nucRate["rateAbs"] += volumetricRR
if name != "fission":
nucRate["rateCap"] += volumetricRR
else:
nucRate["rateFis"] += volumetricRR
# scale nu by keff.
nusigmaF = micros["fission"] * micros.neutronsPerFission
nucRate["rateProdFis"] += (
numberDensity * mgFlux.dot(nusigmaF) / keff
)

nucRate["rateProdN2n"] += 2.0 * numberDensity * mgFlux.dot(micros.n2n)

for rx in RX_PARAM_NAMES:
if nucRate[rx]:
rate[rx] += nucRate[rx]

for paramName, val in rate.items():
obj.p[paramName] = val # put in #/cm^3/s

if rate["rateFis"] > 0.0:
fuelVolFrac = obj.getComponentAreaFrac(Flags.FUEL)
obj.p.fisDens = rate["rateFis"] / fuelVolFrac
obj.p.fisDensHom = rate["rateFis"]
else:
obj.p.fisDens = 0.0
obj.p.fisDensHom = 0.0

def updateReactionRates(self):
"""
Update reaction rates on converted assemblies.
Expand All @@ -1147,10 +1259,9 @@ def updateReactionRates(self):
self.convReactor.core.lib, self.convReactor.core.p.keff, assem
)
else:
for assem in self.convReactor.core.getAssemblies():
self._calculateReactionRates(
self.convReactor.core.lib, self.convReactor.core.p.keff, assem
)
self._calculateReactionRatesEfficient(
self.convReactor.core, self.convReactor.core.p.keff
)


class NeutronicsUniformMeshConverter(UniformMeshGeometryConverter):
Expand Down
12 changes: 11 additions & 1 deletion armi/resources/nuclides.dat
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ---------------------------------------------------------------------
# NUCLIDE DATA
# ---------------------------------------------------------------------
# This file contains a set of 4614 nuclides and their associated metadata
# This file contains a set of 4624 nuclides and their associated metadata
# of atomic number (Z), number of neutrons (N), mass number (A), stability
# state number (S), Mass (amu), natural abundance (fractional), half-life (sec),
# and the spontaneous fission neutron yield (nu-bar).
Expand Down Expand Up @@ -2911,6 +2911,7 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
70 115 185 0 YB 1.84967901031e+02 0.00000000000e+00 1.60000000000e-07 0.000000
70 116 186 0 YB 1.85960897004e+02 0.00000000000e+00 1.11110000000e+01 0.000000
70 117 187 0 YB 1.86964769503e+02 0.00000000000e+00 1.11110000000e+01 0.000000
70 118 188 0 YB 1.87966850000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
71 79 150 0 LU 1.49973227957e+02 0.00000000000e+00 4.50000000000e-02 0.000000
71 79 150 1 LU 1.49973251575e+02 0.00000000000e+00 3.90000000000e-05 0.000000
71 80 151 0 LU 1.50967576821e+02 0.00000000000e+00 8.06000000000e-02 0.000000
Expand Down Expand Up @@ -2979,6 +2980,7 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
71 117 188 0 LU 1.87973172133e+02 0.00000000000e+00 inf 0.000000
71 118 189 0 LU 1.88970840395e+02 0.00000000000e+00 1.11110000000e+01 0.000000
71 119 190 0 LU 1.89969390037e+02 0.00000000000e+00 1.11110000000e+01 0.000000
71 120 191 0 LU 1.90971560000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
72 81 153 0 HF 1.52970690099e+02 0.00000000000e+00 inf 0.000000
72 82 154 0 HF 1.53964859681e+02 0.00000000000e+00 2.00000000000e+00 0.000000
72 83 155 0 HF 1.54963389999e+02 0.00000000000e+00 8.43000000000e-01 0.000000
Expand Down Expand Up @@ -3087,6 +3089,7 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
73 119 192 0 TA 1.91975147454e+02 0.00000000000e+00 2.20000000000e+00 0.000000
73 120 193 0 TA 1.92977401897e+02 0.00000000000e+00 inf 0.000000
73 121 194 0 TA 1.93981277391e+02 0.00000000000e+00 inf 0.000000
73 122 195 0 TA 1.94972540000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
74 83 157 0 W 1.56978357351e+02 0.00000000000e+00 2.75000000000e-01 0.000000
74 84 158 0 W 1.57974562372e+02 0.00000000000e+00 1.25000000000e-03 0.000000
74 84 158 1 W 1.57976589224e+02 0.00000000000e+00 1.43000000000e-04 0.000000
Expand Down Expand Up @@ -4246,6 +4249,7 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
95 156 251 0 AM 2.51082286436e+02 0.00000000000e+00 1.11110000000e+01 0.000000
95 157 252 0 AM 2.52084870103e+02 0.00000000000e+00 inf 0.000000
95 158 253 0 AM 2.53086880851e+02 0.00000000000e+00 1.11110000000e+01 0.000000
96 134 230 0 CM 2.30046089000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
96 135 231 0 CM 2.31050381425e+02 0.00000000000e+00 1.11110000000e+01 0.000000
96 136 232 0 CM 2.32049576267e+02 0.00000000000e+00 1.11110000000e+01 0.000000
96 137 233 0 CM 2.33050771121e+02 0.00000000000e+00 2.30000000000e+01 0.000000
Expand All @@ -4272,6 +4276,8 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
96 157 253 0 CM 2.53086880851e+02 0.00000000000e+00 1.11110000000e+01 0.000000
96 158 254 0 CM 2.54090599607e+02 0.00000000000e+00 1.11110000000e+01 0.000000
96 159 255 0 CM 2.55091048349e+02 0.00000000000e+00 1.11110000000e+01 0.000000
97 134 231 0 BK 2.31045560000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
97 135 232 0 BK 2.32049817000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
97 136 233 0 BK 2.33056210769e+02 0.00000000000e+00 2.10000000000e+01 0.000000
97 137 234 0 BK 2.34056940779e+02 0.00000000000e+00 1.40000000000e+02 0.000000
97 138 235 0 BK 2.35056580068e+02 0.00000000000e+00 1.11110000000e+01 0.000000
Expand Down Expand Up @@ -4377,6 +4383,7 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
100 161 261 0 FM 2.61092087368e+02 0.00000000000e+00 1.11110000000e+01 0.000000
100 162 262 0 FM 2.62095806125e+02 0.00000000000e+00 1.11110000000e+01 0.000000
100 163 263 0 FM 2.63096254866e+02 0.00000000000e+00 1.11110000000e+01 0.000000
101 142 243 0 MD 2.43070833000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
101 143 244 0 MD 2.44080977432e+02 0.00000000000e+00 3.80000000000e-01 0.000000
101 144 245 0 MD 2.45080829283e+02 0.00000000000e+00 9.00000000000e-04 0.000000
101 145 246 0 MD 2.46081885650e+02 0.00000000000e+00 9.00000000000e-01 0.000000
Expand Down Expand Up @@ -4429,6 +4436,7 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
102 163 265 0 NO 2.65094690616e+02 0.00000000000e+00 1.11110000000e+01 0.000000
102 164 266 0 NO 2.66098409372e+02 0.00000000000e+00 1.11110000000e+01 0.000000
102 165 267 0 NO 2.67098858114e+02 0.00000000000e+00 1.11110000000e+01 0.000000
103 145 248 0 LR 2.48074127000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
103 146 249 0 LR 2.49083411070e+02 0.00000000000e+00 1.11110000000e+01 0.000000
103 147 250 0 LR 2.50084316068e+02 0.00000000000e+00 1.11110000000e+01 0.000000
103 148 251 0 LR 2.51094360232e+02 0.00000000000e+00 1.11110000000e+01 0.000000
Expand Down Expand Up @@ -4477,6 +4485,8 @@ Z N A S El Mass, amu Abundance, frac. Half-life (sec) Spontaneous F
104 165 269 0 RF 2.69097293874e+02 0.00000000000e+00 1.11110000000e+01 0.000000
104 166 270 0 RF 2.70101012631e+02 0.00000000000e+00 1.11110000000e+01 0.000000
104 167 271 0 RF 2.71101461372e+02 0.00000000000e+00 1.11110000000e+01 0.000000
105 147 252 0 DB 2.52076730000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
105 148 253 0 DB 2.53086014000e+02 0.00000000000e+00 1.11110000000e+01 0.000000
105 149 254 0 DB 2.54086919316e+02 0.00000000000e+00 1.11110000000e+01 0.000000
105 150 255 0 DB 2.55107398426e+02 0.00000000000e+00 1.60000000000e+00 0.000000
105 151 256 0 DB 2.56108127362e+02 0.00000000000e+00 1.60000000000e+00 0.000000
Expand Down
2 changes: 1 addition & 1 deletion doc/release/0.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ New Features
#. Provide ``Parameter.hasCategory`` for quickly checking if a parameter is defined with a given category. (`PR#1899 <https://github.com/terrapower/armi/pull/1899>`_)
#. Provide ``ParameterCollection.where`` for efficient iteration over parameters who's definition matches a given condition. (`PR#1899 <https://github.com/terrapower/armi/pull/1899>`_)
#. Flags can now be defined with letters and numbers. (`PR#1966 <https://github.com/terrapower/armi/pull/1966>`_)
#. Plugins can provide the ``getAxialExpansionChanger`` hook to customize axial expansion. (`PR#1870 <https://github.com/terrapower/armi/pull/1870`_)
#. Plugins can provide the ``getAxialExpansionChanger`` hook to customize axial expansion. (`PR#1870 <https://github.com/terrapower/armi/pull/1870>`_)
#. New plugin hook ``beforeReactorConstruction`` added to enable plugins to process case settings before reactor init. (`PR#1945 <https://github.com/terrapower/armi/pull/1945>`_)
#. Provide ``Block.getInputHeight`` for determining the height of a block from blueprints. (`PR#1927 <https://github.com/terrapower/armi/pull/1927`_)
#. Improve performance by changing the lattice physics interface so that cross sections are not updated on ``everyNode`` calls during coupled calculations (`PR#1963 <https://github.com/terrapower/armi/pull/1963>`_)
#. Improve efficiency of reaction rate calculations. (`PR#1887 <https://github.com/terrapower/armi/pull/1887>`_)
#. TBD

API Changes
Expand Down
5 changes: 5 additions & 0 deletions doc/user/outputs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,11 @@ documentation of the database modules.

Also, it is important to note that all components are flattened and then grouped
by type.
* - ``/c{CC}n{NN}EOL/``
- H5Group
- A special time node, like the one above, where {CC} is the last cycle and {NN} is the last
node. If this exists, it is meant to represent the EOL, which is perhaps a few days after the
end of the last cycle, where fuel is decaying non-operationally.
* - ``/c{CC}n{NN}/layout/``
- H5Group
- A group that contains a description of the ARMI model within this timenode
Expand Down

0 comments on commit e2dc917

Please sign in to comment.