OpenMC/tests/unit_tests/test_data_neutron.py

365 lines
12 KiB
Python

#!/usr/bin/env python
from collections import Mapping, Callable
import os
import numpy as np
import pandas as pd
import pytest
import openmc.data
_TEMPERATURES = [300., 600., 900.]
_ENDF_DATA = os.environ['OPENMC_ENDF_DATA']
@pytest.fixture(scope='module')
def pu239():
"""Pu239 HDF5 data."""
directory = os.path.dirname(os.environ['OPENMC_CROSS_SECTIONS'])
filename = os.path.join(directory, 'Pu239.h5')
return openmc.data.IncidentNeutron.from_hdf5(filename)
@pytest.fixture(scope='module')
def xe135():
"""Xe135 ENDF data (contains SLBW resonance range)"""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-054_Xe_135.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def sm150():
"""Sm150 ENDF data (contains MLBW resonance range)"""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-062_Sm_150.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def gd154():
"""Gd154 ENDF data (contains Reich Moore resonance range)"""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-064_Gd_154.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def cl35():
"""Cl35 ENDF data (contains RML resonance range)"""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-017_Cl_035.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def am241():
"""Am241 ENDF data (contains Madland-Nix fission energy distribution)."""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-095_Am_241.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def u233():
"""U233 ENDF data (contains Watt fission energy distribution)."""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-092_U_233.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def u236():
"""U236 ENDF data (contains Watt fission energy distribution)."""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-092_U_236.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def na22():
"""Na22 ENDF data (contains evaporation spectrum)."""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-011_Na_022.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def be9():
"""Be9 ENDF data (contains laboratory angle-energy distribution)."""
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-004_Be_009.endf')
return openmc.data.IncidentNeutron.from_endf(filename)
@pytest.fixture(scope='module')
def h2():
endf_file = os.path.join(_ENDF_DATA, 'neutrons', 'n-001_H_002.endf')
return openmc.data.IncidentNeutron.from_njoy(
endf_file, temperatures=_TEMPERATURES)
@pytest.fixture(scope='module')
def am244():
endf_file = os.path.join(_ENDF_DATA, 'neutrons', 'n-095_Am_244.endf')
return openmc.data.IncidentNeutron.from_njoy(endf_file)
def test_attributes(pu239):
assert pu239.name == 'Pu239'
assert pu239.mass_number == 239
assert pu239.metastable == 0
assert pu239.atomic_symbol == 'Pu'
assert pu239.atomic_weight_ratio == pytest.approx(236.9986)
def test_fission_energy(pu239):
fer = pu239.fission_energy
assert isinstance(fer, openmc.data.FissionEnergyRelease)
components = ['betas', 'delayed_neutrons', 'delayed_photons', 'fragments',
'neutrinos', 'prompt_neutrons', 'prompt_photons', 'recoverable',
'total', 'q_prompt', 'q_recoverable', 'q_total']
for c in components:
assert isinstance(getattr(fer, c), Callable)
def test_compact_fission_energy(tmpdir):
files = [os.path.join(_ENDF_DATA, 'neutrons', 'n-090_Th_232.endf'),
os.path.join(_ENDF_DATA, 'neutrons', 'n-094_Pu_240.endf'),
os.path.join(_ENDF_DATA, 'neutrons', 'n-094_Pu_241.endf')]
output = str(tmpdir.join('compact_lib.h5'))
openmc.data.write_compact_458_library(files, output)
assert os.path.exists(output)
def test_energy_grid(pu239):
assert isinstance(pu239.energy, Mapping)
for temp, grid in pu239.energy.items():
assert temp.endswith('K')
assert np.all(np.diff(grid) >= 0.0)
def test_reactions(pu239):
assert 2 in pu239.reactions
assert isinstance(pu239.reactions[2], openmc.data.Reaction)
with pytest.raises(KeyError):
pu239.reactions[14]
def test_elastic(pu239):
elastic = pu239.reactions[2]
assert elastic.center_of_mass
assert elastic.q_value == 0.0
assert elastic.mt == 2
assert '0K' in elastic.xs
assert '294K' in elastic.xs
assert len(elastic.products) == 1
p = elastic.products[0]
assert isinstance(p, openmc.data.Product)
assert p.particle == 'neutron'
assert p.emission_mode == 'prompt'
assert len(p.distribution) == 1
d = p.distribution[0]
assert isinstance(d, openmc.data.UncorrelatedAngleEnergy)
assert isinstance(d.angle, openmc.data.AngleDistribution)
assert d.energy is None
assert p.yield_(0.0) == 1.0
def test_fission(pu239):
fission = pu239.reactions[18]
assert not fission.center_of_mass
assert fission.q_value == pytest.approx(198902000.0)
assert fission.mt == 18
assert '294K' in fission.xs
assert len(fission.products) == 8
prompt = fission.products[0]
assert prompt.particle == 'neutron'
assert prompt.yield_(1.0e-5) == pytest.approx(2.874262)
delayed = [p for p in fission.products if p.emission_mode == 'delayed']
assert len(delayed) == 6
assert all(d.particle == 'neutron' for d in delayed)
assert sum(d.decay_rate for d in delayed) == pytest.approx(4.037212)
assert sum(d.yield_(1.0) for d in delayed) == pytest.approx(0.00645)
photon = fission.products[-1]
assert photon.particle == 'photon'
def test_derived_products(am244):
fission = am244.reactions[18]
total_neutron = fission.derived_products[0]
assert total_neutron.emission_mode == 'total'
assert total_neutron.yield_(6e6) == pytest.approx(4.2558)
def test_urr(pu239):
for T, ptable in pu239.urr.items():
assert T.endswith('K')
assert isinstance(ptable, openmc.data.ProbabilityTables)
ptable = pu239.urr['294K']
assert ptable.absorption_flag == -1
assert ptable.energy[0] == pytest.approx(2500.001)
assert ptable.energy[-1] == pytest.approx(29999.99)
assert ptable.inelastic_flag == 51
assert ptable.interpolation == 2
assert not ptable.multiply_smooth
assert ptable.table.shape == (70, 6, 20)
assert ptable.table.shape[0] == ptable.energy.size
def test_get_reaction_components(h2):
assert h2.get_reaction_components(1) == [2, 16, 102]
assert h2.get_reaction_components(101) == [102]
assert h2.get_reaction_components(16) == [16]
assert h2.get_reaction_components(51) == []
def test_export_to_hdf5(tmpdir, pu239, gd154):
filename = str(tmpdir.join('pu239.h5'))
pu239.export_to_hdf5(filename)
assert os.path.exists(filename)
with pytest.raises(NotImplementedError):
gd154.export_to_hdf5('gd154.h5')
def test_slbw(xe135):
res = xe135.resonances
assert isinstance(res, openmc.data.Resonances)
assert len(res.ranges) == 2
resolved = res.resolved
assert isinstance(resolved, openmc.data.SingleLevelBreitWigner)
assert resolved.energy_min == pytest.approx(1e-5)
assert resolved.energy_max == pytest.approx(190.)
assert resolved.target_spin == pytest.approx(1.5)
assert isinstance(resolved.parameters, pd.DataFrame)
s = resolved.parameters.iloc[0]
assert s['energy'] == pytest.approx(0.084)
xs = resolved.reconstruct([10., 30., 100.])
assert sorted(xs.keys()) == [2, 18, 102]
assert np.all(xs[18] == 0.0)
def test_mlbw(sm150):
resolved = sm150.resonances.resolved
assert isinstance(resolved, openmc.data.MultiLevelBreitWigner)
assert resolved.energy_min == pytest.approx(1e-5)
assert resolved.energy_max == pytest.approx(1570.)
assert resolved.target_spin == 0.0
xs = resolved.reconstruct([10., 100., 1000.])
assert sorted(xs.keys()) == [2, 18, 102]
assert np.all(xs[18] == 0.0)
def test_reichmoore(gd154):
res = gd154.resonances
assert isinstance(res, openmc.data.Resonances)
assert len(res.ranges) == 2
resolved, unresolved = res.ranges
assert resolved is res.resolved
assert unresolved is res.unresolved
assert isinstance(resolved, openmc.data.ReichMoore)
assert isinstance(unresolved, openmc.data.Unresolved)
assert resolved.energy_min == pytest.approx(1e-5)
assert resolved.energy_max == pytest.approx(2760.)
assert resolved.target_spin == 0.0
assert resolved.channel_radius[0](1.0) == pytest.approx(0.74)
assert isinstance(resolved.parameters, pd.DataFrame)
assert (resolved.parameters['L'] == 0).all()
assert (resolved.parameters['J'] <= 0.5).all()
assert (resolved.parameters['fissionWidthA'] == 0.0).all()
elastic = gd154.reactions[2].xs['0K']
assert isinstance(elastic, openmc.data.ResonancesWithBackground)
assert elastic(0.0253) == pytest.approx(5.7228949796394524)
def test_rml(cl35):
resolved = cl35.resonances.resolved
assert isinstance(resolved, openmc.data.RMatrixLimited)
assert resolved.energy_min == pytest.approx(1e-5)
assert resolved.energy_max == pytest.approx(1.2e6)
assert resolved.target_spin == 0.0
for group in resolved.spin_groups:
assert isinstance(group, openmc.data.SpinGroup)
def test_madland_nix(am241):
fission = am241.reactions[18]
prompt_neutron = fission.products[0]
dist = prompt_neutron.distribution[0].energy
assert isinstance(dist, openmc.data.MadlandNix)
assert dist.efl == pytest.approx(1029979.0)
assert dist.efh == pytest.approx(546729.7)
assert isinstance(dist.tm, Callable)
def test_watt(u233):
fission = u233.reactions[18]
prompt_neutron = fission.products[0]
dist = prompt_neutron.distribution[0].energy
assert isinstance(dist, openmc.data.WattEnergy)
def test_maxwell(u236):
fission = u236.reactions[18]
prompt_neutron = fission.products[0]
dist = prompt_neutron.distribution[0].energy
assert isinstance(dist, openmc.data.MaxwellEnergy)
def test_evaporation(na22):
n2n = na22.reactions[16]
dist = n2n.products[0].distribution[0].energy
assert isinstance(dist, openmc.data.Evaporation)
def test_laboratory(be9):
n2n = be9.reactions[16]
dist = n2n.products[0].distribution[0]
assert isinstance(dist, openmc.data.LaboratoryAngleEnergy)
assert list(dist.breakpoints) == [18]
assert list(dist.interpolation) == [2]
assert dist.energy[0] == pytest.approx(1748830.)
assert dist.energy[-1] == pytest.approx(20.e6)
assert len(dist.energy) == len(dist.energy_out) == len(dist.mu)
for eout, mu in zip(dist.energy_out, dist.mu):
assert len(eout) == len(mu)
assert np.all((-1. <= mu.x) & (mu.x <= 1.))
def test_correlated(tmpdir):
endf_file = os.path.join(_ENDF_DATA, 'neutrons', 'n-014_Si_030.endf')
si30 = openmc.data.IncidentNeutron.from_njoy(endf_file, heatr=False)
# Convert to HDF5 and read back
filename = str(tmpdir.join('si30.h5'))
si30.export_to_hdf5(filename)
si30_copy = openmc.data.IncidentNeutron.from_hdf5(filename)
def test_nbody(tmpdir, h2):
# Convert to HDF5 and read back
filename = str(tmpdir.join('h2.h5'))
h2.export_to_hdf5(filename)
h2_copy = openmc.data.IncidentNeutron.from_hdf5(filename)
# Compare distributions
nbody1 = h2[16].products[0].distribution[0]
nbody2 = h2_copy[16].products[0].distribution[0]
assert nbody1.total_mass == nbody2.total_mass
assert nbody1.n_particles == nbody2.n_particles
assert nbody1.q_value == nbody2.q_value
def test_ace_convert(run_in_tmpdir):
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-001_H_001.endf')
ace_ascii = 'ace_ascii'
ace_binary = 'ace_binary'
openmc.data.njoy.make_ace(filename, ace=ace_ascii)
# Convert to binary
openmc.data.ace.ascii_to_binary(ace_ascii, ace_binary)
# Make sure conversion worked
lib_ascii = openmc.data.ace.Library(ace_ascii)
lib_binary = openmc.data.ace.Library(ace_binary)
for tab_a, tab_b in zip(lib_ascii.tables, lib_binary.tables):
assert tab_a.name == tab_b.name
assert tab_a.atomic_weight_ratio == pytest.approx(tab_b.atomic_weight_ratio)
assert tab_a.temperature == pytest.approx(tab_b.temperature)
assert np.all(tab_a.nxs == tab_b.nxs)
assert np.all(tab_a.jxs == tab_b.jxs)