Source code for armi.reactor.blueprints.tests.test_customIsotopics

# 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.

"""Unit test custom isotopics."""
import unittest

import yamlize

from armi import settings
from armi.physics.neutronics.settings import CONF_XS_KERNEL
from armi.reactor import blueprints
from armi.reactor.blueprints import isotopicOptions
from armi.reactor.flags import Flags


[docs]class TestCustomIsotopics(unittest.TestCase): yamlString = r""" nuclide flags: U238: {burn: true, xs: true} U235: {burn: true, xs: true} U234: {burn: true, xs: true} ZR: {burn: false, xs: true} AL: {burn: false, xs: true} FE: {burn: false, xs: true} C: {burn: false, xs: true} DUMP2: {burn: true, xs: true} DUMP1: {burn: true, xs: true} LFP35: {burn: true, xs: true} PU239: {burn: true, xs: true} NP237: {burn: true, xs: true} LFP38: {burn: true, xs: true} LFP39: {burn: true, xs: true} PU240: {burn: true, xs: true} PU236: {burn: true, xs: true} PU238: {burn: true, xs: true} U236: {burn: true, xs: true} LFP40: {burn: true, xs: true} PU241: {burn: true, xs: true} AM241: {burn: true, xs: true} LFP41: {burn: true, xs: true} PU242: {burn: true, xs: true} AM243: {burn: true, xs: true} CM244: {burn: true, xs: true} CM242: {burn: true, xs: true} AM242: {burn: true, xs: true} CM245: {burn: true, xs: true} NP238: {burn: true, xs: true} CM243: {burn: true, xs: true} CM246: {burn: true, xs: true} CM247: {burn: true, xs: true} NI: {burn: true, xs: true} W: {burn: true, xs: true, expandTo: ["W182", "W183", "W184", "W186"]} MN: {burn: true, xs: true} CR: {burn: true, xs: true} V: {burn: true, xs: true} SI: {burn: true, xs: true} MO: {burn: true, xs: true} custom isotopics: uranium isotopic mass fractions: input format: mass fractions U238: 0.992742 U235: 0.007204 U234: 0.000054 density: 19.1 # >>> from armi.nucDirectory import elements, nuclideBases # >>> import numpy # >>> u = elements.bySymbol['U'] # >>> w_i = numpy.array([n.abundance for n in u.getNaturalIsotopics()]) # >>> Mi = numpy.array([n.weight for n in u.getNaturalIsotopics()]) # >>> Ni = w_i * 19.1 * 6.0221e23 / Mi # >>> N_norm = Ni / sum(Ni) # >>> N_norm.round(6) # array([ 5.50000000e-05, 7.29500000e-03, 9.92650000e-01]) uranium isotopic number fractions: input format: number fractions U238: 0.992650 U235: 0.007295 U234: 0.000055 density: 19.1 # >>> from armi.nucDirectory import elements, nuclideBases # >>> import numpy # >>> u = elements.bySymbol['U'] # >>> Mi = numpy.array([n.weight for n in u.getNaturalIsotopics()]) # >>> w_i = numpy.array([n.abundance for n in u.getNaturalIsotopics()]) # >>> Ni = 19.1 * w_i * 6.0221e23 / Mi # array([ 2.65398007e+18, 3.52549755e+20, 4.79692055e+22]) # >>> for n, ni in zip(u.getNaturalIsotopics(), Ni): # >>> print ' {}: {:.7e}'.format(n.name, ni) # requires 7 decimal places! uranium isotopic number densities: &u_isotopics input format: number densities U234: 2.6539102e-06 U235: 3.5254048e-04 U238: 4.7967943e-02 linked uranium number densities: *u_isotopics steel: input format: mass fractions FE: 0.7 C: 0.3 density: 7.0 blocks: uzr fuel: &block_0 fuel: &basic_fuel shape: Hexagon material: UZr Tinput: 25.0 Thot: 600.0 ip: 0.0 mult: 1.0 op: 10.0 clad: shape: Circle material: HT9 Tinput: 25.0 Thot: 600.0 id: 0.0 mult: 1.0 od: 10.0 uranium fuel from isotopic mass fractions : &block_1 fuel: <<: *basic_fuel material: Custom isotopics: uranium isotopic mass fractions wrong material: &block_2 fuel: <<: *basic_fuel isotopics: uranium isotopic mass fractions uranium fuel from number fractions: &block_3 fuel: <<: *basic_fuel material: Custom isotopics: uranium isotopic number fractions uranium fuel from number densities: &block_4 fuel: <<: *basic_fuel material: Custom isotopics: uranium isotopic number densities uranium fuel from nd link: &block_5 fuel: <<: *basic_fuel material: Custom isotopics: linked uranium number densities steel: &block_6 clad: shape: Hexagon material: Custom isotopics: steel Tinput: 25.0 Thot: 600.0 ip: 0.0 mult: 169.0 op: 0.86602 assemblies: fuel a: &assembly_a specifier: IC blocks: [*block_0, *block_1, *block_2, *block_3, *block_4, *block_5, *block_6] height: [10, 10, 10, 10, 10, 10,10] axial mesh points: [1, 1, 1, 1, 1, 1,1] xs types: [A, A, A, A, A, A,A] """ """:meta hide-value:""" @classmethod def setUpClass(cls): cs = settings.Settings() cs = cs.modified(newSettings={CONF_XS_KERNEL: "MC2v2"}) cls.bp = blueprints.Blueprints.load(cls.yamlString) cls.a = cls.bp.constructAssem(cs, name="fuel a") cls.numUZrNuclides = 29 # Number of nuclides defined `nuclide flags` cls.numCustomNuclides = ( 28 # Number of nuclides defined in `nuclide flags` without Zr )
[docs] def test_unmodified(self): """Ensure that unmodified components have the correct isotopics.""" fuel = self.a[0].getComponent(Flags.FUEL) self.assertEqual( self.numUZrNuclides, len(fuel.p.numberDensities), msg=fuel.p.numberDensities.keys(), ) # Note this density does not come from the material but is based on number densities self.assertAlmostEqual(15.5, fuel.density(), 0) # i.e. it is not 19.1
[docs] def test_massFractionsAreApplied(self): """Ensure that the custom isotopics can be specified via mass fractions. .. test:: Test that custom isotopics can be specified via mass fractions. :id: T_ARMI_MAT_USER_INPUT3 :tests: R_ARMI_MAT_USER_INPUT """ fuel0 = self.a[0].getComponent(Flags.FUEL) fuel1 = self.a[1].getComponent(Flags.FUEL) fuel2 = self.a[2].getComponent(Flags.FUEL) self.assertEqual(self.numCustomNuclides, len(fuel1.p.numberDensities)) self.assertAlmostEqual(19.1, fuel1.density()) # density only works with a Custom material type. self.assertAlmostEqual(fuel0.density(), fuel2.density()) self.assertEqual( set(fuel2.p.numberDensities.keys()), set(fuel1.p.numberDensities.keys()) ) # keys are same
[docs] def test_numberFractions(self): """Ensure that the custom isotopics can be specified via number fractions. .. test:: Test that custom isotopics can be specified via number fractions. :id: T_ARMI_MAT_USER_INPUT4 :tests: R_ARMI_MAT_USER_INPUT """ # fuel blocks 2 and 4 should be the same, one is defined as mass fractions, and the other as number fractions fuel2 = self.a[1].getComponent(Flags.FUEL) fuel4 = self.a[3].getComponent(Flags.FUEL) self.assertAlmostEqual(fuel2.density(), fuel4.density()) for nuc in fuel2.p.numberDensities.keys(): self.assertAlmostEqual( fuel2.p.numberDensities[nuc], fuel4.p.numberDensities[nuc] )
[docs] def test_numberDensities(self): """Ensure that the custom isotopics can be specified via number densities. .. test:: Test that custom isotopics can be specified via number fractions. :id: T_ARMI_MAT_USER_INPUT5 :tests: R_ARMI_MAT_USER_INPUT """ # fuel blocks 2 and 5 should be the same, one is defined as mass fractions, and the other as number densities fuel2 = self.a[1].getComponent(Flags.FUEL) fuel5 = self.a[4].getComponent(Flags.FUEL) self.assertAlmostEqual(fuel2.density(), fuel5.density()) for nuc in fuel2.p.numberDensities.keys(): self.assertAlmostEqual( fuel2.p.numberDensities[nuc], fuel5.p.numberDensities[nuc] )
[docs] def test_numberDensitiesAnchor(self): fuel4 = self.a[4].getComponent(Flags.FUEL) fuel5 = self.a[5].getComponent(Flags.FUEL) self.assertAlmostEqual(fuel4.density(), fuel5.density()) for nuc in fuel4.p.numberDensities.keys(): self.assertAlmostEqual( fuel4.p.numberDensities[nuc], fuel5.p.numberDensities[nuc] )
[docs] def test_expandedNatural(self): cs = settings.Settings() cs = cs.modified(newSettings={CONF_XS_KERNEL: "MC2v3"}) bp = blueprints.Blueprints.load(self.yamlString) a = bp.constructAssem(cs, name="fuel a") b = a[-1] c = b.getComponent(Flags.CLAD) self.assertIn("FE56", c.getNumberDensities()) # natural isotopic self.assertNotIn("FE51", c.getNumberDensities()) # un-natural self.assertNotIn("FE", c.getNumberDensities())
[docs] def test_unrepresentedAreOnlyNatural(self): """Make sure nuclides specified as In-Problem but not actually in any material are only natural isotopics.""" self.assertIn("AL27", self.bp.allNuclidesInProblem) self.assertNotIn("AL26", self.bp.allNuclidesInProblem)
[docs]class TestCustomIsotopics_ErrorConditions(unittest.TestCase):
[docs] def test_densityMustBePositive(self): with self.assertRaises(yamlize.YamlizingError): _ = isotopicOptions.CustomIsotopic.load( r""" name: atom repellent input format: mass fractions U234: 2.6539102e-06 U235: 3.5254048e-04 U238: 4.7967943e-02 density: -0.0001 """ )
[docs] def test_nonConformantElementName(self): with self.assertRaises(yamlize.YamlizingError): _ = isotopicOptions.CustomIsotopic.load( r""" name: non-upper case input format: number densities Au: 0.01 """ )
[docs] def test_numberDensitiesCannotSpecifyDensity(self): with self.assertRaises(yamlize.YamlizingError): _ = isotopicOptions.CustomIsotopic.load( r""" name: over-specified isotopics input format: number densities AU: 0.01 density: 10.0 """ )
[docs]class TestNuclideFlagsExpansion(unittest.TestCase): yamlString = r""" nuclide flags: U238: {burn: false, xs: true} U235: {burn: false, xs: true} ZR: {burn: false, xs: true} AL: {burn: false, xs: true} FE: {burn: false, xs: true, expandTo: ["FE54"]} C: {burn: false, xs: true} NI: {burn: true, xs: true} MN: {burn: true, xs: true} CR: {burn: true, xs: true} V: {burn: true, xs: true} SI: {burn: true, xs: true} MO: {burn: true, xs: true} W: {burn: true, xs: true} blocks: uzr fuel: &block_0 fuel: shape: Hexagon material: UZr Tinput: 25.0 Thot: 600.0 mult: 1.0 op: 10.0 clad: shape: Circle material: HT9 Tinput: 25.0 Thot: 600.0 id: 0.0 mult: 1.0 od: 10.0 assemblies: fuel a: specifier: IC blocks: [*block_0] height: [10] axial mesh points: [1] xs types: [A] """
[docs] def test_expandedNatural(self): cs = settings.Settings() cs = cs.modified(newSettings={CONF_XS_KERNEL: "MC2v3"}) bp = blueprints.Blueprints.load(self.yamlString) a = bp.constructAssem(cs, name="fuel a") b = a[-1] c = b.getComponent(Flags.CLAD) nd = c.getNumberDensities() self.assertIn("FE54", nd) # natural isotopic as requested self.assertNotIn("FE56", nd) # natural isotopic not requested self.assertNotIn("FE51", nd) # un-natural self.assertNotIn("FE", nd)