From 0c3e586dd227948606c24c1576832f772478eacf Mon Sep 17 00:00:00 2001 From: Will Boyd Date: Wed, 8 Mar 2017 14:23:49 -0500 Subject: [PATCH] Tally merging now consolidates moment scores --- openmc/mgxs/library.py | 45 ++++++++++++++++------ openmc/mgxs/mgxs.py | 14 ++++++- openmc/tallies.py | 84 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 126 insertions(+), 17 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 0a9a94828a..7ebe6cb8cf 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -1089,8 +1089,8 @@ class Library(object): using_multiplicity = True # multiplicity will fall back to using scatter and nu-scatter - elif ((('scatter matrix' in self.mgxs_types) and - ('nu-scatter matrix' in self.mgxs_types))): + elif 'scatter matrix' in self.mgxs_types and \ + 'nu-scatter matrix' in self.mgxs_types: scatt_mgxs = self.get_mgxs(domain, 'scatter matrix') nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') xsdata.set_multiplicity_matrix_mgxs(nuscatt_mgxs, scatt_mgxs, @@ -1099,17 +1099,38 @@ class Library(object): subdomain=subdomain) using_multiplicity = True + # multiplicity will fall back to using scatter and nu-scatter + elif 'consistent scatter matrix' in self.mgxs_types and \ + 'consistent nu-scatter matrix' in self.mgxs_types: + scatt_mgxs = self.get_mgxs(domain, 'consistent scatter matrix') + nuscatt_mgxs = \ + self.get_mgxs(domain, 'consistent nu-scatter matrix') + xsdata.set_multiplicity_matrix_mgxs(nuscatt_mgxs, scatt_mgxs, + xs_type=xs_type, + nuclide=[nuclide], + subdomain=subdomain) + using_multiplicity = True + else: using_multiplicity = False if using_multiplicity: - nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') + if 'nu-scatter matrix' in self.mgxs_types: + nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') + else: + nuscatt_mgxs = \ + self.get_mgxs(domain, 'consistent nu-scatter matrix') xsdata.set_scatter_matrix_mgxs(nuscatt_mgxs, xs_type=xs_type, nuclide=[nuclide], subdomain=subdomain) else: - if 'nu-scatter matrix' in self.mgxs_types: - nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') + if 'nu-scatter matrix' in self.mgxs_types or \ + 'consistent nu-scatter matrix' in self.mgxs_types: + if 'nu-scatter matrix' in self.mgxs_types: + nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix') + else: + nuscatt_mgxs = \ + self.get_mgxs(domain, 'consistent nu-scatter matrix') xsdata.set_scatter_matrix_mgxs(nuscatt_mgxs, xs_type=xs_type, nuclide=[nuclide], subdomain=subdomain) @@ -1409,13 +1430,15 @@ class Library(object): error_flag = True warn('An "absorption" MGXS type is required but not provided.') # Ensure nu-scattering matrix is required - if 'nu-scatter matrix' not in self.mgxs_types: + if 'nu-scatter matrix' not in self.mgxs_types and \ + 'consistent nu-scatter matrix' not in self.mgxs_types: error_flag = True warn('A "nu-scatter matrix" MGXS type is required but not provided.') else: # Ok, now see the status of scatter and/or multiplicity - if ((('scatter matrix' not in self.mgxs_types) and - ('multiplicity matrix' not in self.mgxs_types))): + if 'scatter matrix' not in self.mgxs_types or \ + 'consistent scatter matrix' not in self.mgxs_types and \ + 'multiplicity matrix' not in self.mgxs_types: # We dont have data needed for multiplicity matrix, therefore # we need total, and not transport. if 'total' not in self.mgxs_types: @@ -1424,14 +1447,12 @@ class Library(object): 'scattering matrix is not provided.') # Total or transport can be present, but if using # self.correction=="P0", then we should use transport. - if (((self.correction == "P0") and - ('nu-transport' not in self.mgxs_types))): + if self.correction == "P0" and 'nu-transport' not in self.mgxs_types: error_flag = True warn('A "nu-transport" MGXS type is required since a "P0" ' 'correction is applied, but a "nu-transport" MGXS is ' 'not provided.') - elif (((self.correction is None) and - ('total' not in self.mgxs_types))): + elif self.correction is None and 'total' not in self.mgxs_types: error_flag = True warn('A "total" MGXS type is required, but not provided.') diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 84a2e3faff..46f65b1131 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -2747,8 +2747,18 @@ class TransportXS(MGXS): @property def rxn_rate_tally(self): - raise NotImplementedError('The reaction rate tally is poorly defined' \ - ' for the transport cross section') + if self._rxn_rate_tally is None: + # Switch EnergyoutFilter to EnergyFilter. + old_filt = self.tallies['scatter-1'].filters[-1] + new_filt = openmc.EnergyFilter(old_filt.bins) + new_filt.stride = old_filt.stride + self.tallies['scatter-1'].filters[-1] = new_filt + + self._rxn_rate_tally = \ + self.tallies['total'] - self.tallies['scatter-1'] + self._rxn_rate_tally.sparse = self.sparse + + return self._rxn_rate_tally @property def xs_tally(self): diff --git a/openmc/tallies.py b/openmc/tallies.py index a71d1c1c57..d79e979d81 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -2,12 +2,10 @@ from __future__ import division from collections import Iterable, MutableSequence import copy +import re from functools import partial -import os -import pickle import itertools from numbers import Integral, Real -import sys import warnings from xml.etree import ElementTree as ET @@ -1013,8 +1011,88 @@ class Tally(object): # Sparsify merged tally if both tallies are sparse merged_tally.sparse = self.sparse and other.sparse + # Consolidate scatter and flux Legendre moment scores + merged_tally._consolidate_moment_scores() + return merged_tally + def _consolidate_moment_scores(self): + """Remove redundant scattering moment scores from a merged Tally.""" + + # FIXME: This should also work for flux moments + + # Use regex to find (nu-)scatter-(P)n scores + scatt_n = [x for x in self.scores if + re.search(r'^((?!nu-)scatter-\d)', x)] + scatt_pn = [x for x in self.scores if + re.search(r'^((?!nu-)scatter-(P|p)\d)', x)] + nuscatt_n = [x for x in self.scores if + re.search(r'nu-scatter-\d', x)] + nuscatt_pn = [x for x in self.scores if + re.search(r'nu-scatter-(P|p)\d', x)] + + flux_n = [x for x in self.scores if + re.search(r'flux-\d', x)] + flux_pn = [x for x in self.scores if + re.search(r'flux-(P|p)\d', x)] + + # Find all other non-scattering moment scores + # FIXME: this should also find non-flux moment scores + scores = [x for x in self.scores if + re.search(r'^((?!scatter-).)*$', x)] + + # Consolidate scatter moment scores + if len(scatt_pn) > 0: + + # Only keep the highest scatter-PN score + high_pn = sorted([x.lower() for x in scatt_pn])[-1] + pn = int(high_pn.split('-')[1].replace('p', '')) + + # Only keep the scatter-N scores with N > PN + scatt_n = sorted([x.lower() for x in scatt_n]) + scatt_n = [x for x in scatt_n if (int(x.split('-')[1]) > pn)] + + # Append highest scatter-PN and any higher scatter-N scores + scores.extend([high_pn] + scatt_n) + else: + scores.extend(scatt_n) + + # Consolidate nu-scatter moment scores + if len(nuscatt_pn) > 0: + + # Only keep the highest nu-scatter-PN score + high_nupn = sorted([x.lower() for x in nuscatt_pn])[-1] + pn = int(high_nupn.split('-')[1].replace('p', '')) + + # Only keep the nu-scatter-N scores with N > PN + nuscatt_n = sorted([x.lower() for x in nuscatt_n]) + nuscatt_n = [x for x in nuscatt_n if (int(x.split('-')[1]) > pn)] + + # Append highest nu-scatter-PN and any higher nu-scatter-N scores + scores.extend([high_pn] + nuscatt_n) + else: + scores.extend(nuscatt_n) + + # Consolidate flux moment scores + if len(flux_pn) > 0: + + # Only keep the highest flux-PN score + high_pn = sorted([x.lower() for x in flux_pn])[-1] + pn = int(high_pn.split('-')[1].replace('p', '')) + + # Only keep the flux-N scores with N > PN + flux_n = sorted([x.lower() for x in flux_n]) + flux_n = [x for x in flux_n if (int(x.split('-')[1]) > pn)] + + # Append highest flux_n-PN and any higher flux_n-N scores + scores.extend([high_pn] + flux_n) + else: + scores.extend(flux_n) + + # Override Tally's scores with consolidated list of scores + self.scores = scores + + def to_xml_element(self): """Return XML representation of the tally