Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enabling axial expansion with detailed depletion #1954

Merged
merged 34 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
833d08a
added `detailedNDens` component parameter
HunterPSmith Sep 25, 2024
66d4cf8
import isNumpyArray
HunterPSmith Sep 26, 2024
be73ee1
Add powerDecay and pdensDecay parameters to component level
HunterPSmith Oct 15, 2024
29f9dfb
update component detailedNDens in lockstep with `changeNDensByFactor`
HunterPSmith Oct 15, 2024
9a1104a
black
HunterPSmith Oct 15, 2024
d440a12
black and typo fix
HunterPSmith Oct 16, 2024
1a2eb98
Revert last three commits
HunterPSmith Oct 21, 2024
ee30c85
move functionality of updating detailedNDens within changeNDensByFact…
HunterPSmith Oct 21, 2024
16a884f
Revert "move functionality of updating detailedNDens within changeNDe…
HunterPSmith Oct 21, 2024
3bb63bf
move functionality of updating detailedNDens within changeNDensByFact…
HunterPSmith Oct 21, 2024
dba4ae6
black
HunterPSmith Oct 21, 2024
93a4fd2
remove old comment
HunterPSmith Oct 22, 2024
59a0d75
move `powerDecay` and `pdensDecay` component parameters (and block `p…
HunterPSmith Oct 24, 2024
c358aa4
add test for detailedNDensity with detailed axial expansion
HunterPSmith Oct 28, 2024
817bbe0
black
HunterPSmith Oct 28, 2024
2eb8f5b
add test for conservation of components when detailedAxialExpansion: …
HunterPSmith Oct 29, 2024
a93fa9d
Merge branch 'main' of https://github.com/terrapower/armi into CDSD-530
HunterPSmith Oct 30, 2024
3e7df65
Merge branch 'main' of https://github.com/terrapower/armi into CDSD-530
HunterPSmith Oct 31, 2024
bfb8766
Merge branch 'main' of https://github.com/terrapower/armi into CDSD-530
HunterPSmith Nov 1, 2024
1bc99ed
update axial expansion test
HunterPSmith Nov 1, 2024
00bdb8d
black and ruff
HunterPSmith Nov 1, 2024
75c70b6
black
HunterPSmith Nov 1, 2024
ccda7db
Update armi/reactor/converters/tests/test_axialExpansionChanger.py
HunterPSmith Nov 1, 2024
751a0c4
add release note
HunterPSmith Nov 1, 2024
9ef9630
Merge branch 'main' of https://github.com/terrapower/armi into CDSD-530
HunterPSmith Nov 1, 2024
221c5b2
Merge branch 'CDSD-530' of https://github.com/terrapower/armi into CD…
HunterPSmith Nov 1, 2024
b193500
changes from review
albeanth Nov 1, 2024
e285bd3
org imports
albeanth Nov 1, 2024
7ec0c9b
added comments
HunterPSmith Nov 1, 2024
39e47d8
ruff
HunterPSmith Nov 1, 2024
7449e7d
linting
HunterPSmith Nov 3, 2024
4e3d6c5
Alphabetizing imports
john-science Nov 4, 2024
99af47c
Merge branch 'main' of https://github.com/terrapower/armi into CDSD-530
HunterPSmith Nov 5, 2024
5894a15
Merge branch 'CDSD-530' of https://github.com/terrapower/armi into CD…
HunterPSmith Nov 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions armi/physics/neutronics/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,8 +655,6 @@ def _getNeutronicsBlockParams():
categories=[parameters.Category.neutronics],
)

pb.defParam("powerDecay", units=units.WATTS, description="Total decay power")
john-science marked this conversation as resolved.
Show resolved Hide resolved

pb.defParam(
"powerGamma",
units=units.WATTS,
Expand Down
15 changes: 15 additions & 0 deletions armi/reactor/components/componentParameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from armi.reactor import parameters
from armi.reactor.parameters import ParamLocation
from armi.utils import units
from armi.reactor.parameters.parameterDefinitions import isNumpyArray
john-science marked this conversation as resolved.
Show resolved Hide resolved


def getComponentParameterDefinitions():
Expand Down Expand Up @@ -63,6 +64,20 @@ def getComponentParameterDefinitions():
description="Number densities of each nuclide.",
)

pb.defParam(
"detailedNDens",
setter=isNumpyArray("detailedNDens"),
units=f"atoms/(bn*{units.CM})",
description=(
"High-fidelity number density vector with up to thousands of nuclides. "
"Used in high-fi depletion runs where low-fi depletion may also be occurring. "
"This param keeps the hi-fi and low-fi depletion values from interfering. "
"See core.p.detailedNucKeys for keys. "
),
saveToDB=True,
default=None,
)

pb.defParam(
"percentBu",
units=f"{units.PERCENT_FIMA}",
Expand Down
3 changes: 3 additions & 0 deletions armi/reactor/composites.py
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,9 @@ def changeNDensByFactor(self, factor):
nuc: val * factor for nuc, val in self.getNumberDensities().items()
}
self.setNumberDensities(densitiesScaled)
# Update detailedNDens
if self.p.detailedNDens is not None:
self.p.detailedNDens *= factor

def clearNumberDensities(self):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,7 @@ def axiallyExpandAssembly(self):
c.zbottom = self.linked.linkedBlocks[b].lower.p.ztop
c.ztop = c.zbottom + c.height
# update component number densities
newNumberDensities = {
nuc: c.getNumberDensity(nuc) / growFrac
for nuc in c.getNuclides()
}
c.setNumberDensities(newNumberDensities)
c.changeNDensByFactor(1.0 / growFrac)
# redistribute block boundaries if on the target component
if self.expansionData.isTargetComponent(c):
b.p.ztop = c.ztop
Expand Down Expand Up @@ -393,7 +389,7 @@ def manageCoreMesh(self, r):
if not self._detailedAxialExpansion:
# loop through again now that the reference is adjusted and adjust the non-fuel assemblies.
for a in r.core.getAssemblies():
a.setBlockMesh(r.core.refAssem.getAxialMesh())
a.setBlockMesh(r.core.refAssem.getAxialMesh(), conserveMassFlag="auto")

oldMesh = r.core.p.axialMesh
r.core.updateAxialMesh()
Expand Down
83 changes: 78 additions & 5 deletions armi/reactor/converters/tests/test_axialExpansionChanger.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import collections
import os
import unittest
import copy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could alphabetize these imports.

from statistics import mean

from numpy import array, linspace, zeros
Expand Down Expand Up @@ -270,6 +271,7 @@ def test_thermalExpansionContractionConservation_simple(self):
a = buildTestAssemblyWithFakeMaterial(name="HT9")
origMesh = a.getAxialMesh()[:-1]
origMasses, origNDens = self._getComponentMassAndNDens(a)
origDetailedNDens = self._setComponentDetailedNDens(a, origNDens)
axialExpChngr = AxialExpansionChanger(detailedAxialExpansion=True)

tempGrid = linspace(0.0, a.getHeight())
Expand All @@ -284,16 +286,20 @@ def test_thermalExpansionContractionConservation_simple(self):
# Set new isothermal temp and expand
tempField = array([temp] * len(tempGrid))
oldMasses, oldNDens = self._getComponentMassAndNDens(a)
oldDetailedNDens = self._getComponentDetailedNDens(a)
axialExpChngr.performThermalAxialExpansion(a, tempGrid, tempField)
newMasses, newNDens = self._getComponentMassAndNDens(a)
newDetailedNDens = self._getComponentDetailedNDens(a)
self._checkMass(oldMasses, newMasses)
self._checkNDens(oldNDens, newNDens, totGrowthFrac)
self._checkDetailedNDens(oldDetailedNDens, newDetailedNDens, totGrowthFrac)

# make sure that the assembly returned to the original state
for orig, new in zip(origMesh, a.getAxialMesh()):
self.assertAlmostEqual(orig, new, places=12)
self._checkMass(origMasses, newMasses)
self._checkNDens(origNDens, newNDens, 1.0)
self._checkDetailedNDens(origDetailedNDens, newDetailedNDens, 1.0)

def test_thermalExpansionContractionConservation_complex(self):
"""Thermally expand and then contract to ensure original state is recovered.
Expand Down Expand Up @@ -416,6 +422,14 @@ def _checkNDens(self, prevNDen, newNDens, ratio):
if prev:
self.assertAlmostEqual(prev / new, ratio, msg=f"{prev} / {new}")

def _checkDetailedNDens(self, prevDetailedNDen, newDetailedNDens, ratio):
john-science marked this conversation as resolved.
Show resolved Hide resolved
for prevComp, newComp in zip(
prevDetailedNDen.values(), newDetailedNDens.values()
):
for prev, new in zip(prevComp, newComp):
if prev:
self.assertAlmostEqual(prev / new, ratio, msg=f"{prev} / {new}")

@staticmethod
def _getComponentMassAndNDens(a):
masses = {}
Expand All @@ -426,6 +440,23 @@ def _getComponentMassAndNDens(a):
nDens[c] = c.getNumberDensities()
return masses, nDens

@staticmethod
def _setComponentDetailedNDens(a, nDens):
john-science marked this conversation as resolved.
Show resolved Hide resolved
detailedNDens = {}
for b in a:
for c in getSolidComponents(b):
c.p.detailedNDens = copy.deepcopy([val for val in nDens[c].values()])
detailedNDens[c] = c.p.detailedNDens
return detailedNDens

@staticmethod
def _getComponentDetailedNDens(a):
john-science marked this conversation as resolved.
Show resolved Hide resolved
detailedNDens = {}
for b in a:
for c in getSolidComponents(b):
detailedNDens[c] = copy.deepcopy(c.p.detailedNDens)
return detailedNDens

def test_targetComponentMassConservation(self):
"""Tests mass conservation for target components."""
self.expandAssemForMassConservationTest()
Expand Down Expand Up @@ -571,20 +602,62 @@ def setUp(self):
reduceTestReactorRings(self.r, o.cs, 3)

self.oldAxialMesh = self.r.core.p.axialMesh
self.componentLst = []
for b in self.r.core.refAssem:
if b.hasFlags([Flags.FUEL, Flags.PLENUM]):
self.componentLst.extend(getSolidComponents(b))
# expand refAssem by 1.01 L1/L0
componentLst = [c for b in self.r.core.refAssem for c in b]
expansionGrowthFracs = 1.01 + zeros(len(componentLst))
expansionGrowthFracs = 1.01 + zeros(len(self.componentLst))
(
self.origDetailedNDens,
self.origVolumes,
) = self._getComponentDetailedNDensAndVol(self.componentLst)
self.axialExpChngr.performPrescribedAxialExpansion(
self.r.core.refAssem, componentLst, expansionGrowthFracs, setFuel=True
self.r.core.refAssem, self.componentLst, expansionGrowthFracs, setFuel=True
)

def test_manageCoreMesh(self):
self.axialExpChngr.manageCoreMesh(self.r)
newAxialMesh = self.r.core.p.axialMesh
# skip first and last entries as they do not change
for old, new in zip(self.oldAxialMesh[1:-1], newAxialMesh[1:-1]):
# the top and bottom and top of the grid plate block are not expected to change
for old, new in zip(self.oldAxialMesh[2:-1], newAxialMesh[2:-1]):
self.assertLess(old, new)

def test_componentConservation(self):
self.axialExpChngr.manageCoreMesh(self.r)
newDetailedNDens, newVolumes = self._getComponentDetailedNDensAndVol(
self.componentLst
)
for c in newVolumes.keys():
self._checkMass(
self.origDetailedNDens[c],
self.origVolumes[c],
newDetailedNDens[c],
newVolumes[c],
c,
)

def _getComponentDetailedNDensAndVol(self, componentLst):
john-science marked this conversation as resolved.
Show resolved Hide resolved
detailedNDens = {}
volumes = {}
for c in componentLst:
c.p.detailedNDens = [val for val in c.getNumberDensities().values()]
detailedNDens[c] = copy.deepcopy(c.p.detailedNDens)
volumes[c] = c.getVolume()
return (detailedNDens, volumes)

def _checkMass(self, origDetailedNDens, origVolume, newDetailedNDens, newVolume, c):
for prevMass, newMass in zip(
origDetailedNDens * origVolume, newDetailedNDens * newVolume
):
if c.parent.hasFlags(Flags.FUEL):
self.assertAlmostEqual(
prevMass, newMass, delta=1e-12, msg=f"{c}, {c.parent}"
)
else:
# should not conserve mass here as it is structural material above active fuel
self.assertAlmostEqual(newMass / prevMass, 0.99, msg=f"{c}, {c.parent}")


class TestExceptions(AxialExpansionTestBase, unittest.TestCase):
"""Verify exceptions are caught."""
Expand Down
2 changes: 2 additions & 0 deletions armi/reactor/tests/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,9 +697,11 @@ def test_getNumberDensities(self):
def test_changeNumberDensities(self):
"""Test that demonstates that the number densities on a component can be modified."""
self.component.p.numberDensities = {"NA23": 1.0}
self.component.p.detailedNDens = [1.0]
self.assertEqual(self.component.getNumberDensity("NA23"), 1.0)
self.component.changeNDensByFactor(3.0)
self.assertEqual(self.component.getNumberDensity("NA23"), 3.0)
self.assertEqual(self.component.p.detailedNDens[0], 3.0)

def test_fuelMass(self):
nominalMass = self.component.getMass()
Expand Down
1 change: 1 addition & 0 deletions doc/release/0.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ New Features
#. Improve efficiency of reaction rate calculations. (`PR#1887 <https://github.com/terrapower/armi/pull/1887>`_)
#. Adding new options for simplifying 1D cross section modeling. (`PR#1949 <https://github.com/terrapower/armi/pull/1949>`_)
#. Updating ``copyOrWarn`` and ``getFileSHA1Hash`` to support directories. (`PR#1984 <https://github.com/terrapower/armi/pull/1984>`_)
#. Exposing ``detailedNDens`` to components. (`PR#1954 <https://github.com/terrapower/armi/pull/1954>`_)
#. TBD

API Changes
Expand Down
Loading