mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 21:55:41 -04:00
Merge pull request #680 from samuelshaner/new-mgxs-tallies
New MGXS for chi-prompt, prompt-nu-fission, and velocity
This commit is contained in:
commit
97fd71b3e8
26 changed files with 681 additions and 152 deletions
|
|
@ -383,6 +383,9 @@
|
|||
"* `ScatterMatrixXS`\n",
|
||||
"* `NuScatterMatrixXS`\n",
|
||||
"* `Chi`\n",
|
||||
"* `ChiPrompt`\n",
|
||||
"* `InverseVelocity`\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."
|
||||
]
|
||||
|
|
@ -1164,21 +1167,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.2"
|
||||
"pygments_lexer": "ipython2",
|
||||
"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",
|
||||
"* `InverseVelocity` (`\"inverse-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.2"
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.11"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
|
|
@ -269,13 +269,16 @@ Multi-group Cross Sections
|
|||
openmc.mgxs.AbsorptionXS
|
||||
openmc.mgxs.CaptureXS
|
||||
openmc.mgxs.Chi
|
||||
openmc.mgxs.ChiPrompt
|
||||
openmc.mgxs.FissionXS
|
||||
openmc.mgxs.InverseVelocity
|
||||
openmc.mgxs.KappaFissionXS
|
||||
openmc.mgxs.MultiplicityMatrixXS
|
||||
openmc.mgxs.NuFissionXS
|
||||
openmc.mgxs.NuFissionMatrixXS
|
||||
openmc.mgxs.NuScatterXS
|
||||
openmc.mgxs.NuScatterMatrixXS
|
||||
openmc.mgxs.PromptNuFissionXS
|
||||
openmc.mgxs.ScatterXS
|
||||
openmc.mgxs.ScatterMatrixXS
|
||||
openmc.mgxs.TotalXS
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ def check_less_than(name, value, maximum, equality=False):
|
|||
raise ValueError(msg)
|
||||
|
||||
def check_greater_than(name, value, minimum, equality=False):
|
||||
"""Ensure that an object's value is less than a given value.
|
||||
"""Ensure that an object's value is greater than a given value.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
|
|||
|
|
@ -563,7 +563,7 @@ class Filter(object):
|
|||
# Initialize dictionary to build Pandas Multi-index column
|
||||
filter_dict = {}
|
||||
|
||||
# Append Mesh ID as outermost index of mult-index
|
||||
# Append Mesh ID as outermost index of multi-index
|
||||
mesh_key = 'mesh {0}'.format(self.mesh.id)
|
||||
|
||||
# Find mesh dimensions - use 3D indices for simplicity
|
||||
|
|
|
|||
|
|
@ -452,7 +452,7 @@ class Library(object):
|
|||
----------
|
||||
domain : Material or Cell or Universe or Integral
|
||||
The material, cell, or universe object of interest (or its ID)
|
||||
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'}
|
||||
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', 'inverse-velocity', 'prompt-nu-fission'}
|
||||
The type of multi-group cross section object to return
|
||||
|
||||
Returns
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ MGXS_TYPES = ['total',
|
|||
'nu-scatter matrix',
|
||||
'multiplicity matrix',
|
||||
'nu-fission matrix',
|
||||
'chi']
|
||||
'chi',
|
||||
'chi-prompt',
|
||||
'inverse-velocity',
|
||||
'prompt-nu-fission']
|
||||
|
||||
|
||||
# Supported domain types
|
||||
|
|
@ -427,7 +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'}
|
||||
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', 'inverse-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
|
||||
|
|
@ -482,6 +485,12 @@ class MGXS(object):
|
|||
mgxs = NuFissionMatrixXS(domain, domain_type, energy_groups)
|
||||
elif mgxs_type == 'chi':
|
||||
mgxs = Chi(domain, domain_type, energy_groups)
|
||||
elif mgxs_type == 'chi-prompt':
|
||||
mgxs = ChiPrompt(domain, domain_type, energy_groups)
|
||||
elif mgxs_type == 'inverse-velocity':
|
||||
mgxs = InverseVelocity(domain, domain_type, energy_groups)
|
||||
elif mgxs_type == 'prompt-nu-fission':
|
||||
mgxs = PromptNuFissionXS(domain, domain_type, energy_groups)
|
||||
|
||||
mgxs.by_nuclide = by_nuclide
|
||||
mgxs.name = name
|
||||
|
|
@ -704,7 +713,7 @@ class MGXS(object):
|
|||
def get_xs(self, groups='all', subdomains='all', nuclides='all',
|
||||
xs_type='macro', order_groups='increasing',
|
||||
value='mean', **kwargs):
|
||||
"""Returns an array of multi-group cross sections.
|
||||
r"""Returns an array of multi-group cross sections.
|
||||
|
||||
This method constructs a 2D NumPy array for the requested multi-group
|
||||
cross section data data for one or more energy groups and subdomains.
|
||||
|
|
@ -1148,6 +1157,9 @@ class MGXS(object):
|
|||
string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type)
|
||||
string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id)
|
||||
|
||||
# Generate the header for an individual XS
|
||||
xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type))
|
||||
|
||||
# If cross section data has not been computed, only print string header
|
||||
if self.tallies is None:
|
||||
print(string)
|
||||
|
|
@ -1167,11 +1179,7 @@ class MGXS(object):
|
|||
string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide)
|
||||
|
||||
# Build header for cross section type
|
||||
if xs_type == 'macro':
|
||||
string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:')
|
||||
else:
|
||||
string += '{0: <16}\n'.format('\tCross Sections [barns]:')
|
||||
|
||||
string += '{0: <16}\n'.format(xs_header)
|
||||
template = '{0: <12}Group {1} [{2: <10} - {3: <10}MeV]:\t'
|
||||
|
||||
# Loop over energy groups ranges
|
||||
|
|
@ -1530,6 +1538,26 @@ class MGXS(object):
|
|||
df.sort_values(by=[self.domain_type] + columns, inplace=True)
|
||||
return df
|
||||
|
||||
def get_units(self, xs_type='macro'):
|
||||
"""This method returns the units of a MGXS based on a desired xs_type.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xs_type: {'macro', 'micro'}
|
||||
Return the macro or micro cross section units.
|
||||
Defaults to 'macro'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
A string representing the units of the MGXS.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
|
||||
return 'cm^-1' if xs_type == 'macro' else 'barns'
|
||||
|
||||
|
||||
class MatrixMGXS(MGXS):
|
||||
"""An abstract multi-group cross section for some energy group structure
|
||||
|
|
@ -1878,6 +1906,9 @@ class MatrixMGXS(MGXS):
|
|||
string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type)
|
||||
string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id)
|
||||
|
||||
# Generate the header for an individual XS
|
||||
xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type))
|
||||
|
||||
# If cross section data has not been computed, only print string header
|
||||
if self.tallies is None:
|
||||
print(string)
|
||||
|
|
@ -1906,11 +1937,7 @@ class MatrixMGXS(MGXS):
|
|||
string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide)
|
||||
|
||||
# Build header for cross section type
|
||||
if xs_type == 'macro':
|
||||
string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:')
|
||||
else:
|
||||
string += '{0: <16}\n'.format('\tCross Sections [barns]:')
|
||||
|
||||
string += '{0: <16}\n'.format(xs_header)
|
||||
template = '{0: <12}Group {1} -> Group {2}:\t\t'
|
||||
|
||||
# Loop over incoming/outgoing energy groups ranges
|
||||
|
|
@ -3723,6 +3750,9 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type)
|
||||
string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id)
|
||||
|
||||
# Generate the header for an individual XS
|
||||
xs_header = '\tCross Sections [{0}]:'.format(self.get_units(xs_type))
|
||||
|
||||
# If cross section data has not been computed, only print string header
|
||||
if self.tallies is None:
|
||||
print(string)
|
||||
|
|
@ -3751,11 +3781,7 @@ class ScatterMatrixXS(MatrixMGXS):
|
|||
string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide)
|
||||
|
||||
# Build header for cross section type
|
||||
if xs_type == 'macro':
|
||||
string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:')
|
||||
else:
|
||||
string += '{0: <16}\n'.format('\tCross Sections [barns]:')
|
||||
|
||||
string += '{0: <16}\n'.format(xs_header)
|
||||
template = '{0: <12}Group {1} -> Group {2}:\t\t'
|
||||
|
||||
# Loop over incoming/outgoing energy groups ranges
|
||||
|
|
@ -4183,14 +4209,14 @@ class Chi(MGXS):
|
|||
|
||||
.. math::
|
||||
|
||||
\langle \nu\sigma_{f,\rightarrow g} \phi \rangle &= \int_{r \in V} dr
|
||||
\langle \nu\sigma_{f,g' \rightarrow g} \phi \rangle &= \int_{r \in V} dr
|
||||
\int_{4\pi} d\Omega' \int_0^\infty dE' \int_{E_g}^{E_{g-1}} dE \; \chi(E)
|
||||
\nu\sigma_f (r, E') \psi(r, E', \Omega')\\
|
||||
\langle \nu\sigma_f \phi \rangle &= \int_{r \in V} dr \int_{4\pi}
|
||||
d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \chi(E) \nu\sigma_f (r,
|
||||
E') \psi(r, E', \Omega') \\
|
||||
\chi_g &= \frac{\langle \nu\sigma_{f,\rightarrow g} \phi \rangle}{\langle
|
||||
\nu\sigma_f \phi \rangle}
|
||||
\chi_g &= \frac{\langle \nu\sigma_{f,g' \rightarrow g} \phi \rangle}
|
||||
{\langle \nu\sigma_f \phi \rangle}
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -4395,7 +4421,7 @@ class Chi(MGXS):
|
|||
"""
|
||||
|
||||
if not self.can_merge(other):
|
||||
raise ValueError('Unable to merge Chi')
|
||||
raise ValueError('Unable to merge a Chi MGXS')
|
||||
|
||||
# Create deep copy of tally to return as merged tally
|
||||
merged_mgxs = copy.deepcopy(self)
|
||||
|
|
@ -4414,7 +4440,7 @@ class Chi(MGXS):
|
|||
# The nuclides must be mutually exclusive
|
||||
for nuclide in self.nuclides:
|
||||
if nuclide in other.nuclides:
|
||||
msg = 'Unable to merge Chi with shared nuclides'
|
||||
msg = 'Unable to merge a Chi MGXS with shared nuclides'
|
||||
raise ValueError(msg)
|
||||
|
||||
# Concatenate lists of nuclides for the merged MGXS
|
||||
|
|
@ -4618,3 +4644,392 @@ class Chi(MGXS):
|
|||
df['std. dev.'] *= np.tile(densities, tile_factor)
|
||||
|
||||
return df
|
||||
|
||||
def get_units(self, xs_type='macro'):
|
||||
"""Returns the units of Chi.
|
||||
|
||||
This method returns the units of Chi, which is "%" for both macro
|
||||
and micro xs types.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xs_type: {'macro', 'micro'}
|
||||
Return the macro or micro cross section units.
|
||||
Defaults to 'macro'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
A string representing the units of Chi.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
|
||||
# Chi has the same units (%) for both macro and micro
|
||||
return '%'
|
||||
|
||||
|
||||
class ChiPrompt(Chi):
|
||||
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
|
||||
multi-group cross sections for multi-group neutronics calculations. At a
|
||||
minimum, one needs to set the :attr:`ChiPrompt.energy_groups` and
|
||||
:attr:`ChiPrompt.domain` properties. Tallies for the flux and appropriate
|
||||
reaction rates over the specified domain are generated automatically via the
|
||||
:attr:`ChiPrompt.tallies` property, which can then be appended to a
|
||||
:class:`openmc.Tallies` instance.
|
||||
|
||||
For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the
|
||||
necessary data to compute multi-group cross sections from a
|
||||
:class:`openmc.StatePoint` instance. The derived multi-group cross section
|
||||
can then be obtained from the :attr:`ChiPrompt.xs_tally` property.
|
||||
|
||||
For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the
|
||||
fission spectrum is calculated as:
|
||||
|
||||
.. math::
|
||||
|
||||
\langle \nu^p \sigma_{f,g' \rightarrow g} \phi \rangle &= \int_{r \in V}
|
||||
dr \int_{4\pi} d\Omega' \int_0^\infty dE' \int_{E_g}^{E_{g-1}} dE \;
|
||||
\chi(E) \nu^p \sigma_f (r, E') \psi(r, E', \Omega')\\
|
||||
\langle \nu^p \sigma_f \phi \rangle &= \int_{r \in V} dr \int_{4\pi}
|
||||
d\Omega' \int_0^\infty dE' \int_0^\infty dE \; \chi(E) \nu^p \sigma_f (r,
|
||||
E') \psi(r, E', \Omega') \\
|
||||
\chi_g^p &= \frac{\langle \nu^p \sigma_{f,g' \rightarrow g} \phi \rangle}
|
||||
{\langle \nu^p \sigma_f \phi \rangle}
|
||||
|
||||
Parameters
|
||||
----------
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe
|
||||
The domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
The domain type for spatial homogenization
|
||||
groups : openmc.mgxs.EnergyGroups
|
||||
The energy group structure for energy condensation
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
name : str, optional
|
||||
Name of the multi-group cross section. Used as a label to identify
|
||||
tallies in OpenMC 'tallies.xml' file.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name : str, optional
|
||||
Name of the multi-group cross section
|
||||
rxn_type : str
|
||||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
Domain type for spatial homogenization
|
||||
energy_groups : openmc.mgxs.EnergyGroups
|
||||
Energy group structure for energy condensation
|
||||
tally_trigger : openmc.Trigger
|
||||
An (optional) tally precision trigger given to each tally used to
|
||||
compute the cross section
|
||||
scores : list of str
|
||||
The scores in each tally used to compute the multi-group cross section
|
||||
filters : list of openmc.Filter
|
||||
The filters in each tally used to compute the multi-group cross section
|
||||
tally_keys : list of str
|
||||
The keys into the tallies dictionary for each tally used to compute
|
||||
the multi-group cross section
|
||||
estimator : {'tracklength', 'analog'}
|
||||
The tally estimator used to compute the multi-group cross section
|
||||
tallies : collections.OrderedDict
|
||||
OpenMC tallies needed to compute the multi-group cross section. The keys
|
||||
are strings listed in the :attr:`ChiPrompt.tally_keys` property and
|
||||
values are instances of :class:`openmc.Tally`.
|
||||
rxn_rate_tally : openmc.Tally
|
||||
Derived tally for the reaction rate tally used in the numerator to
|
||||
compute the multi-group cross section. This attribute is None
|
||||
unless the multi-group cross section has been computed.
|
||||
xs_tally : openmc.Tally
|
||||
Derived tally for the multi-group cross section. This attribute
|
||||
is None unless the multi-group cross section has been computed.
|
||||
num_subdomains : int
|
||||
The number of subdomains is unity for 'material', 'cell' and 'universe'
|
||||
domain types. When the This is equal to the number of cell instances
|
||||
for 'distribcell' domain types (it is equal to unity prior to loading
|
||||
tally data from a statepoint file).
|
||||
num_nuclides : int
|
||||
The number of nuclides for which the multi-group cross section is
|
||||
being tracked. This is unity if the by_nuclide attribute is False.
|
||||
nuclides : Iterable of str or 'sum'
|
||||
The optional user-specified nuclides for which to compute cross
|
||||
sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides
|
||||
are not specified by the user, all nuclides in the spatial domain
|
||||
are included. This attribute is 'sum' if by_nuclide is false.
|
||||
sparse : bool
|
||||
Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format
|
||||
for compressed data storage
|
||||
loaded_sp : bool
|
||||
Whether or not a statepoint file has been loaded with tally data
|
||||
derived : bool
|
||||
Whether or not the MGXS is merged from one or more other MGXS
|
||||
hdf5_key : str
|
||||
The key used to index multi-group cross sections in an HDF5 data store
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
groups=None, by_nuclide=False, name=''):
|
||||
super(ChiPrompt, self).__init__(domain, domain_type, groups, by_nuclide, name)
|
||||
self._rxn_type = 'chi-prompt'
|
||||
|
||||
@property
|
||||
def scores(self):
|
||||
return ['prompt-nu-fission', 'prompt-nu-fission']
|
||||
|
||||
|
||||
class InverseVelocity(MGXS):
|
||||
r"""An inverse 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
|
||||
multi-group neutron inverse velocities for multi-group neutronics
|
||||
calculations. The units of inverse velocity are seconds per centimeter. At a
|
||||
minimum, one needs to set the :attr:`InverseVelocity.energy_groups` and
|
||||
:attr:`InverseVelocity.domain` properties. Tallies for the flux and
|
||||
appropriate reaction rates over the specified domain are generated
|
||||
automatically via the :attr:`InverseVelocity.tallies` property, which can
|
||||
then be appended to a :class:`openmc.Tallies` instance.
|
||||
|
||||
For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the
|
||||
necessary data to compute multi-group cross sections from a
|
||||
:class:`openmc.StatePoint` instance. The derived multi-group cross section
|
||||
can then be obtained from the :attr:`InverseVelocity.xs_tally` property.
|
||||
|
||||
For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the
|
||||
neutron inverse velocities are calculated by tallying the flux-weighted
|
||||
inverse velocity and the flux. The inverse velocity is then the
|
||||
flux-weighted inverse velocity divided by the flux:
|
||||
|
||||
.. math::
|
||||
|
||||
\frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \;
|
||||
\frac{\psi (r, E, \Omega)}{v (r, E)}}{\int_{r \in V} dr \int_{4\pi}
|
||||
d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}
|
||||
|
||||
Parameters
|
||||
----------
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe
|
||||
The domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
The domain type for spatial homogenization
|
||||
groups : openmc.mgxs.EnergyGroups
|
||||
The energy group structure for energy condensation
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
name : str, optional
|
||||
Name of the multi-group cross section. Used as a label to identify
|
||||
tallies in OpenMC 'tallies.xml' file.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name : str, optional
|
||||
Name of the multi-group cross section
|
||||
rxn_type : str
|
||||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
Domain type for spatial homogenization
|
||||
energy_groups : openmc.mgxs.EnergyGroups
|
||||
Energy group structure for energy condensation
|
||||
tally_trigger : openmc.Trigger
|
||||
An (optional) tally precision trigger given to each tally used to
|
||||
compute the cross section
|
||||
scores : list of str
|
||||
The scores in each tally used to compute the multi-group cross section
|
||||
filters : list of openmc.Filter
|
||||
The filters in each tally used to compute the multi-group cross section
|
||||
tally_keys : list of str
|
||||
The keys into the tallies dictionary for each tally used to compute
|
||||
the multi-group cross section
|
||||
estimator : {'tracklength', 'analog'}
|
||||
The tally estimator used to compute the multi-group cross section
|
||||
tallies : collections.OrderedDict
|
||||
OpenMC tallies needed to compute the multi-group cross section. The keys
|
||||
are strings listed in the :attr:`InverseVelocity.tally_keys` property
|
||||
and values are instances of :class:`openmc.Tally`.
|
||||
rxn_rate_tally : openmc.Tally
|
||||
Derived tally for the reaction rate tally used in the numerator to
|
||||
compute the multi-group cross section. This attribute is None
|
||||
unless the multi-group cross section has been computed.
|
||||
xs_tally : openmc.Tally
|
||||
Derived tally for the multi-group cross section. This attribute
|
||||
is None unless the multi-group cross section has been computed.
|
||||
num_subdomains : int
|
||||
The number of subdomains is unity for 'material', 'cell' and 'universe'
|
||||
domain types. This is equal to the number of cell instances
|
||||
for 'distribcell' domain types (it is equal to unity prior to loading
|
||||
tally data from a statepoint file).
|
||||
num_nuclides : int
|
||||
The number of nuclides for which the multi-group cross section is
|
||||
being tracked. This is unity if the by_nuclide attribute is False.
|
||||
nuclides : Iterable of str or 'sum'
|
||||
The optional user-specified nuclides for which to compute cross
|
||||
sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides
|
||||
are not specified by the user, all nuclides in the spatial domain
|
||||
are included. This attribute is 'sum' if by_nuclide is false.
|
||||
sparse : bool
|
||||
Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format
|
||||
for compressed data storage
|
||||
loaded_sp : bool
|
||||
Whether or not a statepoint file has been loaded with tally data
|
||||
derived : bool
|
||||
Whether or not the MGXS is merged from one or more other MGXS
|
||||
hdf5_key : str
|
||||
The key used to index multi-group cross sections in an HDF5 data store
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
groups=None, by_nuclide=False, name=''):
|
||||
super(InverseVelocity, self).__init__(domain, domain_type,
|
||||
groups, by_nuclide, name)
|
||||
self._rxn_type = 'inverse-velocity'
|
||||
|
||||
def get_units(self, xs_type='macro'):
|
||||
"""Returns the units of InverseVelocity.
|
||||
|
||||
This method returns the units of an InverseVelocity based on a desired
|
||||
xs_type.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xs_type: {'macro', 'micro'}
|
||||
Return the macro or micro cross section units.
|
||||
Defaults to 'macro'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
A string representing the units of the InverseVelocity.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
|
||||
if xs_type == 'macro':
|
||||
return 'second/cm'
|
||||
else:
|
||||
raise ValueError('Unable to return the units of InverseVelocity for'
|
||||
' xs_type other than "macro"')
|
||||
|
||||
|
||||
class PromptNuFissionXS(MGXS):
|
||||
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
|
||||
multi-group cross sections for multi-group neutronics calculations. At a
|
||||
minimum, one needs to set the :attr:`PromptNuFissionXS.energy_groups` and
|
||||
:attr:`PromptNuFissionXS.domain` properties. Tallies for the flux and
|
||||
appropriate reaction rates over the specified domain are generated
|
||||
automatically via the :attr:`PromptNuFissionXS.tallies` property, which can
|
||||
then be appended to a :class:`openmc.Tallies` instance.
|
||||
|
||||
For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the
|
||||
necessary data to compute multi-group cross sections from a
|
||||
:class:`openmc.StatePoint` instance. The derived multi-group cross section
|
||||
can then be obtained from the :attr:`PromptNuFissionXS.xs_tally` property.
|
||||
|
||||
For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the
|
||||
fission spectrum is calculated as:
|
||||
|
||||
.. math::
|
||||
|
||||
\frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \;
|
||||
\nu\sigma_f^p (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi}
|
||||
d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)}.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe
|
||||
The domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
The domain type for spatial homogenization
|
||||
groups : openmc.mgxs.EnergyGroups
|
||||
The energy group structure for energy condensation
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
name : str, optional
|
||||
Name of the multi-group cross section. Used as a label to identify
|
||||
tallies in OpenMC 'tallies.xml' file.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
name : str, optional
|
||||
Name of the multi-group cross section
|
||||
rxn_type : str
|
||||
Reaction type (e.g., 'total', 'nu-fission', etc.)
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in domain
|
||||
domain : Material or Cell or Universe
|
||||
Domain for spatial homogenization
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
Domain type for spatial homogenization
|
||||
energy_groups : openmc.mgxs.EnergyGroups
|
||||
Energy group structure for energy condensation
|
||||
tally_trigger : openmc.Trigger
|
||||
An (optional) tally precision trigger given to each tally used to
|
||||
compute the cross section
|
||||
scores : list of str
|
||||
The scores in each tally used to compute the multi-group cross section
|
||||
filters : list of openmc.Filter
|
||||
The filters in each tally used to compute the multi-group cross section
|
||||
tally_keys : list of str
|
||||
The keys into the tallies dictionary for each tally used to compute
|
||||
the multi-group cross section
|
||||
estimator : {'tracklength', 'analog'}
|
||||
The tally estimator used to compute the multi-group cross section
|
||||
tallies : collections.OrderedDict
|
||||
OpenMC tallies needed to compute the multi-group cross section. The keys
|
||||
are strings listed in the :attr:`PromptNuFissionXS.tally_keys` property
|
||||
and values are instances of :class:`openmc.Tally`.
|
||||
rxn_rate_tally : openmc.Tally
|
||||
Derived tally for the reaction rate tally used in the numerator to
|
||||
compute the multi-group cross section. This attribute is None
|
||||
unless the multi-group cross section has been computed.
|
||||
xs_tally : openmc.Tally
|
||||
Derived tally for the multi-group cross section. This attribute
|
||||
is None unless the multi-group cross section has been computed.
|
||||
num_subdomains : int
|
||||
The number of subdomains is unity for 'material', 'cell' and 'universe'
|
||||
domain types. When the This is equal to the number of cell instances
|
||||
for 'distribcell' domain types (it is equal to unity prior to loading
|
||||
tally data from a statepoint file).
|
||||
num_nuclides : int
|
||||
The number of nuclides for which the multi-group cross section is
|
||||
being tracked. This is unity if the by_nuclide attribute is False.
|
||||
nuclides : Iterable of str or 'sum'
|
||||
The optional user-specified nuclides for which to compute cross
|
||||
sections (e.g., 'U-238', 'O-16'). If by_nuclide is True but nuclides
|
||||
are not specified by the user, all nuclides in the spatial domain
|
||||
are included. This attribute is 'sum' if by_nuclide is false.
|
||||
sparse : bool
|
||||
Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format
|
||||
for compressed data storage
|
||||
loaded_sp : bool
|
||||
Whether or not a statepoint file has been loaded with tally data
|
||||
derived : bool
|
||||
Whether or not the MGXS is merged from one or more other MGXS
|
||||
hdf5_key : str
|
||||
The key used to index multi-group cross sections in an HDF5 data store
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
groups=None, by_nuclide=False, name=''):
|
||||
super(PromptNuFissionXS, self).__init__(domain, domain_type, groups,
|
||||
by_nuclide, name)
|
||||
self._rxn_type = 'prompt-nu-fission'
|
||||
|
|
|
|||
|
|
@ -289,7 +289,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
|
||||
|
|
@ -310,7 +310,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)
|
||||
|
|
|
|||
|
|
@ -3619,6 +3619,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
|
||||
|
|
|
|||
|
|
@ -790,6 +790,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
|
||||
|
|
|
|||
222
src/tally.F90
222
src/tally.F90
|
|
@ -407,7 +407,7 @@ contains
|
|||
! 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_eout_ce(p, t, score_index)
|
||||
call score_fission_eout_ce(p, t, score_index, score_bin)
|
||||
cycle SCORE_LOOP
|
||||
end if
|
||||
end if
|
||||
|
|
@ -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_eout_ce(p, t, score_index, score_bin)
|
||||
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 * (ONE - sum(p % n_delayed_bank) &
|
||||
/ real(p % n_bank, 8))
|
||||
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
|
||||
|
|
@ -461,7 +522,7 @@ contains
|
|||
! 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_delayed_eout(p, t, score_index)
|
||||
call score_fission_eout_ce(p, t, score_index, score_bin)
|
||||
cycle SCORE_LOOP
|
||||
end if
|
||||
end if
|
||||
|
|
@ -1515,12 +1576,18 @@ contains
|
|||
! neutrons produced with different energies.
|
||||
!===============================================================================
|
||||
|
||||
subroutine score_fission_eout_ce(p, t, i_score)
|
||||
type(Particle), intent(in) :: p
|
||||
subroutine score_fission_eout_ce(p, t, i_score, score_bin)
|
||||
|
||||
type(Particle), intent(in) :: p
|
||||
type(TallyObject), intent(inout) :: t
|
||||
integer, intent(in) :: i_score ! index for score
|
||||
integer, intent(in) :: i_score ! index for score
|
||||
integer, intent(in) :: score_bin
|
||||
|
||||
integer :: i ! index of outgoing energy filter
|
||||
integer :: j ! index of delayedgroup filter
|
||||
integer :: d ! delayed group
|
||||
integer :: g ! another delayed group
|
||||
integer :: d_bin ! delayed group bin index
|
||||
integer :: n ! number of energies on filter
|
||||
integer :: k ! loop index for bank sites
|
||||
integer :: bin_energyout ! original outgoing energy bin
|
||||
|
|
@ -1542,6 +1609,10 @@ contains
|
|||
|
||||
! 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
|
||||
|
||||
! determine score based on bank site weight and keff
|
||||
score = keff * fission_bank(n_bank - p % n_bank + k) % wgt
|
||||
|
||||
|
|
@ -1555,13 +1626,49 @@ contains
|
|||
! 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
|
||||
! Case for tallying prompt neutrons
|
||||
if (score_bin == SCORE_NU_FISSION .or. &
|
||||
(score_bin == SCORE_PROMPT_NU_FISSION .and. g == 0)) then
|
||||
|
||||
! Add score to tally
|
||||
! 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
|
||||
t % results(i_score, i_filter) % value = &
|
||||
t % results(i_score, i_filter) % value + score
|
||||
|
||||
! Case for tallying delayed emissions
|
||||
else if (score_bin == SCORE_DELAYED_NU_FISSION .and. g /= 0) then
|
||||
|
||||
! Get the index of delayed group filter
|
||||
j = t % find_filter(FILTER_DELAYEDGROUP)
|
||||
|
||||
! if the delayed group filter is present, tally to corresponding
|
||||
! delayed group bin if it exists
|
||||
if (j > 0) then
|
||||
|
||||
! loop over delayed group bins until the corresponding bin is found
|
||||
do d_bin = 1, t % filters(j) % n_bins
|
||||
d = t % filters(j) % int_bins(d_bin)
|
||||
|
||||
! check whether the delayed group of the particle is equal to the
|
||||
! delayed group of this bin
|
||||
if (d == g) call score_fission_delayed_dg(t, d_bin, score, i_score)
|
||||
end do
|
||||
|
||||
! if the delayed group filter is not present, add score to tally
|
||||
else
|
||||
|
||||
! 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 if
|
||||
end do
|
||||
|
||||
! reset outgoing energy bin and score index
|
||||
|
|
@ -1647,101 +1754,6 @@ contains
|
|||
|
||||
end subroutine score_fission_eout_mg
|
||||
|
||||
!===============================================================================
|
||||
! 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
|
||||
! 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_delayed_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 :: j ! index of delayedgroup filter
|
||||
integer :: d ! delayed group
|
||||
integer :: g ! another delayed group
|
||||
integer :: d_bin ! delayed group bin index
|
||||
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 the index of delayed group filter
|
||||
j = t % find_filter(FILTER_DELAYEDGROUP)
|
||||
|
||||
! 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 delayed
|
||||
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)
|
||||
|
||||
! if the delayed group filter is present, tally to corresponding
|
||||
! delayed group bin if it exists
|
||||
if (j > 0) then
|
||||
|
||||
! loop over delayed group bins until the corresponding bin is found
|
||||
do d_bin = 1, t % filters(j) % n_bins
|
||||
d = t % filters(j) % int_bins(d_bin)
|
||||
|
||||
! check whether the delayed group of the particle is equal to the
|
||||
! delayed group of this bin
|
||||
if (d == g) then
|
||||
call score_fission_delayed_dg(t, d_bin, score, i_score)
|
||||
end if
|
||||
end do
|
||||
|
||||
! if the delayed group filter is not present, add score to tally
|
||||
else
|
||||
|
||||
! 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 if
|
||||
end do
|
||||
|
||||
! reset outgoing energy bin
|
||||
matching_bins(i) = bin_energyout
|
||||
|
||||
end subroutine score_fission_delayed_eout
|
||||
|
||||
!===============================================================================
|
||||
! SCORE_FISSION_DELAYED_DG helper function used to increment the tally when a
|
||||
! delayed group filter is present.
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
855919f7a333acff6423527b82656d6a472ea8416002fb475c2d21c676e2f75f5c040d209a3e9a3a6118cf944f2c1bfb8cf2318273b890861d790b1927791a35
|
||||
e2cdca7ea5b3532050af5b12fac26d7ef212d2696bb1b73cdd00929b2243c40d100ad02438c7b090555b49815d0de6c48cf1b4ebf437a48bc80c2d2b4bad292e
|
||||
|
|
@ -34,6 +34,12 @@
|
|||
0 10000 1 1 total 0.085835 0.005592
|
||||
material group out nuclide mean std. dev.
|
||||
0 10000 1 total 1.0 0.046071
|
||||
material group out nuclide mean std. dev.
|
||||
0 10000 1 total 1.0 0.051471
|
||||
material group in nuclide mean std. dev.
|
||||
0 10000 1 total 4.996730e-07 3.650635e-08
|
||||
material group in nuclide mean std. dev.
|
||||
0 10000 1 total 0.090004 0.006367
|
||||
material group in nuclide mean std. dev.
|
||||
0 10001 1 total 0.311594 0.013793
|
||||
material group in nuclide mean std. dev.
|
||||
|
|
@ -70,6 +76,12 @@
|
|||
0 10001 1 1 total 0.0 0.0
|
||||
material group out nuclide mean std. dev.
|
||||
0 10001 1 total 0.0 0.0
|
||||
material group out nuclide mean std. dev.
|
||||
0 10001 1 total 0.0 0.0
|
||||
material group in nuclide mean std. dev.
|
||||
0 10001 1 total 5.454760e-07 4.949800e-08
|
||||
material group in nuclide mean std. dev.
|
||||
0 10001 1 total 0.0 0.0
|
||||
material group in nuclide mean std. dev.
|
||||
0 10002 1 total 0.904999 0.043964
|
||||
material group in nuclide mean std. dev.
|
||||
|
|
@ -106,3 +118,9 @@
|
|||
0 10002 1 1 total 0.0 0.0
|
||||
material group out nuclide mean std. dev.
|
||||
0 10002 1 total 0.0 0.0
|
||||
material group out nuclide mean std. dev.
|
||||
0 10002 1 total 0.0 0.0
|
||||
material group in nuclide mean std. dev.
|
||||
0 10002 1 total 5.773006e-07 5.322132e-08
|
||||
material group in nuclide mean std. dev.
|
||||
0 10002 1 total 0.0 0.0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3a3b7f75b326c94a8e5c7efe3046b2fdb887e9f75ecf6eb27587f9450c77cf8fd6acc4198c15bffb4e7ceead6d7b4327c19536bbf9cc35dfaae3f4ce4c26cc1a
|
||||
2d948f3b12293294eaeca231a3df9d51195379e8bb38dd3e68d3bc512a7d08ed52a1109054ca381684ec127268710f6d6e9210ac8154c9b379608e996627624a
|
||||
|
|
@ -34,3 +34,9 @@
|
|||
0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 1 total 0.0 0.0
|
||||
avg(distribcell) group out nuclide mean std. dev.
|
||||
0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 total 0.0 0.0
|
||||
avg(distribcell) group out nuclide mean std. dev.
|
||||
0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 total 0.0 0.0
|
||||
avg(distribcell) group in nuclide mean std. dev.
|
||||
0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 total 0.000001 6.946255e-07
|
||||
avg(distribcell) group in nuclide mean std. dev.
|
||||
0 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,... 1 total 0.0 0.0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
855919f7a333acff6423527b82656d6a472ea8416002fb475c2d21c676e2f75f5c040d209a3e9a3a6118cf944f2c1bfb8cf2318273b890861d790b1927791a35
|
||||
e2cdca7ea5b3532050af5b12fac26d7ef212d2696bb1b73cdd00929b2243c40d100ad02438c7b090555b49815d0de6c48cf1b4ebf437a48bc80c2d2b4bad292e
|
||||
|
|
@ -63,6 +63,15 @@ domain=10000 type=nu-fission matrix
|
|||
domain=10000 type=chi
|
||||
[ 1. 0.]
|
||||
[ 0.04607052 0. ]
|
||||
domain=10000 type=chi-prompt
|
||||
[ 1. 0.]
|
||||
[ 0.05147146 0. ]
|
||||
domain=10000 type=inverse-velocity
|
||||
[ 5.70932329e-08 2.85573950e-06]
|
||||
[ 4.68792969e-09 2.44216503e-07]
|
||||
domain=10000 type=prompt-nu-fission
|
||||
[ 0.01923922 0.46671903]
|
||||
[ 0.00130951 0.04141087]
|
||||
domain=10001 type=total
|
||||
[ 0.31373767 0.3008214 ]
|
||||
[ 0.0155819 0.02805245]
|
||||
|
|
@ -128,6 +137,15 @@ domain=10001 type=nu-fission matrix
|
|||
domain=10001 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10001 type=chi-prompt
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10001 type=inverse-velocity
|
||||
[ 5.99598048e-08 2.98549021e-06]
|
||||
[ 4.55309296e-09 3.41701554e-07]
|
||||
domain=10001 type=prompt-nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10002 type=total
|
||||
[ 0.66457226 2.05238401]
|
||||
[ 0.03121475 0.22434291]
|
||||
|
|
@ -193,3 +211,12 @@ domain=10002 type=nu-fission matrix
|
|||
domain=10002 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10002 type=chi-prompt
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10002 type=inverse-velocity
|
||||
[ 6.02207831e-08 3.04495537e-06]
|
||||
[ 3.78043696e-09 3.60007673e-07]
|
||||
domain=10002 type=prompt-nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
855919f7a333acff6423527b82656d6a472ea8416002fb475c2d21c676e2f75f5c040d209a3e9a3a6118cf944f2c1bfb8cf2318273b890861d790b1927791a35
|
||||
e2cdca7ea5b3532050af5b12fac26d7ef212d2696bb1b73cdd00929b2243c40d100ad02438c7b090555b49815d0de6c48cf1b4ebf437a48bc80c2d2b4bad292e
|
||||
|
|
@ -75,6 +75,15 @@
|
|||
material group out nuclide mean std. dev.
|
||||
1 10000 1 total 1.0 0.046071
|
||||
0 10000 2 total 0.0 0.000000
|
||||
material group out nuclide mean std. dev.
|
||||
1 10000 1 total 1.0 0.051471
|
||||
0 10000 2 total 0.0 0.000000
|
||||
material group in nuclide mean std. dev.
|
||||
1 10000 1 total 5.709323e-08 4.687930e-09
|
||||
0 10000 2 total 2.855740e-06 2.442165e-07
|
||||
material group in nuclide mean std. dev.
|
||||
1 10000 1 total 0.019239 0.001310
|
||||
0 10000 2 total 0.466719 0.041411
|
||||
material group in nuclide mean std. dev.
|
||||
1 10001 1 total 0.313738 0.015582
|
||||
0 10001 2 total 0.300821 0.028052
|
||||
|
|
@ -152,6 +161,15 @@
|
|||
material group out nuclide mean std. dev.
|
||||
1 10001 1 total 0.0 0.0
|
||||
0 10001 2 total 0.0 0.0
|
||||
material group out nuclide mean std. dev.
|
||||
1 10001 1 total 0.0 0.0
|
||||
0 10001 2 total 0.0 0.0
|
||||
material group in nuclide mean std. dev.
|
||||
1 10001 1 total 5.995980e-08 4.553093e-09
|
||||
0 10001 2 total 2.985490e-06 3.417016e-07
|
||||
material group in nuclide mean std. dev.
|
||||
1 10001 1 total 0.0 0.0
|
||||
0 10001 2 total 0.0 0.0
|
||||
material group in nuclide mean std. dev.
|
||||
1 10002 1 total 0.664572 0.031215
|
||||
0 10002 2 total 2.052384 0.224343
|
||||
|
|
@ -229,3 +247,12 @@
|
|||
material group out nuclide mean std. dev.
|
||||
1 10002 1 total 0.0 0.0
|
||||
0 10002 2 total 0.0 0.0
|
||||
material group out nuclide mean std. dev.
|
||||
1 10002 1 total 0.0 0.0
|
||||
0 10002 2 total 0.0 0.0
|
||||
material group in nuclide mean std. dev.
|
||||
1 10002 1 total 6.022078e-08 3.780437e-09
|
||||
0 10002 2 total 3.044955e-06 3.600077e-07
|
||||
material group in nuclide mean std. dev.
|
||||
1 10002 1 total 0.0 0.0
|
||||
0 10002 2 total 0.0 0.0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
739796983940a1bad601998cf9ea2f90453a994477c7f675c2fd404d1864fe04a7fbfb5a15c5fe7cf9bad016b78432ba0910baba6f9cc026143761e9f526b62a
|
||||
e4a5f03ab6167e96462c4ef537533fe33b98d7878ae00824c5619356bda8d548b3c71af01ba8c88d5a9b46dd1471d331e6f678a164af922200f2ee3642be6340
|
||||
|
|
@ -1 +1 @@
|
|||
d56c6bae6bf3cd8950d3f50f089458c1c6c807be780fc97570532c6af6eb7e3057968d3345bd3c363f01315271129ef7b2ca028b05767353e601dc37b035f8a7
|
||||
e494320a213b5704a2ac915a2ba504857be91961ceb6735b6ad05d81eb31c44c9584d5bd9d40baececf1dcb5b030e6ecec63cfbd20639baf69bcb596c5c46591
|
||||
|
|
@ -1 +1 @@
|
|||
a392a7a8f27fd2f959b06a6809df29b3482e215da175b19846c248af44dc2ee7e2b05269b802dd9d6ed434506b05092f349436a0048411adab6b296dba0bd683
|
||||
ca47172a42f6c13b244a763c990cbe4811662708ee03307d810a4542ee34bb5db7cc29d66aea313dad95b9f38a4ff7943ded527cfd0c7c8825372fec40cfc0d0
|
||||
|
|
@ -1 +1 @@
|
|||
a0c7d6ca246ecd7dd5fed06373af142390971401c4e97744f29e55810ab9c231c97c4d8947cdf0b3d2df0ae829a9ddf768e5b2d889bbea34f2b6db0e567db884
|
||||
7d085e38f331083a8c3f7814eb6025f9457a1a8e3899e7d9a65af1ba92ea75c0182fcc605d4eadd3eb7edfc0949df688d39a3f45683e10cbdcfb6d7954f34129
|
||||
|
|
@ -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