mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-25 20:45:35 -04:00
added prompt-nu-fission tally and reduced size of new MGXS types
This commit is contained in:
parent
d3550389c9
commit
16dc3db6fa
10 changed files with 181 additions and 289 deletions
|
|
@ -383,6 +383,9 @@
|
|||
"* `ScatterMatrixXS`\n",
|
||||
"* `NuScatterMatrixXS`\n",
|
||||
"* `Chi`\n",
|
||||
"* `ChiPrompt`\n",
|
||||
"* `Velocity`\n",
|
||||
"* `PromptNuFissionXS`\n",
|
||||
"\n",
|
||||
"These classes provide us with an interface to generate the tally inputs as well as perform post-processing of OpenMC's tally data to compute the respective multi-group cross sections. In this case, let's create the multi-group total, absorption and scattering cross sections with our 2-group structure."
|
||||
]
|
||||
|
|
@ -1181,7 +1184,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.6"
|
||||
"version": "2.7.11"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
|
|
@ -549,6 +549,9 @@
|
|||
"* `ScatterMatrixXS` (`\"scatter matrix\"`)\n",
|
||||
"* `NuScatterMatrixXS` (`\"nu-scatter matrix\"`)\n",
|
||||
"* `Chi` (`\"chi\"`)\n",
|
||||
"* `ChiPrompt` (`\"chi prompt\"`)\n",
|
||||
"* `Velocity` (`\"velocity\"`)\n",
|
||||
"* `PromptNuFissionXS` (`\"prompt-nu-fission\"`)\n",
|
||||
"\n",
|
||||
"In this case, let's create the multi-group cross sections needed to run an OpenMOC simulation to verify the accuracy of our cross sections. In particular, we will define `\"transport\"`, `\"nu-fission\"`, `'\"fission\"`, `\"nu-scatter matrix\"` and `\"chi\"` cross sections for our `Library`.\n",
|
||||
"\n",
|
||||
|
|
@ -1596,21 +1599,21 @@
|
|||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.5.1"
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.11"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
|
|
@ -1764,6 +1764,10 @@ The ``<tally>`` element accepts the following sub-elements:
|
|||
| |fission. This score type is not used in the |
|
||||
| |multi-group :ref:`energy_mode`. |
|
||||
+----------------------+---------------------------------------------------+
|
||||
|prompt-nu-fission |Total production of prompt neutrons due to |
|
||||
| |fission. This score type is not used in the |
|
||||
| |multi-group :ref:`energy_mode`. |
|
||||
+----------------------+---------------------------------------------------+
|
||||
|nu-fission |Total production of neutrons due to fission. |
|
||||
+----------------------+---------------------------------------------------+
|
||||
|nu-scatter, |These scores are similar in functionality to their |
|
||||
|
|
|
|||
|
|
@ -430,11 +430,7 @@ class MGXS(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
mgxs_type : {'total', 'transport', 'nu-transport', 'absorption',
|
||||
'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter',
|
||||
'nu-scatter', 'scatter matrix', 'nu-scatter matrix',
|
||||
'multiplicity matrix', 'nu-fission matrix', 'chi', 'chi-prompt',
|
||||
'velocity', 'prompt-nu-fission'}
|
||||
mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', 'chi', 'chi-prompt', 'velocity', 'prompt-nu-fission'}
|
||||
The type of multi-group cross section object to return
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe
|
||||
The domain for spatial homogenization
|
||||
|
|
@ -1948,7 +1944,7 @@ class MatrixMGXS(MGXS):
|
|||
|
||||
|
||||
class TotalXS(MGXS):
|
||||
"""A total multi-group cross section.
|
||||
r"""A total multi-group cross section.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -2057,7 +2053,7 @@ class TotalXS(MGXS):
|
|||
|
||||
|
||||
class TransportXS(MGXS):
|
||||
"""A transport-corrected total multi-group cross section.
|
||||
r"""A transport-corrected total multi-group cross section.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -2200,7 +2196,7 @@ class TransportXS(MGXS):
|
|||
|
||||
|
||||
class NuTransportXS(TransportXS):
|
||||
"""A transport-corrected total multi-group cross section which
|
||||
r"""A transport-corrected total multi-group cross section which
|
||||
accounts for neutron multiplicity in scattering reactions.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
|
|
@ -2313,7 +2309,7 @@ class NuTransportXS(TransportXS):
|
|||
|
||||
|
||||
class AbsorptionXS(MGXS):
|
||||
"""An absorption multi-group cross section.
|
||||
r"""An absorption multi-group cross section.
|
||||
|
||||
Absorption is defined as all reactions that do not produce secondary
|
||||
neutrons (disappearance) plus fission reactions.
|
||||
|
|
@ -2426,7 +2422,7 @@ class AbsorptionXS(MGXS):
|
|||
|
||||
|
||||
class CaptureXS(MGXS):
|
||||
"""A capture multi-group cross section.
|
||||
r"""A capture multi-group cross section.
|
||||
|
||||
The neutron capture reaction rate is defined as the difference between
|
||||
OpenMC's 'absorption' and 'fission' reaction rate score types. This includes
|
||||
|
|
@ -2554,7 +2550,7 @@ class CaptureXS(MGXS):
|
|||
|
||||
|
||||
class FissionXS(MGXS):
|
||||
"""A fission multi-group cross section.
|
||||
r"""A fission multi-group cross section.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -2664,7 +2660,7 @@ class FissionXS(MGXS):
|
|||
|
||||
|
||||
class NuFissionXS(MGXS):
|
||||
"""A fission neutron production multi-group cross section.
|
||||
r"""A fission neutron production multi-group cross section.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -2775,7 +2771,7 @@ class NuFissionXS(MGXS):
|
|||
|
||||
|
||||
class KappaFissionXS(MGXS):
|
||||
"""A recoverable fission energy production rate multi-group cross section.
|
||||
r"""A recoverable fission energy production rate multi-group cross section.
|
||||
|
||||
The recoverable energy per fission, :math:`\kappa`, is defined as the
|
||||
fission product kinetic energy, prompt and delayed neutron kinetic energies,
|
||||
|
|
@ -2891,7 +2887,7 @@ class KappaFissionXS(MGXS):
|
|||
|
||||
|
||||
class ScatterXS(MGXS):
|
||||
"""A scattering multi-group cross section.
|
||||
r"""A scattering multi-group cross section.
|
||||
|
||||
The scattering cross section is defined as the difference between the total
|
||||
and absorption cross sections.
|
||||
|
|
@ -3004,7 +3000,7 @@ class ScatterXS(MGXS):
|
|||
|
||||
|
||||
class NuScatterXS(MGXS):
|
||||
"""A scattering neutron production multi-group cross section.
|
||||
r"""A scattering neutron production multi-group cross section.
|
||||
|
||||
The neutron production from scattering is defined as the average number of
|
||||
neutrons produced from all neutron-producing reactions except for fission.
|
||||
|
|
@ -3123,7 +3119,7 @@ class NuScatterXS(MGXS):
|
|||
|
||||
|
||||
class ScatterMatrixXS(MatrixMGXS):
|
||||
"""A scattering matrix multi-group cross section for one or more Legendre
|
||||
r"""A scattering matrix multi-group cross section for one or more Legendre
|
||||
moments.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
|
|
@ -3793,7 +3789,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
|
||||
|
||||
class NuScatterMatrixXS(ScatterMatrixXS):
|
||||
"""A scattering production matrix multi-group cross section for one or
|
||||
r"""A scattering production matrix multi-group cross section for one or
|
||||
more Legendre moments.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
|
|
@ -3903,7 +3899,7 @@ class NuScatterMatrixXS(ScatterMatrixXS):
|
|||
|
||||
|
||||
class MultiplicityMatrixXS(MatrixMGXS):
|
||||
"""The scattering multiplicity matrix.
|
||||
r"""The scattering multiplicity matrix.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -4057,7 +4053,7 @@ class MultiplicityMatrixXS(MatrixMGXS):
|
|||
|
||||
|
||||
class NuFissionMatrixXS(MatrixMGXS):
|
||||
"""A fission production matrix multi-group cross section.
|
||||
r"""A fission production matrix multi-group cross section.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -4172,7 +4168,7 @@ class NuFissionMatrixXS(MatrixMGXS):
|
|||
|
||||
|
||||
class Chi(MGXS):
|
||||
"""The fission spectrum.
|
||||
r"""The fission spectrum.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -4631,7 +4627,7 @@ class Chi(MGXS):
|
|||
|
||||
|
||||
class ChiPrompt(Chi):
|
||||
"""The prompt fission spectrum.
|
||||
r"""The prompt fission spectrum.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -4744,112 +4740,7 @@ class ChiPrompt(Chi):
|
|||
|
||||
@property
|
||||
def scores(self):
|
||||
return ['delayed-nu-fission', 'delayed-nu-fission',
|
||||
'nu-fission', 'nu-fission']
|
||||
|
||||
@property
|
||||
def filters(self):
|
||||
# Create the non-domain specific Filters for the Tallies
|
||||
group_edges = self.energy_groups.group_edges
|
||||
energyout = openmc.Filter('energyout', group_edges)
|
||||
energyin = openmc.Filter('energy', [group_edges[0], group_edges[-1]])
|
||||
return [[energyin], [energyout], [energyin], [energyout]]
|
||||
|
||||
@property
|
||||
def tally_keys(self):
|
||||
return ['delayed-nu-fission-in', 'delayed-nu-fission-out',
|
||||
'nu-fission-in', 'nu-fission-out']
|
||||
|
||||
@property
|
||||
def rxn_rate_tally(self):
|
||||
if self._rxn_rate_tally is None:
|
||||
self._rxn_rate_tally = self.tallies['nu-fission-out'] - \
|
||||
self.tallies['delayed-nu-fission-out']
|
||||
self._rxn_rate_tally.sparse = self.sparse
|
||||
return self._rxn_rate_tally
|
||||
|
||||
@property
|
||||
def xs_tally(self):
|
||||
|
||||
if self._xs_tally is None:
|
||||
delayed_nu_fission_in = self.tallies['delayed-nu-fission-in']
|
||||
nu_fission_in = self.tallies['nu-fission-in']
|
||||
prompt_nu_fission_in = nu_fission_in - delayed_nu_fission_in
|
||||
|
||||
# Remove coarse energy filter to keep it out of tally arithmetic
|
||||
energy_filter = prompt_nu_fission_in.find_filter('energy')
|
||||
prompt_nu_fission_in.remove_filter(energy_filter)
|
||||
|
||||
# Compute chi
|
||||
self._xs_tally = self.rxn_rate_tally / prompt_nu_fission_in
|
||||
super(ChiPrompt, self)._compute_xs()
|
||||
|
||||
# Add the coarse energy filter back to the nu-fission tally
|
||||
prompt_nu_fission_in.filters.append(energy_filter)
|
||||
|
||||
return self._xs_tally
|
||||
|
||||
def get_slice(self, nuclides=[], groups=[]):
|
||||
"""Build a sliced ChiPrompt for the specified nuclides and energy
|
||||
groups.
|
||||
|
||||
This method constructs a new MGXS to encapsulate a subset of the data
|
||||
represented by this MGXS. The subset of data to include in the tally
|
||||
slice is determined by the nuclides and energy groups specified in
|
||||
the input parameters.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
nuclides : list of str
|
||||
A list of nuclide name strings
|
||||
(e.g., ['U-235', 'U-238']; default is [])
|
||||
groups : list of Integral
|
||||
A list of energy group indices starting at 1 for the high energies
|
||||
(e.g., [1, 2, 3]; default is [])
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.mgxs.MGXS
|
||||
A new MGXS which encapsulates the subset of data requested
|
||||
for the nuclide(s) and/or energy group(s) requested in the
|
||||
parameters.
|
||||
|
||||
"""
|
||||
|
||||
# Temporarily remove energy filter from delayed-nu-fission-in since its
|
||||
# group structure will work in super MGXS.get_slice(...) method
|
||||
delayed_nu_fission_in = self.tallies['delayed-nu-fission-in']
|
||||
nu_fission_in = self.tallies['nu-fission-in']
|
||||
prompt_nu_fission_in = nu_fission_in - delayed_nu_fission_in
|
||||
energy_filter = prompt_nu_fission_in.find_filter('energy')
|
||||
prompt_nu_fission_in.remove_filter(energy_filter)
|
||||
|
||||
# Call super class method and null out derived tallies
|
||||
slice_xs = super(ChiPrompt, self).get_slice(nuclides, groups)
|
||||
slice_xs._rxn_rate_tally = None
|
||||
slice_xs._xs_tally = None
|
||||
|
||||
# Slice energy groups if needed
|
||||
if len(groups) != 0:
|
||||
filter_bins = []
|
||||
for group in groups:
|
||||
group_bounds = self.energy_groups.get_group_bounds(group)
|
||||
filter_bins.append(group_bounds)
|
||||
filter_bins = [tuple(filter_bins)]
|
||||
|
||||
# Slice nu-fission-out tally along energyout filter
|
||||
prompt_nu_fission_out = slice_xs.tallies['nu-fission-out'] - \
|
||||
slice_xs.tallies['delayed-nu-fission-out']
|
||||
tally_slice = prompt_nu_fission_out\
|
||||
.get_slice(filters=['energyout'],
|
||||
filter_bins=filter_bins)
|
||||
slice_xs._tallies['prompt-nu-fission-out'] = tally_slice
|
||||
|
||||
# Add energy filter back to nu-fission-in tallies
|
||||
slice_xs._tallies['prompt-nu-fission-in'].add_filter(energy_filter)
|
||||
|
||||
slice_xs.sparse = self.sparse
|
||||
return slice_xs
|
||||
return ['prompt-nu-fission', 'prompt-nu-fission']
|
||||
|
||||
def merge(self, other):
|
||||
"""Merge another ChiPrompt with this one
|
||||
|
|
@ -4873,148 +4764,9 @@ class ChiPrompt(Chi):
|
|||
|
||||
return super(ChiPrompt, self).merge(other)
|
||||
|
||||
def get_xs(self, groups='all', subdomains='all', nuclides='all',
|
||||
xs_type='macro', order_groups='increasing',
|
||||
value='mean', **kwargs):
|
||||
"""Returns an array of the fission spectrum.
|
||||
|
||||
This method constructs a 2D NumPy array for the requested multi-group
|
||||
cross section data data for one or more energy groups and subdomains.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
groups : Iterable of Integral or 'all'
|
||||
Energy groups of interest. Defaults to 'all'.
|
||||
subdomains : Iterable of Integral or 'all'
|
||||
Subdomain IDs of interest. Defaults to 'all'.
|
||||
nuclides : Iterable of str or 'all' or 'sum'
|
||||
A list of nuclide name strings (e.g., ['U-235', 'U-238']). The
|
||||
special string 'all' will return the cross sections for all nuclides
|
||||
in the spatial domain. The special string 'sum' will return the
|
||||
cross section summed over all nuclides. Defaults to 'all'.
|
||||
xs_type: {'macro', 'micro'}
|
||||
This parameter is not relevant for chi but is included here to
|
||||
mirror the parent MGXS.get_xs(...) class method
|
||||
order_groups: {'increasing', 'decreasing'}
|
||||
Return the cross section indexed according to increasing or
|
||||
decreasing energy groups (decreasing or increasing energies).
|
||||
Defaults to 'increasing'.
|
||||
value : {'mean', 'std_dev', 'rel_err'}
|
||||
A string for the type of value to return. Defaults to 'mean'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
numpy.ndarray
|
||||
A NumPy array of the multi-group cross section indexed in the order
|
||||
each group, subdomain and nuclide is listed in the parameters.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the multi-group cross section is
|
||||
computed from tally data.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_value('value', value, ['mean', 'std_dev', 'rel_err'])
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
|
||||
filters = []
|
||||
filter_bins = []
|
||||
|
||||
# Construct a collection of the domain filter bins
|
||||
if not isinstance(subdomains, basestring):
|
||||
cv.check_iterable_type('subdomains', subdomains, Integral, max_depth=2)
|
||||
for subdomain in subdomains:
|
||||
filters.append(self.domain_type)
|
||||
filter_bins.append((subdomain,))
|
||||
|
||||
# Construct list of energy group bounds tuples for all requested groups
|
||||
if not isinstance(groups, basestring):
|
||||
cv.check_iterable_type('groups', groups, Integral)
|
||||
for group in groups:
|
||||
filters.append('energyout')
|
||||
filter_bins.append((self.energy_groups.get_group_bounds(group),))
|
||||
|
||||
# If chi prompt was computed for each nuclide in the domain
|
||||
if self.by_nuclide:
|
||||
|
||||
# Get the sum as the fission source weighted average chi for all
|
||||
# nuclides in the domain
|
||||
if nuclides == 'sum' or nuclides == ['sum']:
|
||||
|
||||
# Retrieve the fission production tallies
|
||||
prompt_nu_fission_in = self.tallies['nu-fission-in'] - \
|
||||
self.tallies['delayed-nu-fission-in']
|
||||
prompt_nu_fission_out = self.tallies['nu-fission-out'] - \
|
||||
self.tallies['delayed-nu-fission-out']
|
||||
|
||||
# Sum out all nuclides
|
||||
nuclides = self.get_all_nuclides()
|
||||
prompt_nu_fission_in = prompt_nu_fission_in.summation\
|
||||
(nuclides=nuclides)
|
||||
prompt_nu_fission_out = prompt_nu_fission_out.summation\
|
||||
(nuclides=nuclides)
|
||||
|
||||
# Remove coarse energy filter to keep it out of tally arithmetic
|
||||
energy_filter = prompt_nu_fission_in.find_filter('energy')
|
||||
prompt_nu_fission_in.remove_filter(energy_filter)
|
||||
|
||||
# Compute chi prompt and store it as the xs_tally attribute so
|
||||
# we can use the generic get_xs(...) method
|
||||
xs_tally = prompt_nu_fission_out / prompt_nu_fission_in
|
||||
|
||||
# Add the coarse energy filter back to the nu-fission tally
|
||||
prompt_nu_fission_in.filters.append(energy_filter)
|
||||
|
||||
xs = xs_tally.get_values(filters=filters,
|
||||
filter_bins=filter_bins, value=value)
|
||||
|
||||
# Get chi prompt for all nuclides in the domain
|
||||
elif nuclides == 'all':
|
||||
nuclides = self.get_all_nuclides()
|
||||
xs = self.xs_tally.get_values(filters=filters,
|
||||
filter_bins=filter_bins,
|
||||
nuclides=nuclides, value=value)
|
||||
|
||||
# Get chi prompt for user-specified nuclides in the domain
|
||||
else:
|
||||
cv.check_iterable_type('nuclides', nuclides, basestring)
|
||||
xs = self.xs_tally.get_values(filters=filters,
|
||||
filter_bins=filter_bins,
|
||||
nuclides=nuclides, value=value)
|
||||
|
||||
# If chi prompt was computed as an average of nuclides in the domain
|
||||
else:
|
||||
xs = self.xs_tally.get_values(filters=filters,
|
||||
filter_bins=filter_bins, value=value)
|
||||
|
||||
# Reverse data if user requested increasing energy groups since
|
||||
# tally data is stored in order of increasing energies
|
||||
if order_groups == 'increasing':
|
||||
|
||||
# Reshape tally data array with separate axes for domain and energy
|
||||
if groups == 'all':
|
||||
num_groups = self.num_groups
|
||||
else:
|
||||
num_groups = len(groups)
|
||||
num_subdomains = int(xs.shape[0] / num_groups)
|
||||
new_shape = (num_subdomains, num_groups) + xs.shape[1:]
|
||||
xs = np.reshape(xs, new_shape)
|
||||
|
||||
# Reverse energies to align with increasing energy groups
|
||||
xs = xs[:, ::-1, :]
|
||||
|
||||
# Eliminate trivial dimensions
|
||||
xs = np.squeeze(xs)
|
||||
xs = np.atleast_1d(xs)
|
||||
|
||||
xs = np.nan_to_num(xs)
|
||||
return xs
|
||||
|
||||
|
||||
class Velocity(MGXS):
|
||||
"""A velocity multi-group cross section.
|
||||
r"""A velocity multi-group cross section.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -5235,7 +4987,7 @@ class Velocity(MGXS):
|
|||
|
||||
|
||||
class PromptNuFissionXS(MGXS):
|
||||
"""A prompt fission neutron production multi-group cross section.
|
||||
r"""A prompt fission neutron production multi-group cross section.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
|
|
@ -5341,15 +5093,3 @@ class PromptNuFissionXS(MGXS):
|
|||
super(PromptNuFissionXS, self).__init__(domain, domain_type, groups,
|
||||
by_nuclide, name)
|
||||
self._rxn_type = 'prompt-nu-fission'
|
||||
|
||||
@property
|
||||
def scores(self):
|
||||
return ['flux', 'nu-fission', 'delayed-nu-fission']
|
||||
|
||||
@property
|
||||
def rxn_rate_tally(self):
|
||||
if self._rxn_rate_tally is None:
|
||||
self._rxn_rate_tally = self.tallies['nu-fission'] - \
|
||||
self.tallies['delayed-nu-fission']
|
||||
self._rxn_rate_tally.sparse = self.sparse
|
||||
return self._rxn_rate_tally
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ module constants
|
|||
EVENT_ABSORB = 2
|
||||
|
||||
! Tally score type
|
||||
integer, parameter :: N_SCORE_TYPES = 20
|
||||
integer, parameter :: N_SCORE_TYPES = 21
|
||||
integer, parameter :: &
|
||||
SCORE_FLUX = -1, & ! flux
|
||||
SCORE_TOTAL = -2, & ! total reaction rate
|
||||
|
|
@ -303,7 +303,8 @@ module constants
|
|||
SCORE_NU_SCATTER_YN = -17, & ! angular flux-weighted nu-scattering moment (0:N)
|
||||
SCORE_EVENTS = -18, & ! number of events
|
||||
SCORE_DELAYED_NU_FISSION = -19, & ! delayed neutron production rate
|
||||
SCORE_INVERSE_VELOCITY = -20 ! flux-weighted inverse velocity
|
||||
SCORE_PROMPT_NU_FISSION = -20, & ! prompt neutron production rate
|
||||
SCORE_INVERSE_VELOCITY = -21 ! flux-weighted inverse velocity
|
||||
|
||||
! Maximum scattering order supported
|
||||
integer, parameter :: MAX_ANG_ORDER = 10
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ contains
|
|||
string = "nu-fission"
|
||||
case (SCORE_DELAYED_NU_FISSION)
|
||||
string = "delayed-nu-fission"
|
||||
case (SCORE_PROMPT_NU_FISSION)
|
||||
string = "prompt-nu-fission"
|
||||
case (SCORE_KAPPA_FISSION)
|
||||
string = "kappa-fission"
|
||||
case (SCORE_CURRENT)
|
||||
|
|
|
|||
|
|
@ -3599,6 +3599,12 @@ contains
|
|||
! Set tally estimator to analog
|
||||
t % estimator = ESTIMATOR_ANALOG
|
||||
end if
|
||||
case ('prompt-nu-fission')
|
||||
t % score_bins(j) = SCORE_PROMPT_NU_FISSION
|
||||
if (t % find_filter(FILTER_ENERGYOUT) > 0) then
|
||||
! Set tally estimator to analog
|
||||
t % estimator = ESTIMATOR_ANALOG
|
||||
end if
|
||||
|
||||
! Disallow for MG mode since data not present
|
||||
if (.not. run_CE) then
|
||||
|
|
|
|||
|
|
@ -791,6 +791,7 @@ contains
|
|||
score_names(abs(SCORE_NU_SCATTER_PN)) = "Scattering Prod. Rate Moment"
|
||||
score_names(abs(SCORE_NU_SCATTER_YN)) = "Scattering Prod. Rate Moment"
|
||||
score_names(abs(SCORE_DELAYED_NU_FISSION)) = "Delayed-Nu-Fission Rate"
|
||||
score_names(abs(SCORE_PROMPT_NU_FISSION)) = "Prompt-Nu-Fission Rate"
|
||||
score_names(abs(SCORE_INVERSE_VELOCITY)) = "Flux-Weighted Inverse Velocity"
|
||||
|
||||
! Create filename for tally output
|
||||
|
|
|
|||
131
src/tally.F90
131
src/tally.F90
|
|
@ -441,6 +441,67 @@ contains
|
|||
end if
|
||||
|
||||
|
||||
case (SCORE_PROMPT_NU_FISSION)
|
||||
if (t % estimator == ESTIMATOR_ANALOG) then
|
||||
if (survival_biasing .or. p % fission) then
|
||||
if (t % find_filter(FILTER_ENERGYOUT) > 0) then
|
||||
! Normally, we only need to make contributions to one scoring
|
||||
! bin. However, in the case of fission, since multiple fission
|
||||
! neutrons were emitted with different energies, multiple
|
||||
! outgoing energy bins may have been scored to. The following
|
||||
! logic treats this special case and results to multiple bins
|
||||
call score_fission_prompt_eout(p, t, score_index)
|
||||
cycle SCORE_LOOP
|
||||
end if
|
||||
end if
|
||||
if (survival_biasing) then
|
||||
! No fission events occur if survival biasing is on -- need to
|
||||
! calculate fraction of absorptions that would have resulted in
|
||||
! prompt-nu-fission
|
||||
if (micro_xs(p % event_nuclide) % absorption > ZERO) then
|
||||
score = p % absorb_wgt * micro_xs(p % event_nuclide) % fission &
|
||||
* nuclides(p % event_nuclide) % nu(E, EMISSION_PROMPT) &
|
||||
/ micro_xs(p % event_nuclide) % absorption
|
||||
else
|
||||
score = ZERO
|
||||
end if
|
||||
else
|
||||
! Skip any non-fission events
|
||||
if (.not. p % fission) cycle SCORE_LOOP
|
||||
! If there is no outgoing energy filter, than we only need to
|
||||
! score to one bin. For the score to be 'analog', we need to
|
||||
! score the number of particles that were banked in the fission
|
||||
! bank as prompt neutrons. Since this was weighted by 1/keff, we
|
||||
! multiply by keff to get the proper score.
|
||||
score = keff * p % wgt_bank * (1 - sum(p % n_delayed_bank) &
|
||||
/ p % n_bank)
|
||||
end if
|
||||
|
||||
else
|
||||
if (i_nuclide > 0) then
|
||||
score = micro_xs(i_nuclide) % fission * nuclides(i_nuclide) % &
|
||||
nu(E, EMISSION_PROMPT) * atom_density * flux
|
||||
else
|
||||
|
||||
score = ZERO
|
||||
|
||||
! Loop over all nuclides in the current material
|
||||
do l = 1, materials(p % material) % n_nuclides
|
||||
|
||||
! Get atom density
|
||||
atom_density_ = materials(p % material) % atom_density(l)
|
||||
|
||||
! Get index in nuclides array
|
||||
i_nuc = materials(p % material) % nuclide(l)
|
||||
|
||||
! Accumulate the contribution from each nuclide
|
||||
score = score + micro_xs(i_nuc) % fission * nuclides(i_nuc) % &
|
||||
nu(E, EMISSION_PROMPT) * atom_density_ * flux
|
||||
end do
|
||||
end if
|
||||
end if
|
||||
|
||||
|
||||
case (SCORE_DELAYED_NU_FISSION)
|
||||
|
||||
! make sure the correct energy is used
|
||||
|
|
@ -1647,6 +1708,76 @@ contains
|
|||
|
||||
end subroutine score_fission_eout_mg
|
||||
|
||||
!===============================================================================
|
||||
! SCORE_FISSION_PROMPT_EOUT handles a special case where we need to store
|
||||
! prompt neutron production rate with an outgoing energy filter (think of a
|
||||
! fission matrix). In this case, we may need to score to multiple bins if there
|
||||
! were multiple neutrons produced with different energies.
|
||||
!===============================================================================
|
||||
|
||||
subroutine score_fission_prompt_eout(p, t, i_score)
|
||||
|
||||
type(Particle), intent(in) :: p
|
||||
type(TallyObject), intent(inout) :: t
|
||||
integer, intent(in) :: i_score ! index for score
|
||||
|
||||
integer :: i ! index of outgoing energy filter
|
||||
integer :: g ! delayed group
|
||||
integer :: n ! number of energies on filter
|
||||
integer :: k ! loop index for bank sites
|
||||
integer :: bin_energyout ! original outgoing energy bin
|
||||
integer :: i_filter ! index for matching filter bin combination
|
||||
real(8) :: score ! actual score
|
||||
real(8) :: E_out ! energy of fission bank site
|
||||
|
||||
! Save original outgoing energy bin
|
||||
i = t % find_filter(FILTER_ENERGYOUT)
|
||||
bin_energyout = matching_bins(i)
|
||||
|
||||
! Get number of energies on filter
|
||||
n = size(t % filters(i) % real_bins)
|
||||
|
||||
! Since the creation of fission sites is weighted such that it is
|
||||
! expected to create n_particles sites, we need to multiply the
|
||||
! score by keff to get the true delayed-nu-fission rate.
|
||||
|
||||
! loop over number of particles banked
|
||||
do k = 1, p % n_bank
|
||||
|
||||
! get the delayed group
|
||||
g = fission_bank(n_bank - p % n_bank + k) % delayed_group
|
||||
|
||||
! check if the particle was born prompt
|
||||
if (g == 0) then
|
||||
|
||||
! determine score based on bank site weight and keff
|
||||
score = keff * fission_bank(n_bank - p % n_bank + k) % wgt
|
||||
|
||||
! determine outgoing energy from fission bank
|
||||
E_out = fission_bank(n_bank - p % n_bank + k) % E
|
||||
|
||||
! check if outgoing energy is within specified range on filter
|
||||
if (E_out < t % filters(i) % real_bins(1) .or. &
|
||||
E_out > t % filters(i) % real_bins(n)) cycle
|
||||
|
||||
! change outgoing energy bin
|
||||
matching_bins(i) = binary_search(t % filters(i) % real_bins, n, E_out)
|
||||
|
||||
! determine scoring index
|
||||
i_filter = sum((matching_bins(1:t%n_filters) - 1) * t % stride) + 1
|
||||
|
||||
! Add score to tally
|
||||
!$omp atomic
|
||||
t % results(i_score, i_filter) % value = &
|
||||
t % results(i_score, i_filter) % value + score
|
||||
end if
|
||||
end do
|
||||
|
||||
! reset outgoing energy bin
|
||||
matching_bins(i) = bin_energyout
|
||||
|
||||
end subroutine score_fission_prompt_eout
|
||||
|
||||
!===============================================================================
|
||||
! SCORE_FISSION_DELAYED_EOUT handles a special case where we need to store
|
||||
! delayed neutron production rate with an outgoing energy filter (think of a
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ class TalliesTestHarness(PyAPITestHarness):
|
|||
t.filters = [cell_filter]
|
||||
t.scores = ['absorption', 'delayed-nu-fission', 'events', 'fission',
|
||||
'inverse-velocity', 'kappa-fission', '(n,2n)', '(n,n1)',
|
||||
'(n,gamma)', 'nu-fission', 'scatter', 'elastic', 'total']
|
||||
'(n,gamma)', 'nu-fission', 'scatter', 'elastic', 'total',
|
||||
'prompt-nu-fission']
|
||||
score_tallies[0].estimator = 'tracklength'
|
||||
score_tallies[1].estimator = 'analog'
|
||||
score_tallies[2].estimator = 'collision'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue