From 8bd02e7890c1f889d2d0ea1b97a0d94bdfd6bbfb Mon Sep 17 00:00:00 2001 From: Isaac Meyer Date: Tue, 30 Jan 2018 14:01:52 -0500 Subject: [PATCH] Limited functionality for MLBW/SLBW covariances --- openmc/data/resonance_covariance.py | 182 +++++++++++++++++++++++++++- 1 file changed, 177 insertions(+), 5 deletions(-) diff --git a/openmc/data/resonance_covariance.py b/openmc/data/resonance_covariance.py index dc1a7f8cb..fdf4ba22e 100644 --- a/openmc/data/resonance_covariance.py +++ b/openmc/data/resonance_covariance.py @@ -80,9 +80,9 @@ class ResonanceCovariance(object): formalism = items[3] # resonance formalism # Throw error for unsupported formalisms - if formalism in [0,1,2,7]: + if formalism in [0,1,7]: raise TypeError('LRF= ', formalism, - ' covariance not supported for this formalism') + 'covariance not supported for this formalism') if resonance_flag in (0, 1): # resolved resonance region @@ -96,6 +96,174 @@ class ResonanceCovariance(object): return cls(ranges) +class MultiLevelBreitWignerCovariance(ResonanceRange): + """Multi-level Breit-Wigner resolved resonance formalism covariance data. + + Multi-level Breit-Wigner resolved resonance data is identified by LRF=2 in + the ENDF-6 format. + + Parameters + ---------- + target_spin : float + Intrinsic spin, :math:`I`, of the target nuclide + energy_min : float + Minimum energy of the resolved resonance range in eV + energy_max : float + Maximum energy of the resolved resonance range in eV + channel : dict + Dictionary whose keys are l-values and values are channel radii as a + function of energy + scattering : dict + Dictionary whose keys are l-values and values are scattering radii as a + function of energy + + Attributes + ---------- + cov_paramaters: list + The parameters that are included in the covariance matrix + covariance_matrix : array + The covariance matrix contained within the ENDF evaluation + + """ + + def __init__(self, energy_min, energy_max): + self.parameters = None + self.covariance = None + + @classmethod + def from_endf(cls, ev, file_obj, items): + """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=2, MT=151 + items : list + Items from the CONT record at the start of the resonance range + subsection + + 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 = get_tab1_record(file_obj) + + # Other scatter radius parameters + items = get_cont_record(file_obj) + target_spin = items[0] + ap = Polynomial((items[1],)) # energy-independent scattering-radius + 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 = get_cont_record(file_obj) + num_short_range = items[4] #Number of short range type resonance + #covariances + num_long_range = items[5] #Number of long range type resonance + #covariances + + # Read resonance widths, J values, etc + records = [] + for i in range(num_short_range): + items, values = get_list_record(file_obj) + num_parameters = 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 = num_parameters*num_res + cov = np.zeros([cov_dim,cov_dim]) + indices = np.triu_indices(cov_dim) + cov[indices] = cov_values + + #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) + + # Create instance of class + mlbw = cls(energy_min, energy_max) + mlbw.parameters = parameters + mlbw.covariance = cov + + return mlbw + + elif LCOMP in [0,2]: + raise TypeError('LCOMP = ' + str(LCOMP) + ' not supported') + +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 + ---------- + target_spin : float + Intrinsic spin, :math:`I`, of the target nuclide + energy_min : float + Minimum energy of the resolved resonance range in eV + energy_max : float + Maximum energy of the resolved resonance range in eV + channel : dict + Dictionary whose keys are l-values and values are channel radii as a + function of energy + scattering : dict + Dictionary whose keys are l-values and values are scattering radii as a + function of energy + + Attributes + ---------- + atomic_weight_ratio : float + Atomic weight ratio of the target nuclide given as a function of + l-value. Note that this may be different than the value for the + evaluation as a whole. + channel_radius : dict + Dictionary whose keys are l-values and values are channel radii as a + function of energy + energy_max : float + Maximum energy of the resolved resonance range in eV + energy_min : float + Minimum energy of the resolved resonance range in eV + parameters : pandas.DataFrame + Energies, spins, and resonances widths for each resonance + q_value : dict + Q-value to be added to incident particle's center-of-mass energy to + determine the channel energy for use in the penetrability factor. The + keys of the dictionary are l-values. + scattering_radius : dict + Dictionary whose keys are l-values and values are scattering radii as a + function of energy + target_spin : float + Intrinsic spin, :math:`I`, of the target nuclide + + """ + class ReichMooreCovariance(ResonanceRange): """Reich-Moore resolved resonance formalism covariance data. @@ -121,6 +289,8 @@ class ReichMooreCovariance(ResonanceRange): Attributes ---------- + num_parameters: list + Number of parameters used in each subsection cov_paramaters: list The parameters that are included in the covariance matrix covariance_matrix : array @@ -130,6 +300,7 @@ class ReichMooreCovariance(ResonanceRange): """ def __init__(self, energy_min, energy_max): + self.num_parameters = None self.parameters = None self.covariance = None @@ -172,7 +343,6 @@ class ReichMooreCovariance(ResonanceRange): # Build covariance matrix for General Resolved Resonance Formats if LCOMP == 1: items = get_cont_record(file_obj) - awri = items[0] num_short_range = items[4] #Number of short range type resonance #covariances num_long_range = items[5] #Number of long range type resonance @@ -219,7 +389,7 @@ class ReichMooreCovariance(ResonanceRange): return rmc elif LCOMP in [0,2]: - TypeError('LCOMP = ',LCOMP,' not supported') + raise TypeError('LCOMP = ' + str(LCOMP) + ' not supported') # _FORMALISMS = {0: ResonanceRange, @@ -227,6 +397,8 @@ class ReichMooreCovariance(ResonanceRange): # 2: MultiLevelBreitWigner, # 3: ReichMoore, # 7: RMatrixLimited} -_FORMALISMS = {3: ReichMooreCovariance} +_FORMALISMS = {1: SingleLevelBreitWignerCovariance, + 2: MultiLevelBreitWignerCovariance, + 3: ReichMooreCovariance}