Source code for armi.utils.tests.test_densityTools
# Copyright 2019 TerraPower, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test densityTools."""
import unittest
from armi.materials.material import Material
from armi.materials.uraniumOxide import UO2
from armi.nucDirectory import elements, nuclideBases
from armi.utils import densityTools
[docs]class UraniumOxide(Material):
"""A test material that needs to be stored in a different namespace.
This is a duplicate (by name only) of :py:class:`armi.materials.uraniumOxide.UraniumOxide`
and is used for testing in :py:meth:`armi.materials.tests.test_materials.MaterialFindingTests.test_namespacing`
"""
[docs]class TestDensityTools(unittest.TestCase):
[docs] def test_expandElementalMassFracsToNuclides(self):
"""
Expand mass fraction to nuclides.
.. test:: Expand mass fractions to nuclides.
:id: T_ARMI_UTIL_EXP_MASS_FRACS
:tests: R_ARMI_UTIL_EXP_MASS_FRACS
"""
element = elements.bySymbol["N"]
mass = {"N": 1.0}
densityTools.expandElementalMassFracsToNuclides(mass, [(element, None)])
self.assertNotIn("N", mass)
self.assertIn("N15", mass)
self.assertIn("N14", mass)
self.assertAlmostEqual(sum(mass.values()), 1.0)
self.assertNotIn("N13", mass) # nothing unnatural.
[docs] def test_expandElementalZeroMassFrac(self):
"""As above, but try with a zero mass frac elemental."""
elementals = [(elements.bySymbol["N"], None), (elements.bySymbol["O"], None)]
mass = {"N": 0.0, "O": 1.0}
densityTools.expandElementalMassFracsToNuclides(mass, elementals)
self.assertNotIn("N", mass)
self.assertNotIn("O", mass)
# Current expectation is for elements with zero mass fraction get expanded and
# isotopes with zero mass remain in the dictionary.
self.assertIn("N14", mass)
self.assertAlmostEqual(sum(mass.values()), 1.0)
[docs] def test_getChemicals(self):
u235 = nuclideBases.byName["U235"]
u238 = nuclideBases.byName["U238"]
o16 = nuclideBases.byName["O16"]
uo2 = UO2()
uo2Chemicals = densityTools.getChemicals(uo2.massFrac)
for symbol in ["U", "O"]:
self.assertIn(symbol, uo2Chemicals.keys())
self.assertAlmostEqual(
uo2Chemicals["U"], uo2.massFrac["U235"] + uo2.massFrac["U238"], 6
)
self.assertAlmostEqual(uo2Chemicals["O"], uo2.massFrac["O"], 6)
# ensure getChemicals works if the nuclideBase is the dict key
massFrac = {u238: 0.87, u235: 0.12, o16: 0.01}
uo2Chemicals = densityTools.getChemicals(massFrac)
for symbol in ["U", "O"]:
self.assertIn(symbol, uo2Chemicals.keys())
self.assertAlmostEqual(uo2Chemicals["U"], massFrac[u235] + massFrac[u238], 2)
self.assertAlmostEqual(uo2Chemicals["O"], massFrac[o16], 2)
[docs] def test_expandElement(self):
"""Ensure isotopic subset feature works in expansion."""
elemental = elements.bySymbol["O"]
massFrac = 1.0
subset = [nuclideBases.byName["O16"], nuclideBases.byName["O17"]]
m1 = densityTools.expandElementalNuclideMassFracs(elemental, massFrac)
m2 = densityTools.expandElementalNuclideMassFracs(elemental, massFrac, subset)
self.assertIn("O18", m1)
self.assertNotIn("O18", m2)
self.assertAlmostEqual(1.0, sum(m1.values()))
self.assertAlmostEqual(1.0, sum(m2.values()))
# expect some small difference due to renormalization
self.assertNotAlmostEqual(m1["O17"], m2["O17"])
self.assertAlmostEqual(m1["O17"], m2["O17"], delta=1e-5)
[docs] def test_applyIsotopicsMix(self):
"""Ensure isotopc classes get mixed properly."""
uo2 = UO2()
massFracO = uo2.massFrac["O"]
uo2.class1_wt_frac = 0.2
enrichedMassFracs = {"U235": 0.3, "U234": 0.1, "PU239": 0.6}
fertileMassFracs = {"U238": 0.3, "PU240": 0.7}
densityTools.applyIsotopicsMix(uo2, enrichedMassFracs, fertileMassFracs)
self.assertAlmostEqual(
uo2.massFrac["U234"], (1 - massFracO) * 0.2 * 0.1
) # HM blended
self.assertAlmostEqual(
uo2.massFrac["U238"], (1 - massFracO) * 0.8 * 0.3
) # HM blended
self.assertAlmostEqual(uo2.massFrac["O"], massFracO) # non-HM stays unchanged
[docs] def test_getNDensFromMasses(self):
"""
Number densities from masses.
.. test:: Number densities are retrievable from masses.
:id: T_ARMI_UTIL_MASS2N_DENS
:tests: R_ARMI_UTIL_MASS2N_DENS
"""
nDens = densityTools.getNDensFromMasses(1, {"O": 1, "H": 2})
self.assertAlmostEqual(nDens["O"], 0.03764, 5)
self.assertAlmostEqual(nDens["H"], 1.19490, 5)
[docs] def test_getMassFractions(self):
"""Number densities to mass fraction."""
numDens = {"O17": 0.1512, "PU239": 1.5223, "U234": 0.135}
massFracs = densityTools.getMassFractions(numDens)
self.assertAlmostEqual(massFracs["O17"], 0.006456746320668389)
self.assertAlmostEqual(massFracs["PU239"], 0.9141724414849527)
self.assertAlmostEqual(massFracs["U234"], 0.07937081219437897)
[docs] def test_calculateNumberDensity(self):
"""Mass fraction to number density."""
nDens = densityTools.calculateNumberDensity("U235", 1, 1)
self.assertAlmostEqual(nDens, 0.0025621344549254283)
nDens = densityTools.calculateNumberDensity("PU239", 0.00012, 0.001)
self.assertAlmostEqual(nDens, 0.0003023009578309138)
nDens = densityTools.calculateNumberDensity("N15", 111, 222)
self.assertAlmostEqual(nDens, 0.020073659896941428)
[docs] def test_getMassInGrams(self):
m = densityTools.getMassInGrams("N16", 1.001, None)
self.assertEqual(m, 0)
m = densityTools.getMassInGrams("O17", 1.001, 0.00123)
self.assertAlmostEqual(m, 0.034754813848559635)
m = densityTools.getMassInGrams("PU239", 1.001, 2.123)
self.assertAlmostEqual(m, 843.5790671316283)
[docs] def test_normalizeNuclideList(self):
"""
Normalize a nuclide list.
.. test:: Normalize nuclide vector
:id: T_ARMI_UTIL_DENS_TOOLS
:tests: R_ARMI_UTIL_DENS_TOOLS
"""
nList = {"PU239": 23.2342, "U234": 0.001234, "U235": 34.152}
norm = densityTools.normalizeNuclideList(nList)
self.assertAlmostEqual(norm["PU239"], 0.40486563661306063)
self.assertAlmostEqual(norm["U234"], 2.1502965265880334e-05)
self.assertAlmostEqual(norm["U235"], 0.5951128604216736)
[docs] def test_formatMaterialCard(self):
"""Formatting material information into an MCNP input card.
.. test:: Create MCNP material card
:id: T_ARMI_UTIL_MCNP_MAT_CARD
:tests: R_ARMI_UTIL_MCNP_MAT_CARD
"""
u235 = nuclideBases.byName["U235"]
pu239 = nuclideBases.byName["PU239"]
o16 = nuclideBases.byName["O16"]
numDens = {o16: 0.7, pu239: 0.1, u235: 0.2}
matCard = densityTools.formatMaterialCard(
numDens,
matNum=1,
sigFigs=4,
)
refMatCard = """m1
8016 7.0000e-01
92235 2.0000e-01
94239 1.0000e-01
"""
self.assertEqual(refMatCard, "".join(matCard))
lfp35 = nuclideBases.byName["LFP35"]
dump1 = nuclideBases.byName["DUMP1"]
o16 = nuclideBases.byName["O16"]
numDens = {o16: 0.7, pu239: 1e-8, u235: 0.2, lfp35: 1e-3, dump1: 1e-4}
matCard = densityTools.formatMaterialCard(
numDens,
matNum=-1,
minDens=1e-6,
mcnp6Compatible=True,
mcnpLibrary="81",
)
refMatCard = """m{}
8016 7.00000000e-01
92235 2.00000000e-01
94239 1.00000000e-06
nlib=81c
"""
self.assertEqual(refMatCard, "".join(matCard))
numDens = {lfp35: 0.5, dump1: 0.5}
matCard = densityTools.formatMaterialCard(
numDens,
mcnp6Compatible=False,
mcnpLibrary=None,
)
refMatCard = []
self.assertEqual(refMatCard, matCard)