mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 13:45:36 -04:00
Merge pull request #1024 from icmeyer/develop
Resonace Covariance Module
This commit is contained in:
commit
cbb9ace80e
10 changed files with 1919 additions and 10 deletions
|
|
@ -24,6 +24,7 @@ Basic Usage
|
|||
triso
|
||||
candu
|
||||
nuclear-data
|
||||
nuclear-data-resonance-covariance
|
||||
|
||||
------------------------------------
|
||||
Multi-Group Cross Section Generation
|
||||
|
|
|
|||
13
docs/source/examples/nuclear-data-resonance-covariance.rst
Normal file
13
docs/source/examples/nuclear-data-resonance-covariance.rst
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
.. _notebook_nuclear_data_resonance_covariance:
|
||||
|
||||
==================================
|
||||
Nuclear Data: Resonance Covariance
|
||||
==================================
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. notebook:: ../../../examples/jupyter/nuclear-data-resonance-covariance.ipynb
|
||||
|
||||
.. only:: latex
|
||||
|
||||
IPython notebooks must be viewed in the online HTML documentation.
|
||||
|
|
@ -79,6 +79,11 @@ Resonance Data
|
|||
openmc.data.MultiLevelBreitWigner
|
||||
openmc.data.ReichMoore
|
||||
openmc.data.RMatrixLimited
|
||||
openmc.data.ResonanceCovariances
|
||||
openmc.data.ResonanceCovarianceRange
|
||||
openmc.data.SingleLevelBreitWignerCovariance
|
||||
openmc.data.MultiLevelBreitWignerCovariance
|
||||
openmc.data.ReichMooreCovariance
|
||||
openmc.data.ParticlePair
|
||||
openmc.data.SpinGroup
|
||||
openmc.data.Unresolved
|
||||
|
|
|
|||
964
examples/jupyter/nuclear-data-resonance-covariance.ipynb
Normal file
964
examples/jupyter/nuclear-data-resonance-covariance.ipynb
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -27,5 +27,6 @@ from .urr import *
|
|||
from .library import *
|
||||
from .fission_energy import *
|
||||
from .resonance import *
|
||||
from .resonance_covariance import *
|
||||
from .multipole import *
|
||||
from .grid import *
|
||||
|
|
|
|||
|
|
@ -71,6 +71,24 @@ def float_endf(s):
|
|||
return float(_ENDF_FLOAT_RE.sub(r'\1e\2', s))
|
||||
|
||||
|
||||
def _int_endf(s):
|
||||
"""Convert string to int. Used for INTG records where blank entries
|
||||
indicate a 0.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
s : str
|
||||
Integer or spaces
|
||||
|
||||
Returns
|
||||
-------
|
||||
integer
|
||||
The number or 0
|
||||
"""
|
||||
s = s.strip()
|
||||
return int(s) if s else 0
|
||||
|
||||
|
||||
def get_text_record(file_obj):
|
||||
"""Return data from a TEXT record in an ENDF-6 file.
|
||||
|
||||
|
|
@ -250,6 +268,50 @@ def get_tab2_record(file_obj):
|
|||
return params, Tabulated2D(breakpoints, interpolation)
|
||||
|
||||
|
||||
def get_intg_record(file_obj):
|
||||
"""
|
||||
Return data from an INTG record in an ENDF-6 file. Used to store the
|
||||
covariance matrix in a compact format.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
file_obj : file-like object
|
||||
ENDF-6 file to read from
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
The correlation matrix described in the INTG record
|
||||
"""
|
||||
# determine how many items are in list and NDIGIT
|
||||
items = get_cont_record(file_obj)
|
||||
ndigit = int(items[2])
|
||||
npar = int(items[3]) # Number of parameters
|
||||
nlines = int(items[4]) # Lines to read
|
||||
NROW_RULES = {2: 18, 3: 12, 4: 11, 5: 9, 6: 8}
|
||||
nrow = NROW_RULES[ndigit]
|
||||
|
||||
# read lines and build correlation matrix
|
||||
corr = np.identity(npar)
|
||||
for i in range(nlines):
|
||||
line = file_obj.readline()
|
||||
ii = _int_endf(line[:5]) - 1 # -1 to account for 0 indexing
|
||||
jj = _int_endf(line[5:10]) - 1
|
||||
factor = 10**ndigit
|
||||
for j in range(nrow):
|
||||
if jj+j >= ii:
|
||||
break
|
||||
element = _int_endf(line[11+(ndigit+1)*j:11+(ndigit+1)*(j+1)])
|
||||
if element > 0:
|
||||
corr[ii, jj] = (element+0.5)/factor
|
||||
elif element < 0:
|
||||
corr[ii, jj] = (element-0.5)/factor
|
||||
|
||||
# Symmetrize the correlation matrix
|
||||
corr = corr + corr.T - np.diag(corr.diagonal())
|
||||
return corr
|
||||
|
||||
|
||||
def get_evaluations(filename):
|
||||
"""Return a list of all evaluations within an ENDF file.
|
||||
|
||||
|
|
@ -288,7 +350,7 @@ class Evaluation(object):
|
|||
Attributes
|
||||
----------
|
||||
info : dict
|
||||
Miscallaneous information about the evaluation.
|
||||
Miscellaneous information about the evaluation.
|
||||
target : dict
|
||||
Information about the target material, such as its mass, isomeric state,
|
||||
whether it's stable, and whether it's fissionable.
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ from .njoy import make_ace
|
|||
from .product import Product
|
||||
from .reaction import Reaction, _get_photon_products_ace
|
||||
from . import resonance as res
|
||||
from . import resonance_covariance as res_cov
|
||||
from .urr import ProbabilityTables
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
|
|
@ -148,6 +149,8 @@ class IncidentNeutron(EqualityMixin):
|
|||
and the values are Reaction objects.
|
||||
resonances : openmc.data.Resonances or None
|
||||
Resonance parameters
|
||||
resonance_covariance : openmc.data.ResonanceCovariance or None
|
||||
Covariance for resonance parameters
|
||||
summed_reactions : collections.OrderedDict
|
||||
Contains summed cross sections, e.g., the total cross section. The keys
|
||||
are the MT values and the values are Reaction objects.
|
||||
|
|
@ -228,6 +231,10 @@ class IncidentNeutron(EqualityMixin):
|
|||
def resonances(self):
|
||||
return self._resonances
|
||||
|
||||
@property
|
||||
def resonance_covariance(self):
|
||||
return self._resonance_covariance
|
||||
|
||||
@property
|
||||
def summed_reactions(self):
|
||||
return self._summed_reactions
|
||||
|
|
@ -289,6 +296,12 @@ class IncidentNeutron(EqualityMixin):
|
|||
cv.check_type('resonances', resonances, res.Resonances)
|
||||
self._resonances = resonances
|
||||
|
||||
@resonance_covariance.setter
|
||||
def resonance_covariance(self, resonance_covariance):
|
||||
cv.check_type('resonance covariance', resonance_covariance,
|
||||
res_cov.ResonanceCovariances)
|
||||
self._resonance_covariance = resonance_covariance
|
||||
|
||||
@summed_reactions.setter
|
||||
def summed_reactions(self, summed_reactions):
|
||||
cv.check_type('summed reactions', summed_reactions, Mapping)
|
||||
|
|
@ -744,7 +757,7 @@ class IncidentNeutron(EqualityMixin):
|
|||
return data
|
||||
|
||||
@classmethod
|
||||
def from_endf(cls, ev_or_filename):
|
||||
def from_endf(cls, ev_or_filename, covariance=False):
|
||||
"""Generate incident neutron continuous-energy data from an ENDF evaluation
|
||||
|
||||
Parameters
|
||||
|
|
@ -753,6 +766,10 @@ class IncidentNeutron(EqualityMixin):
|
|||
ENDF evaluation to read from. If given as a string, it is assumed to
|
||||
be the filename for the ENDF file.
|
||||
|
||||
covariance : bool
|
||||
Flag to indicate whether or not covariance data from File 32 should be
|
||||
retrieved
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.data.IncidentNeutron
|
||||
|
|
@ -784,6 +801,11 @@ class IncidentNeutron(EqualityMixin):
|
|||
if (2, 151) in ev.section:
|
||||
data.resonances = res.Resonances.from_endf(ev)
|
||||
|
||||
if (32, 151) in ev.section and covariance:
|
||||
data.resonance_covariance = (
|
||||
res_cov.ResonanceCovariances.from_endf(ev, data.resonances)
|
||||
)
|
||||
|
||||
# Read each reaction
|
||||
for mf, mt, nc, mod in ev.reaction_list:
|
||||
if mf == 3:
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ except ImportError:
|
|||
_reconstruct = False
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
class Resonances(object):
|
||||
"""Resolved and unresolved resonance data
|
||||
|
||||
|
|
@ -90,14 +91,14 @@ class Resonances(object):
|
|||
|
||||
# Determine whether discrete or continuous representation
|
||||
items = get_head_record(file_obj)
|
||||
n_isotope = items[4] # Number of isotopes
|
||||
n_isotope = items[4] # Number of isotopes
|
||||
|
||||
ranges = []
|
||||
for iso in range(n_isotope):
|
||||
items = get_cont_record(file_obj)
|
||||
abundance = items[1]
|
||||
fission_widths = (items[3] == 1) # fission widths are given?
|
||||
n_ranges = items[4] # number of resonance energy ranges
|
||||
fission_widths = (items[3] == 1) # fission widths are given?
|
||||
n_ranges = items[4] # number of resonance energy ranges
|
||||
|
||||
for j in range(n_ranges):
|
||||
items = get_cont_record(file_obj)
|
||||
|
|
@ -112,7 +113,7 @@ class Resonances(object):
|
|||
# unresolved resonance region
|
||||
erange = Unresolved.from_endf(file_obj, items, fission_widths)
|
||||
|
||||
#erange.material = self
|
||||
# erange.material = self
|
||||
ranges.append(erange)
|
||||
|
||||
return cls(ranges)
|
||||
|
|
@ -162,6 +163,13 @@ class ResonanceRange(object):
|
|||
self._prepared = False
|
||||
self._parameter_matrix = {}
|
||||
|
||||
def __copy__(self):
|
||||
cls = type(self)
|
||||
new_copy = cls.__new__(cls)
|
||||
new_copy.__dict__.update(self.__dict__)
|
||||
new_copy._prepared = False
|
||||
return new_copy
|
||||
|
||||
@classmethod
|
||||
def from_endf(cls, ev, file_obj, items):
|
||||
"""Create resonance range from an ENDF evaluation.
|
||||
|
|
@ -437,7 +445,7 @@ class MultiLevelBreitWigner(ResonanceRange):
|
|||
self._l_values = np.array(l_values)
|
||||
self._competitive = np.array(competitive)
|
||||
for l in l_values:
|
||||
self._parameter_matrix[l] = df[df.L == l].as_matrix()
|
||||
self._parameter_matrix[l] = df[df.L == l].values
|
||||
|
||||
self._prepared = True
|
||||
|
||||
|
|
@ -682,7 +690,7 @@ class ReichMoore(ResonanceRange):
|
|||
self._l_values = np.array(l_values)
|
||||
for (l, J) in lj_values:
|
||||
self._parameter_matrix[l, J] = df[(df.L == l) &
|
||||
(abs(df.J) == J)].as_matrix()
|
||||
(abs(df.J) == J)].values
|
||||
|
||||
self._prepared = True
|
||||
|
||||
|
|
|
|||
708
openmc/data/resonance_covariance.py
Normal file
708
openmc/data/resonance_covariance.py
Normal file
|
|
@ -0,0 +1,708 @@
|
|||
from collections import MutableSequence
|
||||
import warnings
|
||||
import io
|
||||
import copy
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from . import endf
|
||||
import openmc.checkvalue as cv
|
||||
from .resonance import Resonances
|
||||
|
||||
|
||||
def _add_file2_contributions(file32params, file2params):
|
||||
"""Function for aiding in adding resonance parameters from File 2 that are
|
||||
not always present in File 32. Uses already imported resonance data.
|
||||
|
||||
Paramaters
|
||||
----------
|
||||
file32params : pandas.Dataframe
|
||||
Incomplete set of resonance parameters contained in File 32.
|
||||
file2params : pandas.Dataframe
|
||||
Resonance parameters from File 2. Ordered by energy.
|
||||
|
||||
Returns
|
||||
-------
|
||||
parameters : pandas.Dataframe
|
||||
Complete set of parameters ordered by L-values and then energy
|
||||
|
||||
"""
|
||||
# Use l-values and competitiveWidth from File 2 data
|
||||
# Re-sort File 2 by energy to match File 32
|
||||
file2params = file2params.sort_values(by=['energy'])
|
||||
file2params.reset_index(drop=True, inplace=True)
|
||||
# Sort File 32 parameters by energy as well (maintaining index)
|
||||
file32params.sort_values(by=['energy'], inplace=True)
|
||||
# Add in values (.values converts to array first to ignore index)
|
||||
file32params['L'] = file2params['L'].values
|
||||
if 'competitiveWidth' in file2params.columns:
|
||||
file32params['competitiveWidth'] = file2params['competitiveWidth'].values
|
||||
# Resort to File 32 order (by L then by E) for use with covariance
|
||||
file32params.sort_index(inplace=True)
|
||||
return file32params
|
||||
|
||||
|
||||
class ResonanceCovariances(Resonances):
|
||||
"""Resolved resonance covariance data
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ranges : list of openmc.data.ResonanceCovarianceRange
|
||||
Distinct energy ranges for resonance data
|
||||
|
||||
Attributes
|
||||
----------
|
||||
ranges : list of openmc.data.ResonanceCovarianceRange
|
||||
Distinct energy ranges for resonance data
|
||||
|
||||
"""
|
||||
|
||||
@property
|
||||
def ranges(self):
|
||||
return self._ranges
|
||||
|
||||
@ranges.setter
|
||||
def ranges(self, ranges):
|
||||
cv.check_type('resonance ranges', ranges, MutableSequence)
|
||||
self._ranges = cv.CheckedList(ResonanceCovarianceRange,
|
||||
'resonance range', ranges)
|
||||
|
||||
@classmethod
|
||||
def from_endf(cls, ev, resonances):
|
||||
"""Generate resonance covariance data from an ENDF evaluation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ev : openmc.data.endf.Evaluation
|
||||
ENDF evaluation
|
||||
resonances : openmc.data.Resonance object
|
||||
openmc.data.Resonanance object generated from the same evaluation
|
||||
used to import values not contained in File 32
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.data.ResonanceCovariances
|
||||
Resonance covariance data
|
||||
|
||||
"""
|
||||
file_obj = io.StringIO(ev.section[32, 151])
|
||||
|
||||
# Determine whether discrete or continuous representation
|
||||
items = endf.get_head_record(file_obj)
|
||||
n_isotope = items[4] # Number of isotopes
|
||||
|
||||
ranges = []
|
||||
for iso in range(n_isotope):
|
||||
items = endf.get_cont_record(file_obj)
|
||||
abundance = items[1]
|
||||
fission_widths = (items[3] == 1) # Flag for fission widths
|
||||
n_ranges = items[4] # Number of resonance energy ranges
|
||||
|
||||
for j in range(n_ranges):
|
||||
items = endf.get_cont_record(file_obj)
|
||||
# Unresolved flags - 0: only scattering radius given
|
||||
# 1: resolved parameters given
|
||||
# 2: unresolved parameters given
|
||||
unresolved_flag = items[2]
|
||||
formalism = items[3] # resonance formalism
|
||||
|
||||
# Throw error for unsupported formalisms
|
||||
if formalism in [0, 7]:
|
||||
error = 'LRF='+str(formalism)+' covariance not supported '\
|
||||
'for this formalism'
|
||||
raise NotImplementedError(error)
|
||||
|
||||
if unresolved_flag in (0, 1):
|
||||
# Resolved resonance region
|
||||
resonance = resonances.ranges[j]
|
||||
erange = _FORMALISMS[formalism].from_endf(ev, file_obj,
|
||||
items, resonance)
|
||||
ranges.append(erange)
|
||||
|
||||
elif unresolved_flag == 2:
|
||||
warn = 'Unresolved resonance not supported. Covariance '\
|
||||
'values for the unresolved region not imported.'
|
||||
warnings.warn(warn)
|
||||
|
||||
return cls(ranges)
|
||||
|
||||
|
||||
class ResonanceCovarianceRange:
|
||||
"""Resonace covariance range. Base class for different formalisms.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
|
||||
Attributes
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
parameters : pandas.DataFrame
|
||||
Resonance parameters
|
||||
covariance : numpy.array
|
||||
The covariance matrix contained within the ENDF evaluation
|
||||
lcomp : int
|
||||
Flag indicating format of the covariance matrix within the ENDF file
|
||||
file2res : openmc.data.ResonanceRange object
|
||||
Corresponding resonance range with File 2 data.
|
||||
mpar : int
|
||||
Number of parameters in covariance matrix for each individual resonance
|
||||
formalism : str
|
||||
String descriptor of formalism
|
||||
"""
|
||||
def __init__(self, energy_min, energy_max):
|
||||
self.energy_min = energy_min
|
||||
self.energy_max = energy_max
|
||||
|
||||
def subset(self, parameter_str, bounds):
|
||||
"""Produce a subset of resonance parameters and the corresponding
|
||||
covariance matrix to an IncidentNeutron object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
parameter_str : str
|
||||
parameter to be discriminated
|
||||
(i.e. 'energy', 'captureWidth', 'fissionWidthA'...)
|
||||
bounds : np.array
|
||||
[low numerical bound, high numerical bound]
|
||||
|
||||
Returns
|
||||
-------
|
||||
res_cov_range : openmc.data.ResonanceCovarianceRange
|
||||
ResonanceCovarianceRange object that contains a subset of the
|
||||
covariance matrix (upper triangular) as well as a subset parameters
|
||||
within self.file2params
|
||||
|
||||
"""
|
||||
# Copy range and prevent change of original
|
||||
res_cov_range = copy.deepcopy(self)
|
||||
|
||||
parameters = self.file2res.parameters
|
||||
cov = res_cov_range.covariance
|
||||
mpar = res_cov_range.mpar
|
||||
# Create mask
|
||||
mask1 = parameters[parameter_str] >= bounds[0]
|
||||
mask2 = parameters[parameter_str] <= bounds[1]
|
||||
mask = mask1 & mask2
|
||||
res_cov_range.parameters = parameters[mask]
|
||||
indices = res_cov_range.parameters.index.values
|
||||
# Build subset of covariance
|
||||
sub_cov_dim = len(indices)*mpar
|
||||
cov_subset_vals = []
|
||||
for index1 in indices:
|
||||
for i in range(mpar):
|
||||
for index2 in indices:
|
||||
for j in range(mpar):
|
||||
if index2*mpar+j >= index1*mpar+i:
|
||||
cov_subset_vals.append(cov[index1*mpar+i,
|
||||
index2*mpar+j])
|
||||
|
||||
cov_subset = np.zeros([sub_cov_dim, sub_cov_dim])
|
||||
tri_indices = np.triu_indices(sub_cov_dim)
|
||||
cov_subset[tri_indices] = cov_subset_vals
|
||||
|
||||
res_cov_range.file2res.parameters = parameters[mask]
|
||||
res_cov_range.covariance = cov_subset
|
||||
return res_cov_range
|
||||
|
||||
def sample(self, n_samples):
|
||||
"""Sample resonance parameters based on the covariances provided
|
||||
within an ENDF evaluation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
n_samples : int
|
||||
The number of samples to produce
|
||||
|
||||
Returns
|
||||
-------
|
||||
samples : list of openmc.data.ResonanceCovarianceRange objects
|
||||
List of samples size `n_samples`
|
||||
|
||||
"""
|
||||
warn_str = 'Sampling routine does not guarantee positive values for '\
|
||||
'parameters. This can lead to undefined behavior in the '\
|
||||
'reconstruction routine.'
|
||||
warnings.warn(warn_str)
|
||||
parameters = self.parameters
|
||||
cov = self.covariance
|
||||
|
||||
# Symmetrizing covariance matrix
|
||||
cov = cov + cov.T - np.diag(cov.diagonal())
|
||||
formalism = self.formalism
|
||||
mpar = self.mpar
|
||||
samples = []
|
||||
|
||||
# Handling MLBW/SLBW sampling
|
||||
if formalism == 'mlbw' or formalism == 'slbw':
|
||||
params = ['energy', 'neutronWidth', 'captureWidth', 'fissionWidth',
|
||||
'competitiveWidth']
|
||||
param_list = params[:mpar]
|
||||
mean_array = parameters[param_list].values
|
||||
mean = mean_array.flatten()
|
||||
par_samples = np.random.multivariate_normal(mean, cov,
|
||||
size=n_samples)
|
||||
spin = parameters['J'].values
|
||||
l_value = parameters['L'].values
|
||||
for sample in par_samples:
|
||||
energy = sample[0::mpar]
|
||||
gn = sample[1::mpar]
|
||||
gg = sample[2::mpar]
|
||||
gf = sample[3::mpar] if mpar > 3 else parameters['fissionWidth'].values
|
||||
gx = sample[4::mpar] if mpar > 4 else parameters['competitiveWidth'].values
|
||||
gt = gn + gg + gf + gx
|
||||
|
||||
records = []
|
||||
for j, E in enumerate(energy):
|
||||
records.append([energy[j], l_value[j], spin[j], gt[j],
|
||||
gn[j], gg[j], gf[j], gx[j]])
|
||||
columns = ['energy', 'L', 'J', 'totalWidth', 'neutronWidth',
|
||||
'captureWidth', 'fissionWidth', 'competitiveWidth']
|
||||
sample_params = pd.DataFrame.from_records(records,
|
||||
columns=columns)
|
||||
# Copy ResonanceRange object
|
||||
res_range = copy.copy(self.file2res)
|
||||
res_range.parameters = sample_params
|
||||
samples.append(res_range)
|
||||
|
||||
# Handling RM sampling
|
||||
elif formalism == 'rm':
|
||||
params = ['energy', 'neutronWidth', 'captureWidth',
|
||||
'fissionWidthA', 'fissionWidthB']
|
||||
param_list = params[:mpar]
|
||||
mean_array = parameters[param_list].values
|
||||
mean = mean_array.flatten()
|
||||
par_samples = np.random.multivariate_normal(mean, cov,
|
||||
size=n_samples)
|
||||
spin = parameters['J'].values
|
||||
l_value = parameters['L'].values
|
||||
for sample in par_samples:
|
||||
energy = sample[0::mpar]
|
||||
gn = sample[1::mpar]
|
||||
gg = sample[2::mpar]
|
||||
gfa = sample[3::mpar] if mpar > 3 else parameters['fissionWidthA'].values
|
||||
gfb = sample[4::mpar] if mpar > 3 else parameters['fissionWidthB'].values
|
||||
|
||||
records = []
|
||||
for j, E in enumerate(energy):
|
||||
records.append([energy[j], l_value[j], spin[j], gn[j],
|
||||
gg[j], gfa[j], gfb[j]])
|
||||
columns = ['energy', 'L', 'J', 'neutronWidth',
|
||||
'captureWidth', 'fissionWidthA', 'fissionWidthB']
|
||||
sample_params = pd.DataFrame.from_records(records,
|
||||
columns=columns)
|
||||
# Copy ResonanceRange object
|
||||
res_range = copy.copy(self.file2res)
|
||||
res_range.parameters = sample_params
|
||||
samples.append(res_range)
|
||||
|
||||
return samples
|
||||
|
||||
|
||||
class MultiLevelBreitWignerCovariance(ResonanceCovarianceRange):
|
||||
"""Multi-level Breit-Wigner resolved resonance formalism covariance data.
|
||||
Parameters
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
|
||||
Attributes
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
parameters : pandas.DataFrame
|
||||
Resonance parameters
|
||||
covariance : numpy.array
|
||||
The covariance matrix contained within the ENDF evaluation
|
||||
mpar : int
|
||||
Number of parameters in covariance matrix for each individual resonance
|
||||
lcomp : int
|
||||
Flag indicating format of the covariance matrix within the ENDF file
|
||||
file2res : openmc.data.ResonanceRange object
|
||||
Corresponding resonance range with File 2 data.
|
||||
formalism : str
|
||||
String descriptor of formalism
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, energy_min, energy_max, parameters, covariance, mpar,
|
||||
lcomp, file2res):
|
||||
super().__init__(energy_min, energy_max)
|
||||
self.parameters = parameters
|
||||
self.covariance = covariance
|
||||
self.mpar = mpar
|
||||
self.lcomp = lcomp
|
||||
self.file2res = copy.copy(file2res)
|
||||
self.formalism = 'mlbw'
|
||||
|
||||
@classmethod
|
||||
def from_endf(cls, ev, file_obj, items, resonance):
|
||||
"""Create MLBW covariance data from an ENDF evaluation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ev : openmc.data.endf.Evaluation
|
||||
ENDF evaluation
|
||||
file_obj : file-like object
|
||||
ENDF file positioned at the second record of a resonance range
|
||||
subsection in MF=32, MT=151
|
||||
items : list
|
||||
Items from the CONT record at the start of the resonance range
|
||||
subsection
|
||||
resonance : openmc.data.ResonanceRange object
|
||||
Corresponding resonance range with File 2 data.
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.data.MultiLevelBreitWignerCovariance
|
||||
Multi-level Breit-Wigner resonance covariance parameters
|
||||
|
||||
"""
|
||||
|
||||
# Read energy-dependent scattering radius if present
|
||||
energy_min, energy_max = items[0:2]
|
||||
nro, naps = items[4:6]
|
||||
if nro != 0:
|
||||
params, ape = endf.get_tab1_record(file_obj)
|
||||
|
||||
# Other scatter radius parameters
|
||||
items = endf.get_cont_record(file_obj)
|
||||
target_spin = items[0]
|
||||
lcomp = items[3] # Flag for compatibility 0, 1, 2 - 2 is compact form
|
||||
nls = items[4] # number of l-values
|
||||
|
||||
# Build covariance matrix for General Resolved Resonance Formats
|
||||
if lcomp == 1:
|
||||
items = endf.get_cont_record(file_obj)
|
||||
# Number of short range type resonance covariances
|
||||
num_short_range = items[4]
|
||||
# Number of long range type resonance covariances
|
||||
num_long_range = items[5]
|
||||
|
||||
# Read resonance widths, J values, etc
|
||||
records = []
|
||||
for i in range(num_short_range):
|
||||
items, values = endf.get_list_record(file_obj)
|
||||
mpar = items[2]
|
||||
num_res = items[5]
|
||||
num_par_vals = num_res*6
|
||||
res_values = values[:num_par_vals]
|
||||
cov_values = values[num_par_vals:]
|
||||
|
||||
energy = res_values[0::6]
|
||||
spin = res_values[1::6]
|
||||
gt = res_values[2::6]
|
||||
gn = res_values[3::6]
|
||||
gg = res_values[4::6]
|
||||
gf = res_values[5::6]
|
||||
|
||||
for i, E in enumerate(energy):
|
||||
records.append([energy[i], spin[i], gt[i], gn[i],
|
||||
gg[i], gf[i]])
|
||||
|
||||
# Build the upper-triangular covariance matrix
|
||||
cov_dim = mpar*num_res
|
||||
cov = np.zeros([cov_dim, cov_dim])
|
||||
indices = np.triu_indices(cov_dim)
|
||||
cov[indices] = cov_values
|
||||
|
||||
# Compact format - Resonances and individual uncertainties followed by
|
||||
# compact correlations
|
||||
elif lcomp == 2:
|
||||
items, values = endf.get_list_record(file_obj)
|
||||
mean = items
|
||||
num_res = items[5]
|
||||
energy = values[0::12]
|
||||
spin = values[1::12]
|
||||
gt = values[2::12]
|
||||
gn = values[3::12]
|
||||
gg = values[4::12]
|
||||
gf = values[5::12]
|
||||
par_unc = []
|
||||
for i in range(num_res):
|
||||
res_unc = values[i*12+6 : i*12+12]
|
||||
# Delete 0 values (not provided, no fission width)
|
||||
# DAJ/DGT always zero, DGF sometimes nonzero [1, 2, 5]
|
||||
res_unc_nonzero = []
|
||||
for j in range(6):
|
||||
if j in [1, 2, 5] and res_unc[j] != 0.0:
|
||||
res_unc_nonzero.append(res_unc[j])
|
||||
elif j in [0, 3, 4]:
|
||||
res_unc_nonzero.append(res_unc[j])
|
||||
par_unc.extend(res_unc_nonzero)
|
||||
|
||||
records = []
|
||||
for i, E in enumerate(energy):
|
||||
records.append([energy[i], spin[i], gt[i], gn[i],
|
||||
gg[i], gf[i]])
|
||||
|
||||
corr = endf.get_intg_record(file_obj)
|
||||
cov = np.diag(par_unc).dot(corr).dot(np.diag(par_unc))
|
||||
|
||||
# Compatible resolved resonance format
|
||||
elif lcomp == 0:
|
||||
cov = np.zeros([4, 4])
|
||||
records = []
|
||||
cov_index = 0
|
||||
for i in range(nls):
|
||||
items, values = endf.get_list_record(file_obj)
|
||||
num_res = items[5]
|
||||
for j in range(num_res):
|
||||
one_res = values[18*j:18*(j+1)]
|
||||
res_values = one_res[:6]
|
||||
cov_values = one_res[6:]
|
||||
records.append(list(res_values))
|
||||
|
||||
# Populate the coviariance matrix for this resonance
|
||||
# There are no covariances between resonances in lcomp=0
|
||||
cov[cov_index, cov_index] = cov_values[0]
|
||||
cov[cov_index+1, cov_index+1 : cov_index+2] = cov_values[1:2]
|
||||
cov[cov_index+1, cov_index+3] = cov_values[4]
|
||||
cov[cov_index+2, cov_index+2] = cov_values[3]
|
||||
cov[cov_index+2, cov_index+3] = cov_values[5]
|
||||
cov[cov_index+3, cov_index+3] = cov_values[6]
|
||||
|
||||
cov_index += 4
|
||||
if j < num_res-1: # Pad matrix for additional values
|
||||
cov = np.pad(cov, ((0, 4), (0, 4)), 'constant',
|
||||
constant_values=0)
|
||||
|
||||
# Create pandas DataFrame with resonance data, currently
|
||||
# redundant with data.IncidentNeutron.resonance
|
||||
columns = ['energy', 'J', 'totalWidth', 'neutronWidth',
|
||||
'captureWidth', 'fissionWidth']
|
||||
parameters = pd.DataFrame.from_records(records, columns=columns)
|
||||
# Determine mpar (number of parameters for each resonance in
|
||||
# covariance matrix)
|
||||
nparams, params = parameters.shape
|
||||
covsize = cov.shape[0]
|
||||
mpar = int(covsize/nparams)
|
||||
# Add parameters from File 2
|
||||
parameters = _add_file2_contributions(parameters,
|
||||
resonance.parameters)
|
||||
# Create instance of class
|
||||
mlbw = cls(energy_min, energy_max, parameters, cov, mpar, lcomp,
|
||||
resonance)
|
||||
return mlbw
|
||||
|
||||
|
||||
class SingleLevelBreitWignerCovariance(MultiLevelBreitWignerCovariance):
|
||||
"""Single-level Breit-Wigner resolved resonance formalism covariance data.
|
||||
Single-level Breit-Wigner resolved resonance data is is identified by LRF=1
|
||||
in the ENDF-6 format.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
|
||||
Attributes
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
parameters : pandas.DataFrame
|
||||
Resonance parameters
|
||||
covariance : numpy.array
|
||||
The covariance matrix contained within the ENDF evaluation
|
||||
mpar : int
|
||||
Number of parameters in covariance matrix for each individual resonance
|
||||
formalism : str
|
||||
String descriptor of formalism
|
||||
lcomp : int
|
||||
Flag indicating format of the covariance matrix within the ENDF file
|
||||
file2res : openmc.data.ResonanceRange object
|
||||
Corresponding resonance range with File 2 data.
|
||||
"""
|
||||
|
||||
def __init__(self, energy_min, energy_max, parameters, covariance, mpar,
|
||||
lcomp, file2res):
|
||||
super().__init__(energy_min, energy_max, parameters, covariance, mpar,
|
||||
lcomp, file2res)
|
||||
self.formalism = 'slbw'
|
||||
|
||||
|
||||
class ReichMooreCovariance(ResonanceCovarianceRange):
|
||||
"""Reich-Moore resolved resonance formalism covariance data.
|
||||
|
||||
Reich-Moore resolved resonance data is identified by LRF=3 in the ENDF-6
|
||||
format.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
|
||||
Attributes
|
||||
----------
|
||||
energy_min : float
|
||||
Minimum energy of the resolved resonance range in eV
|
||||
energy_max : float
|
||||
Maximum energy of the resolved resonance range in eV
|
||||
parameters : pandas.DataFrame
|
||||
Resonance parameters
|
||||
covariance : numpy.array
|
||||
The covariance matrix contained within the ENDF evaluation
|
||||
lcomp : int
|
||||
Flag indicating format of the covariance matrix within the ENDF file
|
||||
mpar : int
|
||||
Number of parameters in covariance matrix for each individual resonance
|
||||
file2res : openmc.data.ResonanceRange object
|
||||
Corresponding resonance range with File 2 data.
|
||||
formalism : str
|
||||
String descriptor of formalism
|
||||
"""
|
||||
|
||||
def __init__(self, energy_min, energy_max, parameters, covariance, mpar,
|
||||
lcomp, file2res):
|
||||
super().__init__(energy_min, energy_max)
|
||||
self.parameters = parameters
|
||||
self.covariance = covariance
|
||||
self.mpar = mpar
|
||||
self.lcomp = lcomp
|
||||
self.file2res = copy.copy(file2res)
|
||||
self.formalism = 'rm'
|
||||
|
||||
@classmethod
|
||||
def from_endf(cls, ev, file_obj, items, resonance):
|
||||
"""Create Reich-Moore resonance covariance data from an ENDF
|
||||
evaluation. Includes the resonance parameters contained separately in
|
||||
File 32.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ev : openmc.data.endf.Evaluation
|
||||
ENDF evaluation
|
||||
file_obj : file-like object
|
||||
ENDF file positioned at the second record of a resonance range
|
||||
subsection in MF=2, MT=151
|
||||
items : list
|
||||
Items from the CONT record at the start of the resonance range
|
||||
subsection
|
||||
resonance : openmc.data.Resonance object
|
||||
openmc.data.Resonanance object generated from the same evaluation
|
||||
used to import values not contained in File 32
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.data.ReichMooreCovariance
|
||||
Reich-Moore resonance covariance parameters
|
||||
|
||||
"""
|
||||
# Read energy-dependent scattering radius if present
|
||||
energy_min, energy_max = items[0:2]
|
||||
nro, naps = items[4:6]
|
||||
if nro != 0:
|
||||
params, ape = endf.get_tab1_record(file_obj)
|
||||
|
||||
# Other scatter radius parameters
|
||||
items = endf.get_cont_record(file_obj)
|
||||
target_spin = items[0]
|
||||
lcomp = items[3] # Flag for compatibility 0, 1, 2 - 2 is compact form
|
||||
nls = items[4] # Number of l-values
|
||||
|
||||
# Build covariance matrix for General Resolved Resonance Formats
|
||||
if lcomp == 1:
|
||||
items = endf.get_cont_record(file_obj)
|
||||
# Number of short range type resonance covariances
|
||||
num_short_range = items[4]
|
||||
# Number of long range type resonance covariances
|
||||
num_long_range = items[5]
|
||||
# Read resonance widths, J values, etc
|
||||
channel_radius = {}
|
||||
scattering_radius = {}
|
||||
records = []
|
||||
for i in range(num_short_range):
|
||||
items, values = endf.get_list_record(file_obj)
|
||||
mpar = items[2]
|
||||
num_res = items[5]
|
||||
num_par_vals = num_res*6
|
||||
res_values = values[:num_par_vals]
|
||||
cov_values = values[num_par_vals:]
|
||||
|
||||
energy = res_values[0::6]
|
||||
spin = res_values[1::6]
|
||||
gn = res_values[2::6]
|
||||
gg = res_values[3::6]
|
||||
gfa = res_values[4::6]
|
||||
gfb = res_values[5::6]
|
||||
|
||||
for i, E in enumerate(energy):
|
||||
records.append([energy[i], spin[i], gn[i], gg[i],
|
||||
gfa[i], gfb[i]])
|
||||
|
||||
# Build the upper-triangular covariance matrix
|
||||
cov_dim = mpar*num_res
|
||||
cov = np.zeros([cov_dim, cov_dim])
|
||||
indices = np.triu_indices(cov_dim)
|
||||
cov[indices] = cov_values
|
||||
|
||||
# Compact format - Resonances and individual uncertainties followed by
|
||||
# compact correlations
|
||||
elif lcomp == 2:
|
||||
items, values = endf.get_list_record(file_obj)
|
||||
num_res = items[5]
|
||||
energy = values[0::12]
|
||||
spin = values[1::12]
|
||||
gn = values[2::12]
|
||||
gg = values[3::12]
|
||||
gfa = values[4::12]
|
||||
gfb = values[5::12]
|
||||
par_unc = []
|
||||
for i in range(num_res):
|
||||
res_unc = values[i*12+6 : i*12+12]
|
||||
# Delete 0 values (not provided in evaluation)
|
||||
res_unc = [x for x in res_unc if x != 0.0]
|
||||
par_unc.extend(res_unc)
|
||||
|
||||
records = []
|
||||
for i, E in enumerate(energy):
|
||||
records.append([energy[i], spin[i], gn[i], gg[i],
|
||||
gfa[i], gfb[i]])
|
||||
|
||||
corr = endf.get_intg_record(file_obj)
|
||||
cov = np.diag(par_unc).dot(corr).dot(np.diag(par_unc))
|
||||
|
||||
# Create pandas DataFrame with resonacne data
|
||||
columns = ['energy', 'J', 'neutronWidth', 'captureWidth',
|
||||
'fissionWidthA', 'fissionWidthB']
|
||||
parameters = pd.DataFrame.from_records(records, columns=columns)
|
||||
|
||||
# Determine mpar (number of parameters for each resonance in
|
||||
# covariance matrix)
|
||||
nparams, params = parameters.shape
|
||||
covsize = cov.shape[0]
|
||||
mpar = int(covsize/nparams)
|
||||
|
||||
# Add parameters from File 2
|
||||
parameters = _add_file2_contributions(parameters,
|
||||
resonance.parameters)
|
||||
# Create instance of ReichMooreCovariance
|
||||
rmc = cls(energy_min, energy_max, parameters, cov, mpar, lcomp,
|
||||
resonance)
|
||||
return rmc
|
||||
|
||||
|
||||
_FORMALISMS = {
|
||||
0: ResonanceCovarianceRange,
|
||||
1: SingleLevelBreitWignerCovariance,
|
||||
2: MultiLevelBreitWignerCovariance,
|
||||
3: ReichMooreCovariance
|
||||
# 7: RMatrixLimitedCovariance
|
||||
}
|
||||
|
|
@ -37,9 +37,10 @@ def sm150():
|
|||
|
||||
@pytest.fixture(scope='module')
|
||||
def gd154():
|
||||
"""Gd154 ENDF data (contains Reich Moore resonance range)"""
|
||||
"""Gd154 ENDF data (contains Reich Moore resonance range and reosnance
|
||||
covariance with LCOMP=1)."""
|
||||
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-064_Gd_154.endf')
|
||||
return openmc.data.IncidentNeutron.from_endf(filename)
|
||||
return openmc.data.IncidentNeutron.from_endf(filename, covariance=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
|
|
@ -77,6 +78,13 @@ def na22():
|
|||
return openmc.data.IncidentNeutron.from_endf(filename)
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def na23():
|
||||
"""Na23 ENDF data (contains MLBW resonance covariance with LCOMP=0)."""
|
||||
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-011_Na_023.endf')
|
||||
return openmc.data.IncidentNeutron.from_endf(filename, covariance=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def be9():
|
||||
"""Be9 ENDF data (contains laboratory angle-energy distribution)."""
|
||||
|
|
@ -97,6 +105,28 @@ def am244():
|
|||
return openmc.data.IncidentNeutron.from_njoy(endf_file)
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def ti50():
|
||||
"""Ti50 ENDF data (contains Multi-level Breit-Wigner resonance range and
|
||||
resonance covariance with LCOMP=1)."""
|
||||
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-022_Ti_050.endf')
|
||||
return openmc.data.IncidentNeutron.from_endf(filename, covariance=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def cf252():
|
||||
"""Cf252 ENDF data (contains RM resonance covariance with LCOMP=0)."""
|
||||
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-098_Cf_252.endf')
|
||||
return openmc.data.IncidentNeutron.from_endf(filename, covariance=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def th232():
|
||||
"""Th232 ENDF data (contains RM resonance covariance with LCOMP=2)."""
|
||||
filename = os.path.join(_ENDF_DATA, 'neutrons', 'n-090_Th_232.endf')
|
||||
return openmc.data.IncidentNeutron.from_endf(filename, covariance=True)
|
||||
|
||||
|
||||
def test_attributes(pu239):
|
||||
assert pu239.name == 'Pu239'
|
||||
assert pu239.mass_number == 239
|
||||
|
|
@ -277,6 +307,101 @@ def test_rml(cl35):
|
|||
assert isinstance(group, openmc.data.SpinGroup)
|
||||
|
||||
|
||||
def test_mlbw_cov_lcomp0(cf252):
|
||||
# Testing on first range only
|
||||
cov = cf252.resonance_covariance.ranges[0]
|
||||
res = cf252.resonances.ranges[0]
|
||||
assert cov.parameters['energy'][0] == pytest.approx(-3.5)
|
||||
assert res.parameters['energy'][0] == cov.parameters['energy'][0]
|
||||
assert isinstance(cov, openmc.data.resonance_covariance.MultiLevelBreitWignerCovariance)
|
||||
assert cov.energy_min == pytest.approx(1e-5)
|
||||
assert cov.energy_max == pytest.approx(1000.)
|
||||
assert cov.covariance[0,0] == pytest.approx(1.225e-05)
|
||||
|
||||
subset = cov.subset('energy', [0, 100])
|
||||
assert not subset.parameters.empty
|
||||
assert (subset.file2res.parameters['energy'] < 100).all()
|
||||
samples = cov.sample(1)
|
||||
xs = samples[0].reconstruct([10., 100., 1000.])
|
||||
assert sorted(xs.keys()) == [2, 18, 102]
|
||||
|
||||
|
||||
def test_mlbw_cov_lcomp1(ti50):
|
||||
# Testing on first range only
|
||||
cov = ti50.resonance_covariance.ranges[0]
|
||||
res = ti50.resonances.ranges[0]
|
||||
assert cov.parameters['energy'][0] == pytest.approx(-21020.)
|
||||
assert res.parameters['energy'][0] == cov.parameters['energy'][0]
|
||||
assert isinstance(cov, openmc.data.resonance_covariance.MultiLevelBreitWignerCovariance)
|
||||
assert cov.energy_min == pytest.approx(1e-5)
|
||||
assert cov.energy_max == pytest.approx(587000.)
|
||||
assert cov.covariance[0,0] == pytest.approx(1.410177e5)
|
||||
|
||||
subset = cov.subset('L', [1, 1])
|
||||
assert not subset.parameters.empty
|
||||
assert (subset.file2res.parameters['L'] == 1).all()
|
||||
samples = cov.sample(1)
|
||||
xs = samples[0].reconstruct([10., 100., 1000.])
|
||||
assert sorted(xs.keys()) == [2, 18, 102]
|
||||
|
||||
|
||||
def test_mlbw_cov_lcomp2(na23):
|
||||
# Testing on first range only
|
||||
cov = na23.resonance_covariance.ranges[0]
|
||||
res = na23.resonances.ranges[0]
|
||||
assert cov.parameters['energy'][0] == pytest.approx(2810.)
|
||||
assert res.parameters['energy'][0] == cov.parameters['energy'][0]
|
||||
assert isinstance(cov, openmc.data.resonance_covariance.MultiLevelBreitWignerCovariance)
|
||||
assert cov.energy_min == pytest.approx(600)
|
||||
assert cov.energy_max == pytest.approx(500000.)
|
||||
assert cov.covariance[0,0] == pytest.approx(16.1064163584)
|
||||
|
||||
subset = cov.subset('L', [1, 1])
|
||||
assert not subset.parameters.empty
|
||||
assert (subset.file2res.parameters['L'] == 1).all()
|
||||
samples = cov.sample(1)
|
||||
xs = samples[0].reconstruct([10., 100., 1000.])
|
||||
assert sorted(xs.keys()) == [2, 18, 102]
|
||||
|
||||
|
||||
def test_rmcov_lcomp1(gd154):
|
||||
# Testing on first range only
|
||||
cov = gd154.resonance_covariance.ranges[0]
|
||||
res = gd154.resonances.ranges[0]
|
||||
assert cov.parameters['energy'][0] == pytest.approx(-2.200001)
|
||||
assert res.parameters['energy'][0] == cov.parameters['energy'][0]
|
||||
assert isinstance(cov, openmc.data.resonance_covariance.ReichMooreCovariance)
|
||||
assert cov.energy_min == pytest.approx(1e-5)
|
||||
assert cov.energy_max == pytest.approx(2760.)
|
||||
assert cov.covariance[0,0] == pytest.approx(0.8895997)
|
||||
|
||||
subset = cov.subset('energy', [0, 100])
|
||||
assert not subset.parameters.empty
|
||||
assert (subset.file2res.parameters['energy'] < 100).all()
|
||||
samples = cov.sample(1)
|
||||
xs = samples[0].reconstruct([10., 100., 1000.])
|
||||
assert sorted(xs.keys()) == [2, 18, 102]
|
||||
|
||||
|
||||
def test_rmcov_lcomp2(th232):
|
||||
# Testing on first range only
|
||||
cov = th232.resonance_covariance.ranges[0]
|
||||
res = th232.resonances.ranges[0]
|
||||
assert cov.parameters['energy'][0] == pytest.approx(-2000)
|
||||
assert res.parameters['energy'][0] == cov.parameters['energy'][0]
|
||||
assert isinstance(cov, openmc.data.resonance_covariance.ReichMooreCovariance)
|
||||
assert cov.energy_min == pytest.approx(1e-5)
|
||||
assert cov.energy_max == pytest.approx(4000.)
|
||||
assert cov.covariance[0,0] == pytest.approx(246.6043092496)
|
||||
|
||||
subset = cov.subset('energy', [0, 100])
|
||||
assert not subset.parameters.empty
|
||||
assert (subset.file2res.parameters['energy'] < 100).all()
|
||||
samples = cov.sample(1)
|
||||
xs = samples[0].reconstruct([10., 100., 1000.])
|
||||
assert sorted(xs.keys()) == [2, 18, 102]
|
||||
|
||||
|
||||
def test_madland_nix(am241):
|
||||
fission = am241.reactions[18]
|
||||
prompt_neutron = fission.products[0]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue