Skip to content

Commit

Permalink
Merge fe0546a into 6b94942
Browse files Browse the repository at this point in the history
  • Loading branch information
jakehader committed Jul 19, 2022
2 parents 6b94942 + fe0546a commit 3bd6131
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 12 deletions.
25 changes: 18 additions & 7 deletions armi/reactor/converters/geometryConverters.py
Expand Up @@ -326,6 +326,9 @@ class HexToRZThetaConverter(GeometryConverter):
* ``Axial Coordinates`` -- use :py:class:`armi.reactor.converters.meshConverters._RZThetaReactorMeshConverterByAxialCoordinates`
* ``Axial Bins`` -- use :py:class:`armi.reactor.converters.meshConverters._RZThetaReactorMeshConverterByAxialBins`
homogenizeAxiallyByFlags
Boolean that if set to True will ignore the `axialConversionType` input and determine a mesh based on the
material boundaries for each RZ region axially.
expandReactor : bool
If True, the HEX-Z reactor will be expanded to full core geometry prior to converting to the RZT reactor.
Expand Down Expand Up @@ -385,16 +388,24 @@ def _generateConvertedReactorMesh(self):
runLog.info("Generating mesh coordinates for the reactor conversion")
self._radialMeshConversionType = self.converterSettings["radialConversionType"]
self._axialMeshConversionType = self.converterSettings["axialConversionType"]
self._homogenizeAxiallyByFlags = self.converterSettings[
"homogenizeAxiallyByFlags"
]
converter = None
if self._radialMeshConversionType == self._MESH_BY_RING_COMP:
if self._axialMeshConversionType == self._MESH_BY_AXIAL_COORDS:
converter = meshConverters.RZThetaReactorMeshConverterByRingCompositionAxialCoordinates(
self.converterSettings
)
elif self._axialMeshConversionType == self._MESH_BY_AXIAL_BINS:
converter = meshConverters.RZThetaReactorMeshConverterByRingCompositionAxialBins(
if self._homogenizeAxiallyByFlags:
converter = meshConverters.RZThetaReactorMeshConverterByRingCompositionAxialFlags(
self.converterSettings
)
else:
if self._axialMeshConversionType == self._MESH_BY_AXIAL_COORDS:
converter = meshConverters.RZThetaReactorMeshConverterByRingCompositionAxialCoordinates(
self.converterSettings
)
elif self._axialMeshConversionType == self._MESH_BY_AXIAL_BINS:
converter = meshConverters.RZThetaReactorMeshConverterByRingCompositionAxialBins(
self.converterSettings
)
if converter is None:
raise ValueError(
"No mesh converter exists for `radialConversionType` and `axialConversionType` settings "
Expand Down Expand Up @@ -860,7 +871,7 @@ def createHomogenizedRZTBlock(
msg + "Modify mesh converter settings before proceeding."
)
else:
runLog.important(msg)
runLog.extra(msg)

homBlockType = self._getHomogenizedBlockType(numHexBlockByType)
homBlockTemperature = homBlockTemperature / homBlockVolume
Expand Down
66 changes: 61 additions & 5 deletions armi/reactor/converters/meshConverters.py
Expand Up @@ -17,6 +17,9 @@
"""

import math
import collections
import itertools

import numpy

from armi import runLog
Expand Down Expand Up @@ -85,7 +88,7 @@ def generateMesh(self, r=None):
self._numRingsInCore = core.getNumHexRings()
self._assemsInCore = core.getAssemblies()
self._coreAxialMeshCoords = core.findAllAxialMeshPoints(applySubMesh=False)
self.setAxialMesh()
self.setAxialMesh(core)
self._checkAxialMeshList()
self.setThetaMesh()
self._checkThetaMeshList()
Expand Down Expand Up @@ -139,7 +142,7 @@ def _logMeshData(self, listType, listName, listDataType):
def setRingsToConvert(self, core):
raise NotImplementedError

def setAxialMesh(self):
def setAxialMesh(self, core):
raise NotImplementedError

def setThetaMesh(self):
Expand Down Expand Up @@ -213,7 +216,7 @@ def _checkThetaMeshList(self):
class _RZThetaReactorMeshConverterByAxialCoordinates(RZThetaReactorMeshConverter):
"""Generate an axial mesh based on user provided axial mesh coordinates."""

def setAxialMesh(self):
def setAxialMesh(self, core):
"""Set up the reactor's new radial rings based on a user-specified axial coordinate list (axial mesh)."""
self.axialMesh = self._converterSettings["axialMesh"]

Expand All @@ -229,7 +232,7 @@ class _RZThetaReactorMeshConverterByAxialBins(RZThetaReactorMeshConverter):
be [2, 4, 6, 8]).
"""

def setAxialMesh(self):
def setAxialMesh(self, core):
"""
Set up axial mesh coordinates using user-specified number of axial segments per bins.
Expand All @@ -252,7 +255,43 @@ def _mergeAxialMeshByAxialSegsPerBin(self):
self.axialMesh = [0] * len(axialMeshIndices)
for axialMeshIndex, locIndex in enumerate(axialMeshIndices):
self.axialMesh[axialMeshIndex] = self._coreAxialMeshCoords[locIndex]
return self.axialMesh


class _RZThetaReactorMeshConverterByAxialFlags(RZThetaReactorMeshConverter):
"""
Generate an axial mesh based on examining the block flags axially across the core.
"""

def setAxialMesh(self, core):
"""
Generate an axial mesh based on examining the block flags axially across the core.
Notes
-----
This approach is useful as it will create the largest material regions possible
to minimize number of axially regions within the converted reactor core. This
class not only looks at the block flags axially, but will add new mesh points for
regions where the blocks of the same flag differ by XSID.
"""
axialMeshCoordinates = collections.defaultdict(set)
for a in core.getAssemblies():
blockFlags = set([(b.p.flags, b.getMicroSuffix()) for b in a])
for flags, xsID in blockFlags:
meshes = []
for b in a.getBlocks(flags):
# Skip this block if it has a different XS ID than the
# current target.
if b.getMicroSuffix() != xsID:
continue

# Neglect any zero mesh points as zero points are implicit
if b.p.zbottom != 0.0:
meshes.append(round(b.p.zbottom, 8))
if b.p.ztop != 0.0:
meshes.append(round(b.p.ztop, 8))
axialMeshCoordinates[a].add(min(meshes))
axialMeshCoordinates[a].add(max(meshes))
self.axialMesh = sorted(set(itertools.chain(*axialMeshCoordinates.values())))


class _RZThetaReactorMeshConverterByRingComposition(RZThetaReactorMeshConverter):
Expand Down Expand Up @@ -334,6 +373,23 @@ class RZThetaReactorMeshConverterByRingCompositionAxialCoordinates(
pass


class RZThetaReactorMeshConverterByRingCompositionAxialFlags(
_RZThetaReactorMeshConverterByRingComposition,
_RZThetaReactorMeshConverterByAxialFlags,
):
"""
Generate a new mesh based on the radial compositions and axial material
(based on block flags) regions in the core.
See Also
--------
_RZThetaReactorMeshConverterByRingComposition
_RZThetaReactorMeshConverterByAxialFlags
"""

pass


def checkLastValueInList(
inputList, listName, expectedValue, eps=0.001, adjustLastValue=False
):
Expand Down
33 changes: 33 additions & 0 deletions armi/reactor/converters/tests/test_meshConverters.py
Expand Up @@ -67,6 +67,22 @@ def test_meshByRingCompositionAxialCoordinatesSmallCore(self):
self.assertListEqual(meshConvert.axialMesh, expectedAxialMesh)
self.assertListEqual(meshConvert.thetaMesh, expectedThetaMesh)

def test_meshByRingCompositionAxialFlagsSmallCore(self):
expectedRadialMesh = [2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 8, 9, 10]
expectedAxialMesh = [25.0, 50.0, 75.0, 100.0, 175.0]
expectedThetaMesh = [2 * math.pi]

meshConvert = (
meshConverters.RZThetaReactorMeshConverterByRingCompositionAxialFlags(
self._converterSettings
)
)
meshConvert.generateMesh(self.r)

self.assertListEqual(meshConvert.radialMesh, expectedRadialMesh)
self.assertListEqual(meshConvert.axialMesh, expectedAxialMesh)
self.assertListEqual(meshConvert.thetaMesh, expectedThetaMesh)

def _growReactor(self):
modifier = geometryConverters.FuelAssemNumModifier(self.o.cs)
modifier.numFuelAssems = 1
Expand Down Expand Up @@ -114,6 +130,23 @@ def test_meshByRingCompositionAxialCoordinatesLargeCore(self):
self.assertListEqual(meshConvert.axialMesh, expectedAxialMesh)
self.assertListEqual(meshConvert.thetaMesh, expectedThetaMesh)

def test_meshByRingCompositionAxialFlagsLargeCore(self):
self._growReactor()
expectedRadialMesh = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13]
expectedAxialMesh = [25.0, 100.0, 175.0]
expectedThetaMesh = [2 * math.pi]

meshConvert = (
meshConverters.RZThetaReactorMeshConverterByRingCompositionAxialFlags(
self._converterSettingsLargerCore
)
)
meshConvert.generateMesh(self.r)

self.assertListEqual(meshConvert.radialMesh, expectedRadialMesh)
self.assertListEqual(meshConvert.axialMesh, expectedAxialMesh)
self.assertListEqual(meshConvert.thetaMesh, expectedThetaMesh)


if __name__ == "__main__":
# import sys;sys.argv = ['', 'TestRZReactorMeshConverter.test_meshByRingCompositionAxialBinsSmallCore']
Expand Down

0 comments on commit 3bd6131

Please sign in to comment.