Implemented MGXS merging

This commit is contained in:
wbinventor@gmail.com 2016-02-08 15:40:58 -05:00
parent 184ed3733b
commit ef60d9d2f5
4 changed files with 157 additions and 24 deletions

View file

@ -289,24 +289,6 @@ class Filter(object):
else:
return True
'''
# FIXME: Should all bins be completely separate???
# FIMXE: This is necessary if merging will choose out unique bins
else:
# None of the bins in this filter should match in the other filter
for bin in self.bins:
if bin in other.bins:
return False
# None of the bins in the other filter should match in this filter
for bin in other.bins:
if bin in self.bins:
return False
# If all conditional checks pass then filters are mergeable
return True
'''
def merge(self, other):
"""Merge this filter with another.

View file

@ -54,10 +54,12 @@ class EnergyGroups(object):
def __eq__(self, other):
if not isinstance(other, EnergyGroups):
return False
elif self.group_edges != other.group_edges:
elif self.num_groups != other.num_groups:
return False
else:
elif np.allclose(self.group_edges, other.group_edges):
return True
else:
return False
def __ne__(self, other):
return not self == other
@ -236,3 +238,64 @@ class EnergyGroups(object):
condensed_groups.group_edges = group_edges
return condensed_groups
def can_merge(self, other):
"""Determine if energy groups can be merged with another.
Parameters
----------
other : EnergyGroups
EnergyGroups to compare with
Returns
-------
bool
Whether the energy groups can be merged
"""
if not isinstance(other, EnergyGroups):
return False
# If the energy group structures match then groups are mergeable
if self == other:
return True
# This low energy edge coincides with other's high energy edge
if self.group_edges[0] == other.group_edges[-1]:
return True
# This high energy edge coincides with other's low energy edge
elif self.group_edges[-1] == other.group_edges[0]:
return True
else:
return False
def merge(self, other):
"""Merge this energy groups with another.
Parameters
----------
other : EnergyGroups
EnergyGroups to merge with
Returns
-------
merged_groups : EnergyGroups
EnergyGroups resulting from the merge
"""
if not self.can_merge(other):
raise ValueError('Unable to merge energy groups')
# Create deep copy to return as merged energy groups
merged_groups = copy.deepcopy(self)
# Merge unique filter bins
merged_edges = np.concatenate((self.group_edges, other.group_edges))
merged_edges = np.unique(merged_edges)
merged_edges = sorted(merged_edges)
# Assign merged edges to merged groups
merged_groups.group_edges = list(merged_edges)
return merged_groups

View file

@ -155,7 +155,7 @@ class MGXS(object):
clone._name = self.name
clone._rxn_type = self.rxn_type
clone._by_nuclide = self.by_nuclide
clone._nuclides = self._nuclides
clone._nuclides = copy.deepcopy(self._nuclides)
clone._domain = self.domain
clone._domain_type = self.domain_type
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
@ -953,9 +953,93 @@ class MGXS(object):
slice_xs.sparse = self.sparse
return slice_xs
# FIXME
def can_merge(self, other):
"""Determine if another MGXS can be merged with this one
If results have been loaded from a statepoint, then MGXS are only
mergeable along one and only one of enegy groups or nuclides.
Parameters
----------
other : MGXS
MGXS to check for merging
"""
if not isinstance(other, type(self)):
return False
# Compare reaction type, energy groups, nuclides, domain type
if self.rxn_type != other.rxn_type:
return False
elif not self.energy_groups.can_merge(other.energy_groups):
return False
elif self.by_nuclide != other.by_nuclide:
return False
elif self.domain_type != other.domain_type:
return False
elif 'distribcell' not in self.domain_type and self.domain != other.domain:
return False
elif len(self.tallies) != len(other.tallies):
return False
# See if each individual tally is mergeable
for tally_key in self.tallies:
if not self.tallies[tally_key].can_merge(other.tallies[tally_key]):
return False
# If all conditionals pass then MGXS are mergeable
return True
def merge(self, other):
raise NotImplementedError('not yet implemented')
"""Merge another MGXS with this one
If results have been loaded from a statepoint, then MGXS are only
mergeable along one and only one of energy groups or nuclides.
Parameters
----------
other : MGXS
MGXS to merge with this one
Returns
-------
merged_mgxs : MGXS
Merged MGXS
"""
if not self.can_merge(other):
raise ValueError('Unable to merge MGXS')
# Create deep copy of tally to return as merged tally
merged_mgxs = copy.deepcopy(self)
merged_mgxs._rxn_rate_tally = None
merged_mgxs._xs_tally = None
# Merge energy groups
if self.energy_groups != other.energy_groups:
merged_groups = self.energy_groups.merge(other.energy_groups)
merged_mgxs.energy_groups = merged_groups
# Merge nuclides
if self.nuclides != other.nuclides:
# The nuclides must be mutually exclusive
for nuclide in self.nuclides:
if nuclide in other.nuclides:
msg = 'Unable to merge MGXS with shared nuclides'
raise ValueError(msg)
# Concatenate lists of nuclides for the merged MGXS
merged_mgxs.nuclides = self.nuclides + other.nuclides
# Merge tallies
for tally_key in self.tallies:
merged_tally = self.tallies[tally_key].merge(other.tallies[tally_key])
merged_mgxs.tallies[tally_key] = merged_tally
return merged_mgxs
def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'):
"""Print a string representation for the multi-group cross section.

View file

@ -859,7 +859,7 @@ class Tally(object):
Parameters
----------
tally : Tally
other : Tally
Tally to merge with this one
Returns
@ -880,6 +880,10 @@ class Tally(object):
# Differentiate Tally with a new auto-generated Tally ID
merged_tally.id = None
# If the two tallies are equal, simpy return copy
if self == other:
return merged_tally
# Create deep copy of other tally to use for array concatenation
other_copy = copy.deepcopy(other)