Merge remote-tracking branch 'upstream/develop' into cmfd-omp

This commit is contained in:
Shikhar Kumar 2019-09-06 18:05:59 -04:00
commit 2c9a222536
121 changed files with 7573 additions and 6213 deletions

View file

@ -120,6 +120,11 @@ target_include_directories(pugixml PUBLIC vendor/pugixml/)
# xtensor header-only library
#===============================================================================
# CMake 3.13+ will complain about policy CMP0079 unless it is set explicitly
if (NOT (CMAKE_VERSION VERSION_LESS 3.13))
cmake_policy(SET CMP0079 NEW)
endif()
add_subdirectory(vendor/xtl)
add_subdirectory(vendor/xtensor)
target_link_libraries(xtensor INTERFACE xtl)

View file

@ -0,0 +1,9 @@
{{ fullname }}
{{ underline }}
.. currentmodule:: {{ module }}
.. autoclass:: {{ objname }}
:members:
:inherited-members:
:special-members: __call__, __len__, __iter__

View file

@ -1,28 +0,0 @@
.. _developers:
================
Development Team
================
The following people have contributed to development of the OpenMC Monte Carlo
code:
* `Paul Romano <https://github.com/paulromano>`_
* `Bryan Herman <https://github.com/bhermanmit>`_
* `Nick Horelik <https://github.com/nhorelik>`_
* `Adam Nelson <https://github.com/nelsonag>`_
* `Jon Walsh <https://github.com/walshjon>`_
* `Sterling Harper <https://github.com/smharper>`_
* `Will Boyd <https://github.com/wbinventor>`_
* `Samuel Shaner <https://github.com/samuelshaner>`_
* `Jingang Liang <https://github.com/liangjg>`_
* `Colin Josey <https://github.com/cjosey>`_
* `Amanda Lund <https://github.com/amandalund>`_
* `Guillaume Giudicelli <https://github.com/giudgiud>`_
* `Isaac Meyer <https://github.com/icmeyer>`_
* `Patrick Shriwise <https://github.com/pshriwise>`_
* `Shikhar Kumar <https://github.com/shikhar413>`_
* `Andrew Davis <https://github.com/makeclean>`_
* `Benoit Forget <http://web.mit.edu/nse/people/faculty/forget.html>`_
* `Kord Smith <http://web.mit.edu/nse/people/faculty/smith.html>`_
* `Andrew Siegel <http://www.mcs.anl.gov/person/andrew-siegel>`_

View file

@ -44,4 +44,3 @@ list <https://groups.google.com/forum/?fromgroups=#!forum/openmc-users>`_.
io_formats/index
publications
license
developers

View file

@ -4,7 +4,7 @@
License Agreement
=================
Copyright © 2011-2018 Massachusetts Institute of Technology and OpenMC contributors
Copyright © 2011-2019 Massachusetts Institute of Technology and OpenMC contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View file

@ -57,6 +57,9 @@ Benchmarking
Coupling and Multi-physics
--------------------------
- Miriam A. Kreher, Benoit Forget, and Kord Smith, "Single-Batch Monte Carlo
Multiphysics Coupling," *Proc. M&C*, Portland, Oregon, Aug. 25-29 (2019).
- Ze-Long Zhao, Yongwei Yang, and Shuang Hong, "`Application of FLUKA and OpenMC
in coupled physics calculation of target and subcritical reactor for ADS
<https://doi.org/10.1007/s41365-018-0539-1>`_," *Nucl. Sci. Tech.*, **30**: 10
@ -113,6 +116,10 @@ Coupling and Multi-physics
Geometry and Visualization
--------------------------
- Sterling Harper, Paul Romano, Benoit Forget, and Kord Smith, "Efficient
dynamic threadsafe neighbor lists for Monte Carlo ray tracing," *Proc. M&C*,
Portland, Oregon, Aug. 25-29 (2019).
- Jin-Yang Li, Long Gu, Hu-Shan Xu, Nadezha Korepanova, Rui Yu, Yan-Lei Zhu, and
Chang-Ping Qin, "`CAD modeling study on FLUKA and OpenMC for accelerator
driven system simulation <https://doi.org/10.1016/j.anucene.2017.12.050>`_",
@ -303,6 +310,11 @@ Multigroup Cross Section Generation
Doppler Broadening
------------------
- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, and Forrest B. Brown,
"`On-the-fly Doppler broadening of unresolved resonance region cross sections
<https://doi.org/10.1016/j.pnucene.2017.05.032>`_," *Prog. Nucl. Energy*,
**101**, 444-460 (2017).
- Colin Josey, Pablo Ducru, Benoit Forget, and Kord Smith, "`Windowed multipole
for cross section Doppler broadening
<https://doi.org/10.1016/j.jcp.2015.08.013>`_," *J. Comput. Phys.*, **307**,
@ -313,6 +325,12 @@ Doppler Broadening
via Probability Band Interpolation," *Proc. PHYSOR*, Sun Valley, Idaho, May
1-5, 2016.
- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, Brian C. Kiedrowski, and
Forrest B. Brown, "`Direct, on-the-fly calculation of unresolved resonance
region cross sections in Monte Carlo simulations
<http://hdl.handle.net/1721.1/108644>`_," *Proc. Joint Int. Conf. M&C+SNA+MC*,
Nashville, Tennessee, Apr. 19--23 (2015).
- Colin Josey, Benoit Forget, and Kord Smith, "`Windowed multipole sensitivity
to target accuracy of the optimization procedure
<https://doi.org/10.1080/00223131.2015.1035353>`_,"
@ -366,11 +384,6 @@ Nuclear Data
<https://doi.org/10.1016/j.cpc.2015.05.025>`_", *Comput. Phys. Commun.*,
**196**, 134-142 (2015).
- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, Brian C. Kiedrowski, and
Forrest B. Brown, "Direct, on-the-fly calculation of unresolved resonance
region cross sections in Monte Carlo simulations," *Proc. Joint
Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015).
- Amanda L. Lund, Andrew R. Siegel, Benoit Forget, Colin Josey, and
Paul K. Romano, "Using fractional cascading to accelerate cross section
lookups in Monte Carlo particle transport calculations," *Proc. Joint
@ -481,6 +494,10 @@ Parallelism
Depletion
---------
- Jose L. Salcedo-Perez, Benoit Forget, Kord Smith, and Paul Romano, "Hybrid
tallies to improve performance in depletion Monte Carlo simulations," *Proc.
M&C*, Aug. 25-29 (2019).
- Zhao-Qing Liu, Ze-Long Zhao, Yong-Wei Yang, Yu-Cui Gao, Hai-Yan Meng, and
Qing-Yu Gao, "`Development and validation of depletion code system IMPC-Burnup
for ADS <https://doi.org/10.1007/s41365-019-0560-z>`_," *Nucl. Sci. Tech.*,

View file

@ -6,26 +6,26 @@
.. module:: openmc.deplete
Several functions are provided that implement different time-integration
Several classes are provided that implement different time-integration
algorithms for depletion calculations, which are described in detail in Colin
Josey's thesis, `Development and analysis of high order neutron
transport-depletion coupling algorithms <http://hdl.handle.net/1721.1/113721>`_.
.. autosummary::
:toctree: generated
:nosignatures:
:template: myfunction.rst
:toctree: generated
:nosignatures:
:template: myintegrator.rst
integrator.predictor
integrator.cecm
integrator.celi
integrator.leqi
integrator.cf4
integrator.epc_rk4
integrator.si_celi
integrator.si_leqi
PredictorIntegrator
CECMIntegrator
CELIIntegrator
CF4Integrator
EPCRK4Integrator
LEQIIntegrator
SICELIIntegrator
SILEQIIntegrator
Each of these functions expects a "transport operator" to be passed. An operator
Each of these classes expects a "transport operator" to be passed. An operator
specific to OpenMC is available using the following class:
.. autosummary::
@ -65,6 +65,8 @@ for a depletion chain:
DecayTuple
Nuclide
ReactionTuple
FissionYieldDistribution
FissionYield
The following classes are used during a depletion simulation and store auxiliary
data, such as number densities and reaction rates for each material.
@ -75,13 +77,25 @@ data, such as number densities and reaction rates for each material.
:template: myclass.rst
AtomNumber
ChainFissionHelper
DirectReactionRateHelper
OperatorResult
ReactionRates
Results
ResultsList
The following classes are used to help the :class:`openmc.deplete.Operator`
compute quantities like effective fission yields, reaction rates, and
total system energy.
.. autosummary::
:toctree: generated
:nosignatures:
:template: myclass.rst
helpers.AveragedFissionYieldHelper
helpers.ChainFissionHelper
helpers.ConstantFissionYieldHelper
helpers.DirectReactionRateHelper
helpers.FissionYieldCutoffHelper
The following classes are abstract classes that can be used to extend the
:mod:`openmc.deplete` capabilities:
@ -91,11 +105,24 @@ The following classes are abstract classes that can be used to extend the
:nosignatures:
:template: myclass.rst
ReactionRateHelper
EnergyHelper
FissionYieldHelper
ReactionRateHelper
TalliedFissionYieldHelper
TransportOperator
Each of the integrator functions also relies on a number of "helper" functions
Custom integrators can be developed by subclassing from the following abstract
base classes:
.. autosummary::
:toctree: generated
:nosignatures:
:template: myintegrator.rst
Integrator
SIIntegrator
Each of the integrator classes also relies on a number of "helper" functions
as follows:
.. autosummary::
@ -103,5 +130,5 @@ as follows:
:nosignatures:
:template: myfunction.rst
integrator.CRAM16
integrator.CRAM48
cram.CRAM16
cram.CRAM48

View file

@ -25,7 +25,7 @@ surface is a locus of zeros of a function of Cartesian coordinates
Defining a surface alone is not sufficient to specify a volume -- in order to
define an actual volume, one must reference the *half-space* of a surface. A
surface half-space is the region whose points satisfy a positive of negative
surface half-space is the region whose points satisfy a positive or negative
inequality of the surface equation. For example, for a sphere of radius one
centered at the origin, the surface equation is :math:`f(x,y,z) = x^2 + y^2 +
z^2 - 1 = 0`. Thus, we say that the negative half-space of the sphere, is

View file

@ -106,6 +106,37 @@ Compton profile data using an existing data library from `Geant4
<http://geant4.cern.ch/>`_. Note that OpenMC includes this data file by default
so it should not be necessary in practice to generate it yourself.
.. _scripts_depletion_chain:
-------------------------------
``openmc-make-depletion-chain``
-------------------------------
This script generates a depletion chain file called ``chain_endfb71.xml``
using ENDF/B-VII.1 nuclear data. If the :envvar:`OPENMC_ENDF_DATA` variable
is not set, and ``"neutron"``, ``"decay"``, ``"nfy"`` directories
do not exist, then ENDF/B-VII.1 data will be downloaded.
.. _scripts_depletion_chain_casl:
------------------------------------
``openmc-make-depletion-chain-casl``
------------------------------------
This script generates a depletion chain called ``chain_casl.xml``
using ENDF/B-VII.1 nuclear data for a simplified chain.
The nuclides were chosen by CASL-ORIGEN, which can be found in
Appendix A of Kang Seog Kim, `"Specification for the VERA Depletion
Benchmark Suite" <https://doi.org/10.2172/1256820>`_,
CASL-U-2015-1014-000, Rev. 0, ORNL/TM-2016/53, 2016.
``Te129`` has been added into this chain due to its link to
``I129`` production.
If the :envvar:`OPENMC_ENDF_DATA` variable is not set,
and ``"neutron"``, ``"decay"``, ``"nfy"`` directories
to not exist, then ENDF/B-VII.1 data will be downloaded.
.. _scripts_stopping:
-------------------------------

View file

@ -21,6 +21,10 @@ extern "C" {
int openmc_cell_set_temperature(int32_t index, double T, const int32_t* instance);
int openmc_energy_filter_get_bins(int32_t index, const double** energies, size_t* n);
int openmc_energy_filter_set_bins(int32_t index, size_t n, const double* energies);
int openmc_energyfunc_filter_get_energy(int32_t index, size_t* n, const double** energy);
int openmc_energyfunc_filter_get_y(int32_t index, size_t* n, const double** y);
int openmc_energyfunc_filter_set_data(int32_t index, size_t n,
const double* energies, const double* y);
int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end);

View file

@ -126,6 +126,12 @@ namespace data {
extern std::array<double, 2> energy_min;
extern std::array<double, 2> energy_max;
//! Minimum temperature in [K] that nuclide data is available at
extern double temperature_min;
//! Maximum temperature in [K] that nuclide data is available at
extern double temperature_max;
extern std::vector<std::unique_ptr<Nuclide>> nuclides;
extern std::unordered_map<std::string, int> nuclide_map;

View file

@ -40,6 +40,13 @@ public:
std::string text_label(int bin) const override;
//----------------------------------------------------------------------------
// Accessors
const std::vector<double>& energy() const { return energy_; }
const std::vector<double>& y() const { return y_; }
void set_data(gsl::span<const double> energy, gsl::span<const double> y);
private:
//----------------------------------------------------------------------------
// Data members

View file

@ -54,7 +54,7 @@ Indicates the default path to an HDF5 file that contains multi-group cross
section libraries if the user has not specified the <cross_sections> tag in
.I materials.xml\fP.
.SH LICENSE
Copyright \(co 2011-2018 Massachusetts Institute of Technology and OpenMC
Copyright \(co 2011-2019 Massachusetts Institute of Technology and OpenMC
contributors.
.PP
Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -34,6 +34,18 @@ _dll.openmc_energy_filter_get_bins.errcheck = _error_handler
_dll.openmc_energy_filter_set_bins.argtypes = [c_int32, c_size_t, POINTER(c_double)]
_dll.openmc_energy_filter_set_bins.restype = c_int
_dll.openmc_energy_filter_set_bins.errcheck = _error_handler
_dll.openmc_energyfunc_filter_set_data.restype = c_int
_dll.openmc_energyfunc_filter_set_data.errcheck = _error_handler
_dll.openmc_energyfunc_filter_set_data.argtypes = [
c_int32, c_size_t, POINTER(c_double), POINTER(c_double)]
_dll.openmc_energyfunc_filter_get_energy.resttpe = c_int
_dll.openmc_energyfunc_filter_get_energy.errcheck = _error_handler
_dll.openmc_energyfunc_filter_get_energy.argtypes = [
c_int32, POINTER(c_size_t), POINTER(POINTER(c_double))]
_dll.openmc_energyfunc_filter_get_y.resttpe = c_int
_dll.openmc_energyfunc_filter_get_y.errcheck = _error_handler
_dll.openmc_energyfunc_filter_get_y.argtypes = [
c_int32, POINTER(c_size_t), POINTER(POINTER(c_double))]
_dll.openmc_filter_get_id.argtypes = [c_int32, POINTER(c_int32)]
_dll.openmc_filter_get_id.restype = c_int
_dll.openmc_filter_get_id.errcheck = _error_handler
@ -201,6 +213,48 @@ class DistribcellFilter(Filter):
class EnergyFunctionFilter(Filter):
filter_type = 'energyfunction'
def __new__(cls, energy=None, y=None, uid=None, new=True, index=None):
return super().__new__(cls, uid=uid, new=new, index=index)
def __init__(self, energy=None, y=None, uid=None, new=True, index=None):
if (energy is None) != (y is None):
raise AttributeError("Need both energy and y or neither")
super().__init__(uid, new, index)
if energy is not None:
self.set_data(energy, y)
def set_data(self, energy, y):
"""Set the interpolation information for the filter
Parameters
----------
energy : numpy.ndarray
Independent variable for the interpolation
y : numpy.ndarray
Dependent variable for the interpolation
"""
energy_array = np.asarray(energy)
y_array = np.asarray(y)
energy_p = energy_array.ctypes.data_as(POINTER(c_double))
y_p = y_array.ctypes.data_as(POINTER(c_double))
_dll.openmc_energyfunc_filter_set_data(
self._index, len(energy_array), energy_p, y_p)
@property
def energy(self):
return self._get_attr(_dll.openmc_energyfunc_filter_get_energy)
@property
def y(self):
return self._get_attr(_dll.openmc_energyfunc_filter_get_y)
def _get_attr(self, cfunc):
array_p = POINTER(c_double)()
n = c_size_t()
cfunc(self._index, n, array_p)
return as_array(array_p, (n.value, ))
class LegendreFilter(Filter):
filter_type = 'legendre'

View file

@ -358,7 +358,12 @@ def zam(name):
symbol, A, state = _GND_NAME_RE.match(name).groups()
except AttributeError:
raise ValueError("'{}' does not appear to be a nuclide name in GND "
"format.".format(name))
"format".format(name))
if symbol not in ATOMIC_NUMBER:
raise ValueError("'{}' is not a recognized element symbol"
.format(symbol))
metastable = int(state[2:]) if state else 0
return (ATOMIC_NUMBER[symbol], int(A), metastable)

View file

@ -1,11 +1,9 @@
import sys
from collections import OrderedDict
from collections.abc import Iterable, Mapping, MutableMapping
from collections.abc import Mapping, MutableMapping
from io import StringIO
from math import log10
from numbers import Integral, Real
import os
import shutil
import tempfile
from warnings import warn
@ -15,7 +13,8 @@ import h5py
from . import HDF5_VERSION, HDF5_VERSION_MAJOR
from .ace import Library, Table, get_table, get_metadata
from .data import ATOMIC_SYMBOL, K_BOLTZMANN, EV_PER_MEV
from .endf import Evaluation, SUM_RULES, get_head_record, get_tab1_record
from .endf import (
Evaluation, SUM_RULES, get_head_record, get_tab1_record, get_evaluations)
from .fission_energy import FissionEnergyRelease
from .function import Tabulated1D, Sum, ResonancesWithBackground
from .grid import linearize, thin
@ -453,7 +452,7 @@ class IncidentNeutron(EqualityMixin):
if rx.redundant:
photon_rx = any(p.particle == 'photon' for p in rx.products)
keep_mts = (4, 16, 103, 104, 105, 106, 107,
203, 204, 205, 206, 207, 301, 444)
203, 204, 205, 206, 207, 301, 318, 444)
if not (photon_rx or rx.mt in keep_mts):
continue
@ -554,6 +553,20 @@ class IncidentNeutron(EqualityMixin):
fer_group = group['fission_energy_release']
data.fission_energy = FissionEnergyRelease.from_hdf5(fer_group)
# Rebuild non-fission heating
total_heating = data.reactions.get(301)
fission_heating = data.reactions.get(318)
if total_heating is not None and fission_heating is not None:
non_fission_heating = Reaction(999)
non_fission_heating.redundant = True
for strT, total in total_heating.xs.items():
fission = fission_heating.xs.get(strT)
if fission is None:
continue
non_fission_heating.xs[strT] = Tabulated1D(
total.x, total.y - fission(total.x))
data.reactions[999] = non_fission_heating
return data
@classmethod
@ -801,14 +814,14 @@ class IncidentNeutron(EqualityMixin):
"""
with tempfile.TemporaryDirectory() as tmpdir:
# Run NJOY to create an ACE library
kwargs.setdefault('ace', os.path.join(tmpdir, 'ace'))
kwargs.setdefault('xsdir', os.path.join(tmpdir, 'xsdir'))
kwargs.setdefault('pendf', os.path.join(tmpdir, 'pendf'))
kwargs.setdefault("output_dir", tmpdir)
for key in ("acer", "pendf", "heatr", "broadr", "gaspr", "purr"):
kwargs.setdefault(key, os.path.join(kwargs["output_dir"], key))
kwargs['evaluation'] = evaluation
make_ace(filename, temperatures, **kwargs)
# Create instance from ACE tables within library
lib = Library(kwargs['ace'])
lib = Library(kwargs['acer'])
data = cls.from_ace(lib.tables[0])
for table in lib.tables[1:]:
data.add_temperature_from_ace(table)
@ -817,6 +830,29 @@ class IncidentNeutron(EqualityMixin):
ev = evaluation if evaluation is not None else Evaluation(filename)
if (1, 458) in ev.section:
data.fission_energy = FissionEnergyRelease.from_endf(ev, data)
# Add 318 fission heating data from heatr
non_fission_heating = Reaction(999)
non_fission_heating.redundant = True
fission_heating = Reaction(318)
heatr_evals = get_evaluations(kwargs["heatr"])
for heatr in heatr_evals:
temp = "{}K".format(round(heatr.target["temperature"]))
f318 = StringIO(heatr.section[3, 318])
get_head_record(f318)
_params, fission_kerma = get_tab1_record(f318)
fission_heating.xs[temp] = fission_kerma
total_heating_xs = data.reactions[301].xs.get(temp)
if total_heating_xs is None:
continue
non_fission_heating.xs[temp] = Tabulated1D(
fission_kerma.x,
total_heating_xs(fission_kerma.x) - fission_kerma.y,
breakpoints=fission_kerma.breakpoints,
interpolation=fission_kerma.interpolation)
data.reactions[318] = fission_heating
data.reactions[999] = non_fission_heating
# Add 0K elastic scattering cross section
if '0K' not in data.energy:

View file

@ -1,11 +1,10 @@
import argparse
from collections import namedtuple
from io import StringIO
import os
import shutil
from subprocess import Popen, PIPE, STDOUT, CalledProcessError
import sys
import tempfile
from pathlib import Path
from . import endf
@ -215,11 +214,21 @@ def make_pendf(filename, pendf='pendf', error=0.001, stdout=False):
heatr=False, purr=False, acer=False, stdout=stdout)
def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
error=0.001, broadr=True, heatr=True, gaspr=True, purr=True,
acer=True, evaluation=None, **kwargs):
def make_ace(filename, temperatures=None, acer=True, xsdir=None,
output_dir=None, pendf=False, error=0.001, broadr=True,
heatr=True, gaspr=True, purr=True, evaluation=None,
**kwargs):
"""Generate incident neutron ACE file from an ENDF file
File names can be passed to
``[acer, xsdir, pendf, broadr, heatr, gaspr, purr]``
to specify the exact output for the given module.
Otherwise, the files will be writen to the current directory
or directory specified by ``output_dir``. Default file
names mirror the variable names, e.g. ``heatr`` output
will be written to a file named ``heatr`` unless otherwise
specified.
Parameters
----------
filename : str
@ -227,24 +236,34 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
temperatures : iterable of float, optional
Temperatures in Kelvin to produce ACE files at. If omitted, data is
produced at room temperature (293.6 K).
ace : str, optional
Path of ACE file to write
acer : bool or str, optional
Flag indicating if acer should be run. If a string is give, write the
resulting ``ace`` file to this location. Path of ACE file to write.
Defaults to ``"ace"``
xsdir : str, optional
Path of xsdir file to write
Path of xsdir file to write. Defaults to ``"xsdir"`` in the same
directory as ``acer``
output_dir : str, optional
Directory to write output for requested modules. If not provided
and at least one of ``[pendf, broadr, heatr, gaspr, purr, acer]``
is ``True``, then write output files to current directory. If given,
must be a path to a directory.
pendf : str, optional
Path of pendf file to write. If omitted, the pendf file is not saved.
error : float, optional
Fractional error tolerance for NJOY processing
broadr : bool, optional
Indicating whether to Doppler broaden XS when running NJOY
heatr : bool, optional
Indicating whether to add heating kerma when running NJOY
gaspr : bool, optional
Indicating whether to add gas production data when running NJOY
purr : bool, optional
Indicating whether to add probability table when running NJOY
acer : bool, optional
Indicating whether to generate ACE file when running NJOY
broadr : bool or str, optional
Indicating whether to Doppler broaden XS when running NJOY. If string,
write the output tape to this file.
heatr : bool or str, optional
Indicating whether to add heating kerma when running NJOY. If string,
write the output tape to this file.
gaspr : bool or str, optional
Indicating whether to add gas production data when running NJOY.
If string, write the output tape to this file.
purr : bool or str, optional
Indicating whether to add probability table when running NJOY.
If string, write the output tape to this file.
evaluation : openmc.data.endf.Evaluation, optional
If the ENDF file contains multiple material evaluations, this argument
indicates which evaluation should be used.
@ -255,8 +274,17 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
------
subprocess.CalledProcessError
If the NJOY process returns with a non-zero status
IOError
If ``output_dir`` does not point to a directory
"""
if output_dir is None:
output_dir = Path()
else:
output_dir = Path(output_dir)
if not output_dir.is_dir():
raise IOError("{} is not a directory".format(output_dir))
ev = evaluation if evaluation is not None else endf.Evaluation(filename)
mat = ev.material
zsymam = ev.target['zsymam']
@ -275,8 +303,8 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
nendf, npendf = 20, 21
tapein = {nendf: filename}
tapeout = {}
if pendf is not None:
tapeout[npendf] = pendf
if pendf:
tapeout[npendf] = (output_dir / "pendf") if pendf is True else pendf
# reconr
commands += _TEMPLATE_RECONR
@ -285,6 +313,7 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
# broadr
if broadr:
nbroadr = nlast + 1
tapeout[nbroadr] = (output_dir / "broadr") if broadr is True else broadr
commands += _TEMPLATE_BROADR
nlast = nbroadr
@ -292,6 +321,7 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
if heatr:
nheatr_in = nlast
nheatr = nheatr_in + 1
tapeout[nheatr] = (output_dir / "heatr") if heatr is True else heatr
commands += _TEMPLATE_HEATR
nlast = nheatr
@ -299,6 +329,7 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
if gaspr:
ngaspr_in = nlast
ngaspr = ngaspr_in + 1
tapeout[ngaspr] = (output_dir / "gaspr") if gaspr is True else gaspr
commands += _TEMPLATE_GASPR
nlast = ngaspr
@ -306,6 +337,7 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
if purr:
npurr_in = nlast
npurr = npurr_in + 1
tapeout[npurr] = (output_dir / "purr") if purr is True else purr
commands += _TEMPLATE_PURR
nlast = npurr
@ -323,19 +355,21 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
commands += _TEMPLATE_ACER.format(**locals())
# Indicate tapes to save for each ACER run
tapeout[nace] = fname.format(ace, temperature)
tapeout[ndir] = fname.format(xsdir, temperature)
tapeout[nace] = fname.format("ace", temperature)
tapeout[ndir] = fname.format("xsdir", temperature)
commands += 'stop\n'
run(commands, tapein, tapeout, **kwargs)
if acer:
with open(ace, 'w') as ace_file, open(xsdir, 'w') as xsdir_file:
ace = (output_dir / "ace") if acer is True else Path(acer)
xsdir = (ace.parent / "xsdir") if xsdir is None else xsdir
with ace.open('w') as ace_file, xsdir.open('w') as xsdir_file:
for temperature in temperatures:
# Get contents of ACE file
text = open(fname.format(ace, temperature), 'r').read()
text = open(fname.format("ace", temperature), 'r').read()
# If the target is metastable, make sure that ZAID in the ACE file reflects
# this by adding 400
# If the target is metastable, make sure that ZAID in the ACE
# file reflects this by adding 400
if ev.target['isomeric_state'] > 0:
mass_first_digit = int(text[3])
if mass_first_digit <= 2:
@ -345,13 +379,13 @@ def make_ace(filename, temperatures=None, ace='ace', xsdir='xsdir', pendf=None,
ace_file.write(text)
# Concatenate into destination xsdir file
text = open(fname.format(xsdir, temperature), 'r').read()
text = open(fname.format("xsdir", temperature), 'r').read()
xsdir_file.write(text)
# Remove ACE/xsdir files for each temperature
for temperature in temperatures:
os.remove(fname.format(ace, temperature))
os.remove(fname.format(xsdir, temperature))
os.remove(fname.format("ace", temperature))
os.remove(fname.format("xsdir", temperature))
def make_ace_thermal(filename, filename_thermal, temperatures=None,

View file

@ -54,6 +54,7 @@ REACTION_NAME = {1: '(n,total)', 2: '(n,elastic)', 4: '(n,level)',
198: '(n,n3p)', 199: '(n,3n2pa)', 200: '(n,5n2p)', 203: '(n,Xp)',
204: '(n,Xd)', 205: '(n,Xt)', 206: '(n,X3He)', 207: '(n,Xa)',
301: 'heating', 444: 'damage-energy',
318: "fission-heating", 999: "non-fission-heating",
649: '(n,pc)', 699: '(n,dc)', 749: '(n,tc)', 799: '(n,3Hec)',
849: '(n,ac)', 891: '(n,2nc)'}
REACTION_NAME.update({i: '(n,n{})'.format(i - 50) for i in range(50, 91)})

View file

@ -38,4 +38,4 @@ from .reaction_rates import *
from .abc import *
from .results import *
from .results_list import *
from .integrator import *
from .integrators import *

View file

@ -0,0 +1,80 @@
"""Functions to form the special matrix for depletion"""
def celi_f1(chain, rates, fission_yields=None):
return (5 / 12 * chain.form_matrix(rates[0], fission_yields)
+ 1 / 12 * chain.form_matrix(rates[1], fission_yields))
def celi_f2(chain, rates, fission_yields=None):
return (1 / 12 * chain.form_matrix(rates[0], fission_yields)
+ 5 / 12 * chain.form_matrix(rates[1], fission_yields))
def cf4_f1(chain, rates, fission_yields=None):
return 1 / 2 * chain.form_matrix(rates, fission_yields)
def cf4_f2(chain, rates, fission_yields=None):
return (-1 / 2 * chain.form_matrix(rates[0], fission_yields)
+ chain.form_matrix(rates[1], fission_yields))
def cf4_f3(chain, rates, fission_yields=None):
return (1 / 4 * chain.form_matrix(rates[0], fission_yields)
+ 1 / 6 * chain.form_matrix(rates[1], fission_yields)
+ 1 / 6 * chain.form_matrix(rates[2], fission_yields)
- 1 / 12 * chain.form_matrix(rates[3], fission_yields))
def cf4_f4(chain, rates, fission_yields=None):
return (-1 / 12 * chain.form_matrix(rates[0], fission_yields)
+ 1 / 6 * chain.form_matrix(rates[1], fission_yields)
+ 1 / 6 * chain.form_matrix(rates[2], fission_yields)
+ 1 / 4 * chain.form_matrix(rates[3], fission_yields))
def rk4_f1(chain, rates, fission_yields=None):
return 1 / 2 * chain.form_matrix(rates, fission_yields)
def rk4_f4(chain, rates, fission_yields=None):
return (1 / 6 * chain.form_matrix(rates[0], fission_yields)
+ 1 / 3 * chain.form_matrix(rates[1], fission_yields)
+ 1 / 3 * chain.form_matrix(rates[2], fission_yields)
+ 1 / 6 * chain.form_matrix(rates[3], fission_yields))
def leqi_f1(chain, inputs, fission_yields):
f1 = chain.form_matrix(inputs[0], fission_yields)
f2 = chain.form_matrix(inputs[1], fission_yields)
dt_l, dt = inputs[2], inputs[3]
return -dt / (12 * dt_l) * f1 + (dt + 6 * dt_l) / (12 * dt_l) * f2
def leqi_f2(chain, inputs, fission_yields=None):
f1 = chain.form_matrix(inputs[0], fission_yields)
f2 = chain.form_matrix(inputs[1], fission_yields)
dt_l, dt = inputs[2], inputs[3]
return -5 * dt / (12 * dt_l) * f1 + (5 * dt + 6 * dt_l) / (12 * dt_l) * f2
def leqi_f3(chain, inputs, fission_yields=None):
f1 = chain.form_matrix(inputs[0], fission_yields)
f2 = chain.form_matrix(inputs[1], fission_yields)
f3 = chain.form_matrix(inputs[2], fission_yields)
dt_l, dt = inputs[3], inputs[4]
return (-dt ** 2 / (12 * dt_l * (dt + dt_l)) * f1
+ (dt ** 2 + 6 * dt * dt_l + 5 * dt_l ** 2)
/ (12 * dt_l * (dt + dt_l)) * f2 + dt_l / (12 * (dt + dt_l)) * f3)
def leqi_f4(chain, inputs, fission_yields=None):
f1 = chain.form_matrix(inputs[0], fission_yields)
f2 = chain.form_matrix(inputs[1], fission_yields)
f3 = chain.form_matrix(inputs[2], fission_yields)
dt_l, dt = inputs[3], inputs[4]
return (-dt ** 2 / (12 * dt_l * (dt + dt_l)) * f1
+ (dt ** 2 + 2 * dt * dt_l + dt_l ** 2)
/ (12 * dt_l * (dt + dt_l)) * f2
+ (4 * dt * dt_l + 5 * dt_l ** 2) / (12 * dt_l * (dt + dt_l)) * f3)

View file

@ -5,18 +5,23 @@ to run a full depletion simulation.
"""
from collections import namedtuple
from collections.abc import Iterable
import os
from pathlib import Path
from abc import ABC, abstractmethod
from xml.etree import ElementTree as ET
from copy import deepcopy
from warnings import warn
from numbers import Real
from numbers import Real, Integral
from numpy import nonzero, empty
from numpy import nonzero, empty, asarray
from uncertainties import ufloat
from openmc.data import DataLibrary, JOULE_PER_EV
from openmc.capi import MaterialFilter, Tally
from openmc.checkvalue import check_type, check_greater_than
from .results import Results
from .chain import Chain
from .results_list import ResultsList
OperatorResult = namedtuple('OperatorResult', ['k', 'rates'])
OperatorResult.__doc__ = """\
@ -24,8 +29,8 @@ Result of applying transport operator
Parameters
----------
k : float
Resulting eigenvalue
k : uncertainties.ufloat
Resulting eigenvalue and standard deviation
rates : openmc.deplete.ReactionRates
Resulting reaction rates
@ -43,8 +48,8 @@ class TransportOperator(ABC):
Each depletion integrator is written to work with a generic transport
operator that takes a vector of material compositions and returns an
eigenvalue and reaction rates. This abstract class sets the requirements for
such a transport operator. Users should instantiate
eigenvalue and reaction rates. This abstract class sets the requirements
for such a transport operator. Users should instantiate
:class:`openmc.deplete.Operator` rather than this class.
Parameters
@ -61,6 +66,8 @@ class TransportOperator(ABC):
in initial condition to ensure they exist in the decay chain.
Only done for nuclides with reaction rates.
Defaults to 1.0e3.
prev_results : ResultsList, optional
Results from a previous depletion calculation.
Attributes
----------
@ -68,8 +75,12 @@ class TransportOperator(ABC):
Initial atom density [atoms/cm^3] to add for nuclides that are zero
in initial condition to ensure they exist in the decay chain.
Only done for nuclides with reaction rates.
prev_res : ResultsList or None
Results from a previous depletion calculation. ``None`` if no
results are to be used.
"""
def __init__(self, chain_file=None, fission_q=None, dilute_initial=1.0e3):
def __init__(self, chain_file=None, fission_q=None, dilute_initial=1.0e3,
prev_results=None):
self.dilute_initial = dilute_initial
self.output_dir = '.'
@ -93,6 +104,11 @@ class TransportOperator(ABC):
"of adding depletion_chain to OPENMC_CROSS_SECTIONS",
FutureWarning)
self.chain = Chain.from_xml(chain_file, fission_q)
if prev_results is None:
self.prev_res = None
else:
check_type("previous results", prev_results, ResultsList)
self.prev_results = prev_results
@property
def dilute_initial(self):
@ -106,15 +122,15 @@ class TransportOperator(ABC):
self._dilute_initial = value
@abstractmethod
def __call__(self, vec, print_out=True):
def __call__(self, vec, power):
"""Runs a simulation.
Parameters
----------
vec : list of numpy.ndarray
Total atoms to be used in function.
print_out : bool, optional
Whether or not to print out time.
power : float
Power of the reactor in [W]
Returns
-------
@ -122,7 +138,6 @@ class TransportOperator(ABC):
Eigenvalue and reaction rates resulting from transport operator
"""
pass
def __enter__(self):
# Save current directory and move to specific output directory
@ -157,8 +172,6 @@ class TransportOperator(ABC):
Total density for initial conditions.
"""
pass
@abstractmethod
def get_results_info(self):
"""Returns volume list, cell lists, and nuc lists.
@ -170,16 +183,28 @@ class TransportOperator(ABC):
nuc_list : list of str
A list of all nuclide names. Used for sorting the simulation.
burn_list : list of int
A list of all cell IDs to be burned. Used for sorting the simulation.
A list of all cell IDs to be burned. Used for sorting the
simulation.
full_burn_list : list of int
All burnable materials in the geometry.
"""
pass
def finalize(self):
pass
@abstractmethod
def write_bos_data(self, step):
"""Document beginning of step data for a given step
Called at the beginning of a depletion step and at
the final point in the simulation.
Parameters
----------
step : int
Current depletion step including restarts
"""
class ReactionRateHelper(ABC):
"""Abstract class for generating reaction rates for operators
@ -246,7 +271,8 @@ class ReactionRateHelper(ABC):
Parameters
----------
number : iterable of float
Number density [atoms/b-cm] of each nuclide tracked in the calculation.
Number density [atoms/b-cm] of each nuclide tracked in the
calculation.
Returns
-------
@ -337,3 +363,482 @@ class EnergyHelper(ABC):
def nuclides(self, nuclides):
check_type("nuclides", nuclides, list, str)
self._nuclides = nuclides
class FissionYieldHelper(ABC):
"""Abstract class for processing energy dependent fission yields
Parameters
----------
chain_nuclides : iterable of openmc.deplete.Nuclide
Nuclides tracked in the depletion chain. All nuclides are
not required to have fission yield data.
Attributes
----------
constant_yields : dict of str to :class:`openmc.deplete.FissionYield`
Fission yields for all nuclides that only have one set of
fission yield data. Can be accessed as ``{parent: {product: yield}}``
"""
def __init__(self, chain_nuclides):
self._chain_nuclides = {}
self._constant_yields = {}
# Get all nuclides with fission yield data
for nuc in chain_nuclides:
if nuc.yield_data is None:
continue
if len(nuc.yield_data) == 1:
self._constant_yields[nuc.name] = (
nuc.yield_data[nuc.yield_energies[0]])
elif len(nuc.yield_data) > 1:
self._chain_nuclides[nuc.name] = nuc
self._chain_set = set(self._chain_nuclides) | set(self._constant_yields)
@property
def constant_yields(self):
return deepcopy(self._constant_yields)
@abstractmethod
def weighted_yields(self, local_mat_index):
"""Return fission yields for a specific material
Parameters
----------
local_mat_index : int
Index for material tracked on this process that
exists in :attr:`local_mat_index` and fits within
the first axis in :attr:`results`
Returns
-------
library : dict
Dictionary of ``{parent: {product: fyield}}``
"""
@staticmethod
def unpack():
"""Unpack tally data prior to compute fission yields.
Called after a :meth:`openmc.deplete.Operator.__call__`
routine during the normalization of reaction rates.
Not necessary for all subclasses to implement, unless tallies
are used.
"""
@staticmethod
def generate_tallies(materials, mat_indexes):
"""Construct tallies necessary for computing fission yields
Called during the operator set up phase prior to depleting.
Not necessary for subclasses to implement
Parameters
----------
materials : iterable of C-API materials
Materials to be used in :class:`openmc.capi.MaterialFilter`
mat_indexes : iterable of int
Indices of tallied materials that will have their fission
yields computed by this helper. Necessary as the
:class:`openmc.deplete.Operator` that uses this helper
may only burn a subset of all materials when running
in parallel mode.
"""
def update_tally_nuclides(self, nuclides):
"""Return nuclides with non-zero densities and yield data
Parameters
----------
nuclides : iterable of str
Nuclides with non-zero densities from the
:class:`openmc.deplete.Operator`
Returns
-------
nuclides : list of str
Union of nuclides that the :class:`openmc.deplete.Operator`
says have non-zero densities at this stage and those that
have yield data. Sorted by nuclide name
"""
return sorted(self._chain_set & set(nuclides))
@classmethod
def from_operator(cls, operator, **kwargs):
"""Create a new instance by pulling data from the operator
All keyword arguments should be identical to their counterpart
in the main ``__init__`` method
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator with a depletion chain
kwargs: optional
Additional keyword arguments to be used in constuction
"""
return cls(operator.chain.nuclides, **kwargs)
class TalliedFissionYieldHelper(FissionYieldHelper):
"""Abstract class for computing fission yields with tallies
Generates a basic fission rate tally in all burnable materials with
:meth:`generate_tallies`, and set nuclides to be tallied with
:meth:`update_tally_nuclides`. Subclasses will need to implement
:meth:`unpack` and :meth:`weighted_yields`.
Parameters
----------
chain_nuclides : iterable of openmc.deplete.Nuclide
Nuclides tracked in the depletion chain. Not necessary
that all have yield data.
Attributes
----------
constant_yields : dict of str to :class:`openmc.deplete.FissionYield`
Fission yields for all nuclides that only have one set of
fission yield data. Can be accessed as ``{parent: {product: yield}}``
results : None or numpy.ndarray
Tally results shaped in a manner useful to this helper.
"""
_upper_energy = 20.0e6 # upper energy for tallies
def __init__(self, chain_nuclides):
super().__init__(chain_nuclides)
self._local_indexes = None
self._fission_rate_tally = None
self._tally_nucs = []
self.results = None
def generate_tallies(self, materials, mat_indexes):
"""Construct the fission rate tally
Parameters
----------
materials : iterable of :class:`openmc.capi.Material`
Materials to be used in :class:`openmc.capi.MaterialFilter`
mat_indexes : iterable of int
Indices of tallied materials that will have their fission
yields computed by this helper. Necessary as the
:class:`openmc.deplete.Operator` that uses this helper
may only burn a subset of all materials when running
in parallel mode.
"""
self._local_indexes = asarray(mat_indexes)
# Tally group-wise fission reaction rates
self._fission_rate_tally = Tally()
self._fission_rate_tally.scores = ['fission']
self._fission_rate_tally.filters = [MaterialFilter(materials)]
def update_tally_nuclides(self, nuclides):
"""Tally nuclides with non-zero density and multiple yields
Must be run after :meth:`generate_tallies`.
Parameters
----------
nuclides : iterable of str
Potential nuclides to be tallied, such as those with
non-zero density at this stage.
Returns
-------
nuclides : list of str
Union of input nuclides and those that have multiple sets
of yield data. Sorted by nuclide name
Raises
------
AttributeError
If tallies not generated
"""
assert self._fission_rate_tally is not None, (
"Run generate_tallies first")
overlap = set(self._chain_nuclides).intersection(set(nuclides))
nuclides = sorted(overlap)
self._tally_nucs = [self._chain_nuclides[n] for n in nuclides]
self._fission_rate_tally.nuclides = nuclides
return nuclides
@abstractmethod
def unpack(self):
"""Unpack tallies after a transport run.
Abstract because each subclass will need to arrange its
tally data.
"""
class Integrator(ABC):
"""Abstract class for solving the time-integration for depletion
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
"""
def __init__(self, operator, timesteps, power=None, power_density=None):
# Check number of stages previously used
if operator.prev_res is not None:
res = operator.prev_res[-1]
if res.data.shape[0] != self._num_stages:
raise ValueError(
"{} incompatible with previous restart calculation. "
"Previous scheme used {} intermediate solutions, while "
"this uses {}".format(
self.__class__.__name__, res.data.shape[0],
self._num_stages))
self.operator = operator
self.chain = operator.chain
if not isinstance(timesteps, Iterable):
self.timesteps = [timesteps]
else:
self.timesteps = timesteps
if power is None:
if power_density is None:
raise ValueError("Either power or power density must be set")
if not isinstance(power_density, Iterable):
power = power_density * operator.heavy_metal
else:
power = [p * operator.heavy_metal for p in power_density]
if not isinstance(power, Iterable):
# Ensure that power is single value if that is the case
power = [power] * len(self.timesteps)
elif len(power) != len(self.timesteps):
raise ValueError(
"Number of time steps != number of powers. {} vs {}".format(
len(self.timesteps), len(power)))
self.power = power
@abstractmethod
def __call__(self, conc, rates, dt, power, i):
"""Perform the integration across one time step
Parameters
----------
conc : numpy.ndarray
Initial concentrations for all nuclides in [atom]
rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
i : int
Current depletion step index
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from intermediate transport
simulations
"""
@property
@abstractmethod
def _num_stages(self):
"""Number of intermediate transport solutions
Needed to ensure schemes are consistent with restarts
"""
def __iter__(self):
"""Return pairs of time steps in [s] and powers in [W]"""
return zip(self.timesteps, self.power)
def __len__(self):
"""Return integer number of depletion intervals"""
return len(self.timesteps)
def _get_bos_data_from_operator(self, step_index, step_power, bos_conc):
"""Get beginning of step concentrations, reaction rates from Operator
"""
x = deepcopy(bos_conc)
res = self.operator(x, step_power)
self.operator.write_bos_data(step_index + self._i_res)
return x, res
def _get_bos_data_from_restart(self, step_index, step_power, bos_conc):
"""Get beginning of step concentrations, reaction rates from restart"""
res = self.operator.prev_res[-1]
# Depletion methods expect list of arrays
bos_conc = list(res.data[0])
rates = res.rates[0]
k = ufloat(res.k[0, 0], res.k[0, 1])
# Scale rates by ratio of powers
rates *= step_power / res.power[0]
return bos_conc, OperatorResult(k, rates)
def _get_start_data(self):
if self.operator.prev_res is None:
return 0.0, 0
return (self.operator.prev_res[-1].time[-1],
len(self.operator.prev_res) - 1)
def integrate(self):
"""Perform the entire depletion process across all steps"""
with self.operator as conc:
t, self._i_res = self._get_start_data()
for i, (dt, p) in enumerate(self):
if i > 0 or self.operator.prev_res is None:
conc, res = self._get_bos_data_from_operator(i, p, conc)
else:
conc, res = self._get_bos_data_from_restart(i, p, conc)
proc_time, conc_list, res_list = self(conc, res.rates, dt, p, i)
# Insert BOS concentration, transport results
conc_list.insert(0, conc)
res_list.insert(0, res)
# Remove actual EOS concentration for next step
conc = conc_list.pop()
Results.save(self.operator, conc_list, res_list, [t, t + dt],
p, self._i_res + i, proc_time)
t += dt
# Final simulation
res_list = [self.operator(conc, p)]
Results.save(self.operator, [conc], res_list, [t, t],
p, self._i_res + len(self), proc_time)
self.operator.write_bos_data(len(self) + self._i_res)
class SIIntegrator(Integrator):
"""Abstract class for the Stochastic Implicit Euler integrators
Does not provide a ``__call__`` method, but scales and resets
the number of particles used in initial transport calculation
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
n_steps : int, optional
Number of stochastic iterations per depletion interval.
Must be greater than zero. Default : 10
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
n_steps : int
Number of stochastic iterations per depletion interval
"""
def __init__(self, operator, timesteps, power=None, power_density=None,
n_steps=10):
check_type("n_steps", n_steps, Integral)
check_greater_than("n_steps", n_steps, 0)
super().__init__(operator, timesteps, power, power_density)
self.n_steps = n_steps
def _get_bos_data_from_operator(self, step_index, step_power, bos_conc):
reset_particles = False
if step_index == 0 and hasattr(self.operator, "settings"):
reset_particles = True
self.operator.settings.particles *= self.n_stages
inherited = super()._get_bos_data_from_operator(
step_index, step_power, bos_conc)
if reset_particles:
self.operator.settings.particles //= self.n_stages
return inherited
def integrate(self):
"""Perform the entire depletion process across all steps"""
with self.operator as conc:
t, self._i_res = self._get_start_data()
for i, (dt, p) in enumerate(self):
if i == 0:
if self.operator.prev_res is None:
conc, res = self._get_bos_data_from_operator(i, p, conc)
else:
conc, res = self._get_bos_data_from_restart(i, p, conc)
else:
# Pull rates, k from previous iteration w/o
# re-running transport
res = res_list[-1] # defined in previous i iteration
proc_time, conc_list, res_list = self(conc, res.rates, dt, p, i)
# Insert BOS concentration, transport results
conc_list.insert(0, conc)
res_list.insert(0, res)
# Remove actual EOS concentration for next step
conc = conc_list.pop()
Results.save(self.operator, conc_list, res_list, [t, t + dt],
p, self._i_res + i, proc_time)
t += dt
# No final simulation for SIE, use last iteration results
Results.save(self.operator, [conc], [res_list[-1]], [t, t],
p, self._i_res + len(self), proc_time)
self.operator.write_bos_data(self._i_res + len(self))

View file

@ -9,11 +9,13 @@ from itertools import chain
import math
import re
from collections import OrderedDict, defaultdict
from collections.abc import Mapping
from collections.abc import Mapping, Iterable
from numbers import Real
from warnings import warn
from openmc.checkvalue import check_type, check_less_than
from openmc.checkvalue import check_type, check_greater_than
from openmc.data import gnd_name, zam
from .nuclide import FissionYieldDistribution
# Try to use lxml if it is available. It preserves the order of attributes and
# provides a pretty-printer by default. If not available,
@ -103,6 +105,19 @@ def replace_missing(product, decay_data):
return product
_SECONDARY_PARTICLES = {
"(n,p)": ["H1"], "(n,d)": ["H2"], "(n,t)": ["H3"], "(n,3He)": ["He3"],
"(n,a)": ["He4"], "(n,2nd)": ["H2"], "(n,na)": ["He4"], "(n,3na)": ["He4"],
"(n,n3a)": ["He4"] * 3, "(n,2na)": ["He4"], "(n,np)": ["H1"],
"(n,n2a)": ["He4"] * 2, "(n,2n2a)": ["He4"] * 2, "(n,nd)": ["H2"],
"(n,nt)": ["H3"], "(n,nHe-3)": ["He3"], "(n,nd2a)": ["H2", "He4"],
"(n,nt2a)": ["H3", "He4", "He4"], "(n,2np)": ["H1"], "(n,3np)": ["H1"],
"(n,n2p)": ["H1"] * 2, "(n,2a)": ["He4"] * 2, "(n,3a)": ["He4"] * 3,
"(n,2p)": ["H1"] * 2, "(n,pa)": ["H1", "He4"],
"(n,t2a)": ["H3", "He4", "He4"], "(n,d2a)": ["H2", "He4", "He4"],
"(n,pd)": ["H1", "H2"], "(n,pt)": ["H1", "H3"], "(n,da)": ["H2", "He4"]}
class Chain(object):
"""Full representation of a depletion chain.
@ -122,13 +137,22 @@ class Chain(object):
Reactions that are tracked in the depletion chain
nuclide_dict : OrderedDict of str to int
Maps a nuclide name to an index in nuclides.
fission_yields : None or iterable of dict
List of effective fission yields for materials. Each dictionary
should be of the form ``{parent: {product: yield}}`` with
types ``{str: {str: float}}``, where ``yield`` is the fission product
yield for isotope ``parent`` producing isotope ``product``.
A single entry indicates yields are constant across all materials.
Otherwise, an entry can be added for each material to be burned.
Ordering should be identical to how the operator orders reaction
rates for burnable materials.
"""
def __init__(self):
self.nuclides = []
self.reactions = []
self.nuclide_dict = OrderedDict()
self._fission_yields = None
def __contains__(self, nuclide):
return nuclide in self.nuclide_dict
@ -196,8 +220,7 @@ class Chain(object):
for idx, parent in enumerate(sorted(decay_data, key=openmc.data.zam)):
data = decay_data[parent]
nuclide = Nuclide()
nuclide.name = parent
nuclide = Nuclide(parent)
chain.nuclides.append(nuclide)
chain.nuclide_dict[parent] = idx
@ -212,7 +235,8 @@ class Chain(object):
if mode.daughter in decay_data:
target = mode.daughter
else:
print('missing {} {} {}'.format(parent, ','.join(mode.modes), mode.daughter))
print('missing {} {} {}'.format(
parent, ','.join(mode.modes), mode.daughter))
target = replace_missing(mode.daughter, decay_data)
# Write branching ratio, taking care to ensure sum is unity
@ -266,15 +290,16 @@ class Chain(object):
fpy = fpy_data[parent]
if fpy.energies is not None:
nuclide.yield_energies = fpy.energies
yield_energies = fpy.energies
else:
nuclide.yield_energies = [0.0]
yield_energies = [0.0]
for E, table in zip(nuclide.yield_energies, fpy.independent):
yield_data = {}
for E, table in zip(yield_energies, fpy.independent):
yield_replace = 0.0
yields = defaultdict(float)
for product, y in table.items():
# Handle fission products that have no decay data available
# Handle fission products that have no decay data
if product not in decay_data:
daughter = replace_missing(product, decay_data)
product = daughter
@ -284,10 +309,9 @@ class Chain(object):
if yield_replace > 0.0:
missing_fp.append((parent, E, yield_replace))
yield_data[E] = yields
nuclide.yield_data[E] = []
for k in sorted(yields, key=openmc.data.zam):
nuclide.yield_data[E].append((k, yields[k]))
nuclide.yield_data = FissionYieldDistribution(yield_data)
# Display warnings
if missing_daughter:
@ -374,23 +398,56 @@ class Chain(object):
clean_indentation(root_elem)
tree.write(str(filename), encoding='utf-8')
def form_matrix(self, rates):
def get_thermal_fission_yields(self):
"""Return fission yields at lowest incident neutron energy
Used as the default set of fission yields for :meth:`form_matrix`
if ``fission_yields`` are not provided
Returns
-------
fission_yields : dict
Dictionary of ``{parent: {product: f_yield}}``
where ``parent`` and ``product`` are both string
names of nuclides with yield data and ``f_yield``
is a float for the fission yield.
"""
out = {}
for nuc in self.nuclides:
if nuc.yield_data is None:
continue
yield_obj = nuc.yield_data[min(nuc.yield_energies)]
out[nuc.name] = dict(yield_obj)
return out
def form_matrix(self, rates, fission_yields=None):
"""Forms depletion matrix.
Parameters
----------
rates : numpy.ndarray
2D array indexed by (nuclide, reaction)
fission_yields : dict, optional
Option to use a custom set of fission yields. Expected
to be of the form ``{parent : {product : f_yield}}``
with string nuclide names for ``parent`` and ``product``,
and ``f_yield`` as the respective fission yield
Returns
-------
scipy.sparse.csr_matrix
Sparse matrix representing depletion.
See Also
--------
:meth:`get_thermal_fission_yields`
"""
matrix = defaultdict(float)
reactions = set()
if fission_yields is None:
fission_yields = self.get_thermal_fission_yields()
for i, nuc in enumerate(self.nuclides):
if nuc.n_decay_modes != 0:
@ -435,11 +492,7 @@ class Chain(object):
k = self.nuclide_dict[target]
matrix[k, i] += path_rate * br
else:
# Assume that we should always use thermal fission
# yields. At some point it would be nice to account
# for the energy-dependence..
energy, data = sorted(nuc.yield_data.items())[0]
for product, y in data:
for product, y in fission_yields[nuc.name].items():
yield_val = y * path_rate
if yield_val != 0.0:
k = self.nuclide_dict[product]
@ -454,70 +507,99 @@ class Chain(object):
dict.update(matrix_dok, matrix)
return matrix_dok.tocsr()
def get_capture_branches(self):
"""Return a dictionary with capture branching ratios
def get_branch_ratios(self, reaction="(n,gamma)"):
"""Return a dictionary with reaction branching ratios
Parameters
----------
reaction : str, optional
Reaction name like ``"(n,gamma)"`` [default], or
``"(n,alpha)"``.
Returns
-------
capt :
nested dict of parent nuclide keys with capture targets and
branching ratios::
branches : dict
nested dict of parent nuclide keys with reaction targets and
branching ratios. Consider the capture, ``"(n,gamma)"``,
reaction for Am241::
{"Am241": {"Am242": 0.91, "Am242_m1": 0.09}}
See Also
--------
:meth:`set_capture_branches`
:meth:`set_branch_ratios`
"""
capt = {}
for nuclide in self.nuclides:
nuc_capt = {}
for rx in nuclide.reactions:
if rx.type == "(n,gamma)" and rx.branching_ratio != 1.0:
if rx.type == reaction and rx.branching_ratio != 1.0:
nuc_capt[rx.target] = rx.branching_ratio
if len(nuc_capt) > 0:
capt[nuclide.name] = nuc_capt
return capt
def set_capture_branches(self, branch_ratios, strict=True):
"""Set the capture branching ratios
To provide a buffer around floating point precisions,
the sum of all branching ratios from a single parent
cannot be greater than 1.00001.
def set_branch_ratios(self, branch_ratios, reaction="(n,gamma)",
strict=True, tolerance=1e-5):
"""Set the branching ratios for a given reactions
Parameters
----------
branch_ratios : dict of {str: {str: float}}
Capture branching ratios to be inserted.
First layer keys are names of parent nuclides, e.g.
``"Am241"``. The capture branching ratios for these
``"Am241"``. The branching ratios for these
parents will be modified. Corresponding values are
dictionaries of ``{target: branching_ratio}``
strict : bool
If this evalutes to ``True``, then all parents and
products must exist in the :class:`Chain`. A
:class:`KeyError` will be raised at the first
nuclide that does not exist. Otherwise, print
a warning message for missing parents and/or
products.
reaction : str, optional
Reaction name like ``"(n,gamma)"`` [default], or
``"(n, alpha)"``.
strict : bool, optional
Error control. If this evalutes to ``True``, then errors will
be raised if inconsistencies are found. Otherwise, warnings
will be raised for most issues.
tolerance : float, optional
Tolerance on the sum of all branching ratios for a
single parent. Will be checked with::
1 - tol < sum_br < 1 + tol
Raises
------
IndexError
If no isotopes were found on the chain that have the requested
reaction
KeyError
If ``strict`` evaluates to ``False`` and a parent isotope in
``branch_ratios`` does not exist on the chain
AttributeError
If ``strict`` evaluates to ``False`` and a parent isotope in
``branch_ratios`` does not have the requested reaction
ValueError
If ``strict`` evalutes to ``False`` and the sum of one parents
branch ratios is outside 1 +/- ``tolerance``
See Also
--------
:meth:`get_capture_branches`
:meth:`get_branch_ratios`
"""
# Store some useful information through the validation stage
sums = {}
capt_ix_map = {}
rxn_ix_map = {}
grounds = {}
tolerance = abs(tolerance)
missing_parents = set()
missing_products = {}
no_capture = set()
missing_reaction = set()
bad_sums = {}
# Secondary products, like alpha particles, should not be modified
secondary = _SECONDARY_PARTICLES.get(reaction, [])
# Check for validity before manipulation
@ -543,11 +625,11 @@ class Chain(object):
if prod_flag:
continue
# Make sure this nuclide has capture reactions
# Make sure this nuclide has the reaction
indexes = []
for ix, rx in enumerate(self[parent].reactions):
if rx.type == "(n,gamma)":
if rx.type == reaction and rx.target not in secondary:
indexes.append(ix)
if "_m" not in rx.target:
grounds[parent] = rx.target
@ -555,24 +637,39 @@ class Chain(object):
if len(indexes) == 0:
if strict:
raise AttributeError(
"Nuclide {} does not have capture reactions in "
"this {}".format(parent, self.__class__.__name__))
no_capture.add(parent)
"Nuclide {} does not have {} reactions".format(
parent, reaction))
missing_reaction.add(parent)
continue
capt_ix_map[parent] = indexes
this_sum = sum(sub.values())
check_less_than(parent + " ratios", this_sum, 1.00001)
sums[parent] = this_sum
# sum of branching ratios can be lower than 1 if no ground
# target is given, but never greater
if (this_sum >= 1 + tolerance or (grounds[parent] in sub
and this_sum <= 1 - tolerance)):
if strict:
msg = ("Sum of {} branching ratios for {} "
"({:7.3f}) outside tolerance of 1 +/- "
"{:5.3e}".format(
reaction, parent, this_sum, tolerance))
raise ValueError(msg)
bad_sums[parent] = this_sum
else:
rxn_ix_map[parent] = indexes
sums[parent] = this_sum
if len(rxn_ix_map) == 0:
raise IndexError(
"No {} reactions found in this {}".format(
reaction, self.__class__.__name__))
if len(missing_parents) > 0:
warn("The following nuclides were not found in {}: {}".format(
self.__class__.__name__, ", ".join(sorted(missing_parents))))
if len(no_capture) > 0:
warn("The following nuclides did not have capture reactions: "
"{}".format(", ".join(sorted(no_capture))))
if len(missing_reaction) > 0:
warn("The following nuclides did not have {} reactions: "
"{}".format(reaction, ", ".join(sorted(missing_reaction))))
if len(missing_products) > 0:
tail = ("{} -> {}".format(k, v)
@ -581,28 +678,35 @@ class Chain(object):
"parents were unmodified: \n{}".format(
self.__class__.__name__, ", ".join(tail)))
if len(bad_sums) > 0:
tail = ("{}: {:5.3f}".format(k, s)
for k, s in sorted(bad_sums.items()))
warn("The following parent nuclides were given {} branch ratios "
"with a sum outside tolerance of 1 +/- {:5.3e}:\n{}".format(
reaction, tolerance, "\n".join(tail)))
# Insert new ReactionTuples with updated branch ratios
for parent_name, capt_index in capt_ix_map.items():
for parent_name, rxn_index in rxn_ix_map.items():
parent = self[parent_name]
new_ratios = branch_ratios[parent_name]
capt_index = capt_ix_map[parent_name]
rxn_index = rxn_ix_map[parent_name]
# Assume Q value is independent of target state
capt_Q = parent.reactions[capt_index[0]].Q
rxn_Q = parent.reactions[rxn_index[0]].Q
# Remove existing capture reactions
# Remove existing reactions
for ix in reversed(capt_index):
for ix in reversed(rxn_index):
parent.reactions.pop(ix)
all_meta = True
for tgt, br in new_ratios.items():
all_meta = all_meta and ("_m" in tgt)
all_meta = all_meta and ("_m" in tgt)
parent.reactions.append(ReactionTuple(
"(n,gamma)", tgt, capt_Q, br))
reaction, tgt, rxn_Q, br))
if all_meta and sums[parent_name] != 1.0:
ground_br = 1.0 - sums[parent_name]
@ -612,4 +716,69 @@ class Chain(object):
ground_tgt = gnd_name(pz, pa + 1, 0)
new_ratios[ground_tgt] = ground_br
parent.reactions.append(ReactionTuple(
"(n,gamma)", ground_tgt, capt_Q, ground_br))
reaction, ground_tgt, rxn_Q, ground_br))
@property
def fission_yields(self):
if self._fission_yields is None:
self._fission_yields = [self.get_thermal_fission_yields()]
return self._fission_yields
@fission_yields.setter
def fission_yields(self, yields):
if yields is not None:
if isinstance(yields, Mapping):
yields = [yields]
check_type("fission_yields", yields, Iterable, Mapping)
self._fission_yields = yields
def validate(self, strict=True, quiet=False, tolerance=1e-4):
"""Search for possible inconsistencies
The following checks are performed for all nuclides present:
1) For all non-fission reactions, does the sum of branching
ratios equal about one?
2) For fission reactions, does the sum of fission yield
fractions equal about two?
Parameters
----------
strict : bool, optional
Raise exceptions at the first inconsistency if true.
Otherwise mark a warning
quiet : bool, optional
Flag to suppress warnings and return immediately at
the first inconsistency. Used only if
``strict`` does not evaluate to ``True``.
tolerance : float, optional
Absolute tolerance for comparisons. Used to compare computed
value ``x`` to intended value ``y`` as::
valid = (y - tolerance <= x <= y + tolerance)
Returns
-------
valid : bool
True if no inconsistencies were found
Raises
------
ValueError
If ``strict`` evaluates to ``True`` and an inconistency was
found
See Also
--------
openmc.deplete.Nuclide.validate
"""
check_type("tolerance", tolerance, Real)
check_greater_than("tolerance", tolerance, 0.0, True)
valid = True
# Sort through nuclides by name
for name in sorted(self.nuclide_dict):
stat = self[name].validate(strict, quiet, tolerance)
if quiet and not stat:
return stat
valid = valid and stat
return valid

View file

@ -11,10 +11,12 @@ import numpy as np
import scipy.sparse as sp
import scipy.sparse.linalg as sla
from .. import comm
from . import comm
__all__ = ["deplete", "timed_deplete", "CRAM16", "CRAM48"]
def deplete(chain, x, rates, dt, print_out=True, matrix_func=None):
def deplete(chain, x, rates, dt, matrix_func=None):
"""Deplete materials using given reaction rates for a specified time
Parameters
@ -27,28 +29,37 @@ def deplete(chain, x, rates, dt, print_out=True, matrix_func=None):
Reaction rates (from transport operator)
dt : float
Time in [s] to deplete for
print_out : bool, optional
Whether to show elapsed time
maxtrix_func : function, optional
Function to form the depletion matrix
maxtrix_func : Callable, optional
Function to form the depletion matrix after calling
``matrix_func(chain, rates, fission_yields)``, where
``fission_yields = {parent: {product: yield_frac}}``
Expected to return the depletion matrix required by
:func:`CRAM48`.
Returns
-------
x_result : list of numpy.ndarray
Updated atom number vectors for each material
"""
t_start = time.time()
fission_yields = chain.fission_yields
if len(fission_yields) == 1:
fission_yields = repeat(fission_yields[0])
elif len(fission_yields) != len(x):
raise ValueError(
"Number of material fission yield distributions {} is not equal "
"to the number of compositions {}".format(len(fission_yields),
len(x)))
if matrix_func is None:
matrices = map(chain.form_matrix, rates, fission_yields)
else:
matrices = map(matrix_func, repeat(chain), rates, fission_yields)
# Use multiprocessing pool to distribute work
with Pool() as pool:
iters = zip(repeat(chain), x, rates, repeat(dt), repeat(matrix_func))
x_result = list(pool.starmap(_cram_wrapper, iters))
t_end = time.time()
if comm.rank == 0:
if print_out:
print("Time to matexp: ", t_end - t_start)
inputs = zip(matrices, x, repeat(dt))
x_result = list(pool.starmap(CRAM48, inputs))
return x_result
@ -72,35 +83,6 @@ def timed_deplete(*args, **kwargs):
return time.time() - start, results
def _cram_wrapper(chain, n0, rates, dt, matrix_func=None):
"""Wraps depletion matrix creation / CRAM solve for multiprocess execution
Parameters
----------
chain : openmc.deplete.Chain
Depletion chain used to construct the burnup matrix
n0 : numpy.array
Vector to operate a matrix exponent on.
rates : numpy.ndarray
2D array indexed by nuclide then by cell.
dt : float
Time to integrate to.
maxtrix_func : function, optional
Function to form the depletion matrix
Returns
-------
numpy.array
Results of the matrix exponent.
"""
if matrix_func is None:
A = chain.form_matrix(rates)
else:
A = matrix_func(chain, rates)
return CRAM48(A, n0, dt)
def CRAM16(A, n0, dt):
"""Chebyshev Rational Approximation Method, order 16

View file

@ -1,12 +1,24 @@
"""
Class for normalizing fission energy deposition
"""
from copy import deepcopy
from itertools import product
from numbers import Real
import bisect
from numpy import dot, zeros
from numpy import dot, zeros, newaxis
from openmc.capi import Tally, MaterialFilter
from .abc import ReactionRateHelper, EnergyHelper
from openmc.checkvalue import check_type, check_greater_than
from openmc.capi import (
Tally, MaterialFilter, EnergyFilter, EnergyFunctionFilter)
from .abc import (
ReactionRateHelper, EnergyHelper, FissionYieldHelper,
TalliedFissionYieldHelper)
__all__ = (
"DirectReactionRateHelper", "ChainFissionHelper",
"ConstantFissionYieldHelper", "FissionYieldCutoffHelper",
"AveragedFissionYieldHelper")
# -------------------------------------
# Helpers for generating reaction rates
@ -142,3 +154,465 @@ class ChainFissionHelper(EnergyHelper):
isotopes in all materials have the same Q value.
"""
self._energy += dot(fission_rates, self._fission_q_vector)
# ------------------------------------
# Helper for collapsing fission yields
# ------------------------------------
class ConstantFissionYieldHelper(FissionYieldHelper):
"""Class that uses a single set of fission yields on each isotope
Parameters
----------
chain_nuclides : iterable of openmc.deplete.Nuclide
Nuclides tracked in the depletion chain. All nuclides are
not required to have fission yield data.
energy : float, optional
Key in :attr:`openmc.deplete.Nuclide.yield_data` corresponding
to the desired set of fission yield data. Typically one of
``{0.0253, 500000, 14000000}`` corresponding to 0.0253 eV,
500 keV, and 14 MeV yield libraries. If the specific key is not
found, will fall back to closest energy present.
Default: 0.0253 eV for thermal yields
Attributes
----------
constant_yields : dict of str to :class:`openmc.deplete.FissionYield`
Fission yields for all nuclides that only have one set of
fission yield data. Can be accessed as ``{parent: {product: yield}}``
energy : float
Energy of fission yield libraries.
"""
def __init__(self, chain_nuclides, energy=0.0253):
check_type("energy", energy, Real)
check_greater_than("energy", energy, 0.0, equality=True)
self._energy = energy
super().__init__(chain_nuclides)
# Iterate over all nuclides with > 1 set of yields
for name, nuc in self._chain_nuclides.items():
yield_data = nuc.yield_data.get(energy)
if yield_data is not None:
self._constant_yields[name] = yield_data
continue
# Specific energy not found, use closest energy
distances = [abs(energy - ene) for ene in nuc.yield_energies]
min_E = min(nuc.yield_energies, key=lambda e: abs(e - energy))
self._constant_yields[name] = nuc.yield_data[min_E]
@classmethod
def from_operator(cls, operator, **kwargs):
"""Return a new ConstantFissionYieldHelper using operator data
All keyword arguments should be identical to their counterpart
in the main ``__init__`` method
Parameters
----------
operator : openmc.deplete.TransportOperator
operator with a depletion chain
kwargs:
Additional keyword arguments to be used in construction
Returns
-------
ConstantFissionYieldHelper
"""
return cls(operator.chain.nuclides, **kwargs)
@property
def energy(self):
return self._energy
def weighted_yields(self, _local_mat_index=None):
"""Return fission yields for all nuclides requested
Parameters
----------
_local_mat_index : int, optional
Current material index. Not used since all yields are
constant
Returns
-------
library : dict
Dictionary of ``{parent: {product: fyield}}``
"""
return self.constant_yields
class FissionYieldCutoffHelper(TalliedFissionYieldHelper):
"""Helper that computes fission yields based on a cutoff energy
Tally fission rates above and below the cutoff energy.
Assume that all fissions below cutoff energy have use thermal fission
product yield distributions, while all fissions above use a faster
set of yield distributions.
Uses a limit of 20 MeV for tallying fission.
Parameters
----------
chain_nuclides : iterable of openmc.deplete.Nuclide
Nuclides tracked in the depletion chain. All nuclides are
not required to have fission yield data.
n_bmats : int, optional
Number of burnable materials tracked in the problem
cutoff : float, optional
Cutoff energy in [eV] below which all fissions will be
use thermal yields. All other fissions will use a
faster set of yields. Default: 112 [eV]
thermal_energy : float, optional
Energy of yield data corresponding to thermal yields.
Default: 0.0253 [eV]
fast_energy : float, optional
Energy of yield data corresponding to fast yields.
Default: 500 [kev]
Attributes
----------
n_bmats : int
Number of burnable materials tracked in the problem.
Must be set prior to generating tallies
thermal_yields : dict
Dictionary of the form ``{parent: {product: yield}}``
with thermal yields
fast_yields : dict
Dictionary of the form ``{parent: {product: yield}}``
with fast yields
results : numpy.ndarray
Array of fission rate fractions with shape
``(n_mats, 2, n_nucs)``. ``results[:, 0]``
corresponds to the fraction of all fissions
that occured below ``cutoff``. The number
of materials in the first axis corresponds
to the number of materials burned by the
:class:`openmc.deplete.Operator`
"""
def __init__(self, chain_nuclides, n_bmats, cutoff=112.0,
thermal_energy=0.0253, fast_energy=500.0e3):
check_type("cutoff", cutoff, Real)
check_type("thermal_energy", thermal_energy, Real)
check_type("fast_energy", fast_energy, Real)
check_greater_than("thermal_energy", thermal_energy, 0.0, equality=True)
check_greater_than("cutoff", cutoff, thermal_energy, equality=False)
check_greater_than("fast_energy", fast_energy, cutoff, equality=False)
self.n_bmats = n_bmats
super().__init__(chain_nuclides)
self._cutoff = cutoff
self._thermal_yields = {}
self._fast_yields = {}
convert_to_constant = set()
for name, nuc in self._chain_nuclides.items():
yields = nuc.yield_data
energies = nuc.yield_energies
thermal = yields.get(thermal_energy)
fast = yields.get(fast_energy)
if thermal is None or fast is None:
if cutoff <= energies[0]:
# use lowest energy yields as constant
self._constant_yields[name] = yields[energies[0]]
convert_to_constant.add(name)
continue
if cutoff >= energies[-1]:
# use highest energy yields as constant
self._constant_yields[name] = yields[energies[-1]]
convert_to_constant.add(name)
continue
cutoff_ix = bisect.bisect_left(energies, cutoff)
# find closest energy to requested thermal, fast energies
if thermal is None:
min_E = min(energies[:cutoff_ix],
key=lambda e: abs(e - thermal_energy))
thermal = yields[min_E]
if fast is None:
min_E = min(energies[cutoff_ix:],
key=lambda e: abs(e - fast_energy))
fast = yields[min_E]
self._thermal_yields[name] = thermal
self._fast_yields[name] = fast
for name in convert_to_constant:
self._chain_nuclides.pop(name)
@classmethod
def from_operator(cls, operator, **kwargs):
"""Construct a helper from an operator
All keyword arguments should be identical to their counterpart
in the main ``__init__`` method
Parameters
----------
operator : openmc.deplete.Operator
Operator with a chain and burnable materials
kwargs:
Additional keyword arguments to be used in construction
Returns
-------
FissionYieldCutoffHelper
"""
return cls(operator.chain.nuclides, len(operator.burnable_mats),
**kwargs)
def generate_tallies(self, materials, mat_indexes):
"""Use C API to produce a fission rate tally in burnable materials
Include a :class:`openmc.capi.EnergyFilter` to tally fission rates
above and below cutoff energy.
Parameters
----------
materials : iterable of :class:`openmc.capi.Material`
Materials to be used in :class:`openmc.capi.MaterialFilter`
mat_indexes : iterable of int
Indices of tallied materials that will have their fission
yields computed by this helper. Necessary as the
:class:`openmc.deplete.Operator` that uses this helper
may only burn a subset of all materials when running
in parallel mode.
"""
super().generate_tallies(materials, mat_indexes)
energy_filter = EnergyFilter([0.0, self._cutoff, self._upper_energy])
self._fission_rate_tally.filters = (
self._fission_rate_tally.filters + [energy_filter])
def unpack(self):
"""Obtain fast and thermal fission fractions from tally"""
if not self._tally_nucs:
self.results = None
return
fission_rates = self._fission_rate_tally.results[..., 1].reshape(
self.n_bmats, 2, len(self._tally_nucs))
self.results = fission_rates[self._local_indexes]
total_fission = self.results.sum(axis=1)
nz_mat, nz_nuc = total_fission.nonzero()
self.results[nz_mat, :, nz_nuc] /= total_fission[nz_mat, newaxis, nz_nuc]
def weighted_yields(self, local_mat_index):
"""Return fission yields for a specific material
For nuclides with both yield data above and below
the cutoff energy, the effective yield for nuclide ``A``
will be a weighted sum of fast and thermal yields. The
weights will be the fraction of ``A`` fission events
in the above and below the cutoff energy.
If ``A`` has fission product distribution ``F``
for fast fissions and ``T`` for thermal fissions, and
70% of ``A`` fissions are considered thermal, then
the effective fission product yield distributions
for ``A`` is ``0.7 * T + 0.3 * F``
Parameters
----------
local_mat_index : int
Index for specific burnable material. Effective
yields will be produced using
``self.results[local_mat_index]``
Returns
-------
library : dict
Dictionary of ``{parent: {product: fyield}}``
"""
yields = self.constant_yields
if not self._tally_nucs:
return yields
rates = self.results[local_mat_index]
# iterate over thermal then fast yields, prefer __mul__ to __rmul__
for therm_frac, fast_frac, nuc in zip(rates[0], rates[1], self._tally_nucs):
yields[nuc.name] = (self._thermal_yields[nuc.name] * therm_frac
+ self._fast_yields[nuc.name] * fast_frac)
return yields
@property
def thermal_yields(self):
return deepcopy(self._thermal_yields)
@property
def fast_yields(self):
return deepcopy(self._fast_yields)
class AveragedFissionYieldHelper(TalliedFissionYieldHelper):
r"""Class that computes fission yields based on average fission energy
Computes average energy at which fission events occured with
.. math::
\bar{E} = \frac{
\int_0^\infty E\sigma_f(E)\phi(E)dE
}{
\int_0^\infty\sigma_f(E)\phi(E)dE
}
If the average energy for a nuclide is below the lowest energy
with yield data, that set of fission yields is taken.
Conversely, if the average energy is above the highest energy
with yield data, that set of fission yields is used.
For the case where the average energy is between two sets
of yields, the effective fission yield computed by
linearly interpolating between yields provided at the
nearest energies above and below the average.
Parameters
----------
chain_nuclides : iterable of openmc.deplete.Nuclide
Nuclides tracked in the depletion chain. All nuclides are
not required to have fission yield data.
Attributes
----------
constant_yields : dict of str to :class:`openmc.deplete.FissionYield`
Fission yields for all nuclides that only have one set of
fission yield data. Can be accessed as ``{parent: {product: yield}}``
results : None or numpy.ndarray
If tallies have been generated and unpacked, then the array will
have shape ``(n_mats, n_tnucs)``, where ``n_mats`` is the number
of materials where fission reactions were tallied and ``n_tnucs``
is the number of nuclides with multiple sets of fission yields.
Data in the array are the average energy of fission events for
tallied nuclides across burnable materials.
"""
def __init__(self, chain_nuclides):
super().__init__(chain_nuclides)
self._weighted_tally = None
def generate_tallies(self, materials, mat_indexes):
"""Construct tallies to determine average energy of fissions
Parameters
----------
materials : iterable of :class:`openmc.capi.Material`
Materials to be used in :class:`openmc.capi.MaterialFilter`
mat_indexes : iterable of int
Indices of tallied materials that will have their fission
yields computed by this helper. Necessary as the
:class:`openmc.deplete.Operator` that uses this helper
may only burn a subset of all materials when running
in parallel mode.
"""
super().generate_tallies(materials, mat_indexes)
fission_tally = self._fission_rate_tally
filters = fission_tally.filters
ene_filter = EnergyFilter([0, self._upper_energy])
fission_tally.filters = filters + [ene_filter]
func_filter = EnergyFunctionFilter()
func_filter.set_data((0, self._upper_energy), (0, self._upper_energy))
weighted_tally = Tally()
weighted_tally.scores = ['fission']
weighted_tally.filters = filters + [func_filter]
self._weighted_tally = weighted_tally
def update_tally_nuclides(self, nuclides):
"""Tally nuclides with non-zero density and multiple yields
Must be run after :meth:`generate_tallies`.
Parameters
----------
nuclides : iterable of str
Potential nuclides to be tallied, such as those with
non-zero density at this stage.
Returns
-------
nuclides : tuple of str
Union of input nuclides and those that have multiple sets
of yield data. Sorted by nuclide name
Raises
------
AttributeError
If tallies not generated
"""
tally_nucs = super().update_tally_nuclides(nuclides)
self._weighted_tally.nuclides = tally_nucs
return tally_nucs
def unpack(self):
"""Unpack tallies and populate :attr:`results` with average energies"""
if not self._tally_nucs:
self.results = None
return
fission_results = (
self._fission_rate_tally.results[self._local_indexes, :, 1])
self.results = (
self._weighted_tally.results[self._local_indexes, :, 1]).copy()
nz_mat, nz_nuc = fission_results.nonzero()
self.results[nz_mat, nz_nuc] /= fission_results[nz_mat, nz_nuc]
def weighted_yields(self, local_mat_index):
"""Return fission yields for a specific material
Use the computed average energy of fission
events to determine fission yields. If average
energy is between two sets of yields, linearly
interpolate bewteen the two.
Otherwise take the closet set of yields.
Parameters
----------
local_mat_index : int
Index for specific burnable material. Effective
yields will be produced using
``self.results[local_mat_index]``
Returns
-------
library : dict
Dictionary of ``{parent: {product: fyield}}``
"""
if not self._tally_nucs:
return self.constant_yields
mat_yields = {}
average_energies = self.results[local_mat_index]
for avg_e, nuc in zip(average_energies, self._tally_nucs):
nuc_energies = nuc.yield_energies
if avg_e <= nuc_energies[0]:
mat_yields[nuc.name] = nuc.yield_data[nuc_energies[0]]
continue
if avg_e >= nuc_energies[-1]:
mat_yields[nuc.name] = nuc.yield_data[nuc_energies[-1]]
continue
# in-between two energies
# linear search since there are usually ~3 energies
for ix, ene in enumerate(nuc_energies[:-1]):
if nuc_energies[ix + 1] > avg_e:
break
lower, upper = nuc_energies[ix:ix + 2]
fast_frac = (avg_e - lower) / (upper - lower)
mat_yields[nuc.name] = (
nuc.yield_data[lower] * (1 - fast_frac)
+ nuc.yield_data[upper] * fast_frac)
mat_yields.update(self.constant_yields)
return mat_yields
@classmethod
def from_operator(cls, operator, **kwargs):
"""Return a new helper with data from an operator
All keyword arguments should be identical to their counterpart
in the main ``__init__`` method
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator with a depletion chain
kwargs :
Additional keyword arguments to be used in construction
Returns
-------
AveragedFissionYieldHelper
"""
return cls(operator.chain.nuclides)

View file

@ -1,16 +0,0 @@
"""
Integrator
===========
The integrator subcomponents.
"""
from .cf4 import *
from .cecm import *
from .celi import *
from .cram import *
from .epc_rk4 import *
from .leqi import *
from .predictor import *
from .si_celi import *
from .si_leqi import *

View file

@ -1,123 +0,0 @@
"""The CE/CM integrator."""
import copy
from collections.abc import Iterable
from .cram import timed_deplete
from ..results import Results
def cecm(operator, timesteps, power=None, power_density=None, print_out=True):
r"""Deplete using the CE/CM algorithm.
Implements the second order `CE/CM predictor-corrector algorithm
<https://doi.org/10.13182/NSE14-92>`_.
"CE/CM" stands for constant extrapolation on predictor and constant
midpoint on corrector. This algorithm is mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_p &= A(y_n, t_n) \\
y_m &= \text{expm}(A_p h/2) y_n \\
A_c &= A(y_m, t_n + h/2) \\
y_{n+1} &= \text{expm}(A_c h) y_n
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res)
chain = operator.chain
for i, (dt, p) in enumerate(zip(timesteps, power)):
# Get beginning-of-timestep concentrations and reaction rates
# Avoid doing first transport run if already done in previous
# calculation
if i > 0 or operator.prev_res is None:
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], p)]
else:
# Get initial concentration
x = [operator.prev_res[-1].data[0]]
# Get rates
op_results = [operator.prev_res[-1]]
op_results[0].rates = op_results[0].rates[0]
# Set first stage value of keff
op_results[0].k = op_results[0].k[0]
# Scale reaction rates by ratio of powers
power_res = operator.prev_res[-1].power
ratio_power = p / power_res
op_results[0].rates *= ratio_power[0]
# Deplete for first half of timestep
proc_time, x_middle = timed_deplete(
chain, x[0], op_results[0].rates, dt/2, print_out)
# Get middle-of-timestep reaction rates
x.append(x_middle)
op_results.append(operator(x_middle, p))
# Deplete for full timestep using beginning-of-step materials
# and middle-of-timestep reaction rates
pt_end, x_end = timed_deplete(
chain, x[0], op_results[1].rates, dt, print_out)
# Create results, write to disk
Results.save(
operator, x, op_results, [t, t + dt], p, i_res + i,
proc_time + pt_end)
# Advance time, update vector
t += dt
vec = copy.deepcopy(x_end)
# Perform one last simulation
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], power[-1])]
# Create results, write to disk
Results.save(operator, x, op_results, [t, t], p, i_res + len(timesteps))

View file

@ -1,167 +0,0 @@
"""The CE/LI CFQ4 integrator."""
import copy
from collections.abc import Iterable
from .cram import timed_deplete
from ..results import Results
# Functions to form the special matrix for depletion
def _celi_f1(chain, rates):
return 5/12 * chain.form_matrix(rates[0]) + \
1/12 * chain.form_matrix(rates[1])
def _celi_f2(chain, rates):
return 1/12 * chain.form_matrix(rates[0]) + \
5/12 * chain.form_matrix(rates[1])
def celi(operator, timesteps, power=None, power_density=None,
print_out=True):
r"""Deplete using the CE/LI CFQ4 algorithm.
Implements the CE/LI Predictor-Corrector algorithm using the `fourth order
commutator-free integrator <https://doi.org/10.1137/05063042>`_.
"CE/LI" stands for constant extrapolation on predictor and linear
interpolation on corrector. This algorithm is mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_0 &= A(y_n, t_n) \\
y_p &= \text{expm}(h A_0) y_n \\
A_1 &= A(y_p, t_n + h) \\
y_{n+1} &= \text{expm}(\frac{h}{12} A_0 + \frac{5h}{12} A1)
\text{expm}(\frac{5h}{12} A_0 + \frac{h}{12} A1) y_n
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res)
for i, (dt, p) in enumerate(zip(timesteps, power)):
vec, t, _ = celi_inner(operator, vec, p, i, i_res, t, dt,
print_out)
# Perform one last simulation
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], power[-1])]
# Create results, write to disk
Results.save(operator, x, op_results, [t, t], p, i_res + len(timesteps))
def celi_inner(operator, vec, p, i, i_res, t, dt, print_out):
""" The inner loop of CE/LI CFQ4.
Parameters
----------
operator : Operator
The operator object to simulate on.
x : list of nuclide vector
Nuclide vector, beginning of time.
p : float
Power of the reactor in [W]
i : int
Current iteration number.
i_res : int
Starting index, for restart calculation.
t : float
Time at start of step.
dt : float
Time step.
print_out : bool
Whether or not to print out time.
Returns
-------
list of numpy.array
Nuclide vector, end of time.
float
Next time
OperatorResult
Operator result from beginning of step.
"""
chain = operator.chain
# Get beginning-of-timestep concentrations and reaction rates
# Avoid doing first transport run if already done in previous
# calculation
if i > 0 or operator.prev_res is None:
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], p)]
else:
# Get initial concentration
x = [operator.prev_res[-1].data[0]]
# Get rates
op_results = [operator.prev_res[-1]]
op_results[0].rates = op_results[0].rates[0]
# Set first stage value of keff
op_results[0].k = op_results[0].k[0]
# Scale reaction rates by ratio of powers
power_res = operator.prev_res[-1].power
ratio_power = p / power_res
op_results[0].rates *= ratio_power[0]
# Deplete to end
proc_time, x_new = timed_deplete(chain, x[0], op_results[0].rates, dt, print_out)
x.append(x_new)
op_results.append(operator(x[1], p))
# Deplete with two matrix exponentials
rates = list(zip(op_results[0].rates, op_results[1].rates))
time_1, x_end = timed_deplete(chain, x[0], rates, dt, print_out,
matrix_func=_celi_f1)
time_2, x_end = timed_deplete(chain, x_end, rates, dt, print_out,
matrix_func=_celi_f2)
# Create results, write to disk
Results.save(operator, x, op_results, [t, t + dt], p, i_res + i, proc_time + time_1 + time_2)
# return updated time and vectors
return x_end, t + dt, op_results[0]

View file

@ -1,164 +0,0 @@
"""The CF4 integrator."""
import copy
from collections.abc import Iterable
from .cram import timed_deplete
from ..results import Results
# Functions to form the special matrix for depletion
def _cf4_f1(chain, rates):
return 1/2 * chain.form_matrix(rates)
def _cf4_f2(chain, rates):
return -1/2 * chain.form_matrix(rates[0]) + \
chain.form_matrix(rates[1])
def _cf4_f3(chain, rates):
return 1/4 * chain.form_matrix(rates[0]) + \
1/6 * chain.form_matrix(rates[1]) + \
1/6 * chain.form_matrix(rates[2]) + \
-1/12 * chain.form_matrix(rates[3])
def _cf4_f4(chain, rates):
return -1/12 * chain.form_matrix(rates[0]) + \
1/6 * chain.form_matrix(rates[1]) + \
1/6 * chain.form_matrix(rates[2]) + \
1/4 * chain.form_matrix(rates[3])
def cf4(operator, timesteps, power=None, power_density=None, print_out=True):
r"""Deplete using the CF4 algorithm.
Implements the fourth order `commutator-free Lie algorithm
<https://doi.org/10.1016/S0167-739X(02)00161-9>`_.
This algorithm is mathematically defined as:
.. math::
\begin{aligned}
F_1 &= h A(y_0) \\
y_1 &= \text{expm}(1/2 F_1) y_0 \\
F_2 &= h A(y_1) \\
y_2 &= \text{expm}(1/2 F_2) y_0 \\
F_3 &= h A(y_2) \\
y_3 &= \text{expm}(-1/2 F_1 + F_3) y_1 \\
F_4 &= h A(y_3) \\
y_4 &= \text{expm}( 1/4 F_1 + 1/6 F_2 + 1/6 F_3 - 1/12 F_4)
\text{expm}(-1/12 F_1 + 1/6 F_2 + 1/6 F_3 + 1/4 F_4) y_0
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res)
chain = operator.chain
for i, (dt, p) in enumerate(zip(timesteps, power)):
# Get beginning-of-timestep concentrations and reaction rates
# Avoid doing first transport run if already done in previous
# calculation
if i > 0 or operator.prev_res is None:
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], p)]
else:
# Get initial concentration
x = [operator.prev_res[-1].data[0]]
# Get rates
op_results = [operator.prev_res[-1]]
op_results[0].rates = op_results[0].rates[0]
# Set first stage value of keff
op_results[0].k = op_results[0].k[0]
# Scale reaction rates by ratio of powers
power_res = operator.prev_res[-1].power
ratio_power = p / power_res
op_results[0].rates *= ratio_power[0]
# Step 1: deplete with matrix 1/2*A(y0)
time_1, x_new = timed_deplete(
chain, x[0], op_results[0].rates, dt, print_out,
matrix_func=_cf4_f1)
x.append(x_new)
op_results.append(operator(x_new, p))
# Step 2: deplete with matrix 1/2*A(y1)
time_2, x_new = timed_deplete(
chain, x[0], op_results[1].rates, dt, print_out,
matrix_func=_cf4_f1)
x.append(x_new)
op_results.append(operator(x_new, p))
# Step 3: deplete with matrix -1/2*A(y0)+A(y2)
rates = list(zip(op_results[0].rates, op_results[2].rates))
time_3, x_new = timed_deplete(
chain, x[1], rates, dt, print_out, matrix_func=_cf4_f2)
x.append(x_new)
op_results.append(operator(x_new, p))
# Step 4: deplete with two matrix exponentials
rates = list(zip(op_results[0].rates, op_results[1].rates,
op_results[2].rates, op_results[3].rates))
time_4, x_end = timed_deplete(
chain, x[0], rates, dt, print_out, matrix_func=_cf4_f3)
time_5, x_end = timed_deplete(
chain, x_end, rates, dt, print_out, matrix_func=_cf4_f4)
# Create results, write to disk
Results.save(
operator, x, op_results, [t, t + dt], p, i_res + i,
time_1 + time_2 + time_3 + time_4 + time_5)
# Advance time, update vector
t += dt
vec = copy.deepcopy(x_end)
# Perform one last simulation
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], power[-1])]
# Create results, write to disk
Results.save(operator, x, op_results, [t, t], p, i_res + len(timesteps))

View file

@ -1,148 +0,0 @@
"""The EPC-RK4 integrator."""
import copy
from collections.abc import Iterable
from .cram import timed_deplete
from ..results import Results
# Functions to form the special matrix for depletion
def _rk4_f1(chain, rates):
return 1/2 * chain.form_matrix(rates)
def _rk4_f4(chain, rates):
return 1/6 * chain.form_matrix(rates[0]) + \
1/3 * chain.form_matrix(rates[1]) + \
1/3 * chain.form_matrix(rates[2]) + \
1/6 * chain.form_matrix(rates[3])
def epc_rk4(operator, timesteps, power=None, power_density=None, print_out=True):
r"""Deplete using the EPC-RK4 algorithm.
Implements an extended predictor-corrector algorithm with traditional
Runge-Kutta 4 method.
This algorithm is mathematically defined as:
.. math::
\begin{aligned}
F_1 &= h A(y_0) \\
y_1 &= \text{expm}(1/2 F_1) y_0 \\
F_2 &= h A(y_1) \\
y_2 &= \text{expm}(1/2 F_2) y_0 \\
F_3 &= h A(y_2) \\
y_3 &= \text{expm}(F_3) y_0 \\
F_4 &= h A(y_3) \\
y_4 &= \text{expm}(1/6 F_1 + 1/3 F_2 + 1/3 F_3 + 1/6 F_4) y_0
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res)
chain = operator.chain
for i, (dt, p) in enumerate(zip(timesteps, power)):
# Get beginning-of-timestep concentrations and reaction rates
# Avoid doing first transport run if already done in previous
# calculation
if i > 0 or operator.prev_res is None:
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], p)]
else:
# Get initial concentration
x = [operator.prev_res[-1].data[0]]
# Get rates
op_results = [operator.prev_res[-1]]
op_results[0].rates = op_results[0].rates[0]
# Set first stage value of keff
op_results[0].k = op_results[0].k[0]
# Scale reaction rates by ratio of powers
power_res = operator.prev_res[-1].power
ratio_power = p / power_res
op_results[0].rates *= ratio_power[0]
# Step 1: deplete with matrix 1/2*A(y0)
time_1, x_new = timed_deplete(
chain, x[0], op_results[0].rates, dt, print_out,
matrix_func=_rk4_f1)
x.append(x_new)
op_results.append(operator(x[1], p))
# Step 2: deplete with matrix 1/2*A(y1)
time_2, x_new = timed_deplete(
chain, x[0], op_results[1].rates, dt, print_out,
matrix_func=_rk4_f1)
x.append(x_new)
op_results.append(operator(x[2], p))
# Step 3: deplete with matrix A(y2)
time_3, x_new = timed_deplete(
chain, x[0], op_results[2].rates, dt, print_out)
x.append(x_new)
op_results.append(operator(x[3], p))
# Step 4: deplete with matrix 1/6*A(y0)+1/3*A(y1)+1/3*A(y2)+1/6*A(y3)
rates = list(zip(op_results[0].rates, op_results[1].rates,
op_results[2].rates, op_results[3].rates))
time_4, x_end = timed_deplete(
chain, x[0], rates, dt, print_out, matrix_func=_rk4_f4)
# Create results, write to disk
Results.save(
operator, x, op_results, [t, t + dt], p, i_res + i,
time_1 + time_2 + time_3 + time_4)
# Advance time, update vector
t += dt
vec = copy.deepcopy(x_end)
# Perform one last simulation
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], power[-1])]
# Create results, write to disk
Results.save(
operator, x, op_results, [t, t], p, i_res + len(timesteps))

View file

@ -1,170 +0,0 @@
"""The LE/QI CFQ4 integrator."""
import copy
from collections.abc import Iterable
from itertools import repeat
from .celi import celi_inner
from .cram import timed_deplete
from ..results import Results
# Functions to form the special matrix for depletion
def _leqi_f1(chain, inputs):
f1 = chain.form_matrix(inputs[0])
f2 = chain.form_matrix(inputs[1])
dt_l, dt = inputs[2], inputs[3]
return -dt / (12 * dt_l) * f1 + (dt + 6 * dt_l) / (12 * dt_l) * f2
def _leqi_f2(chain, inputs):
f1 = chain.form_matrix(inputs[0])
f2 = chain.form_matrix(inputs[1])
dt_l, dt = inputs[2], inputs[3]
return -5 * dt / (12 * dt_l) * f1 + (5 * dt + 6 * dt_l) / (12 * dt_l) * f2
def _leqi_f3(chain, inputs):
f1 = chain.form_matrix(inputs[0])
f2 = chain.form_matrix(inputs[1])
f3 = chain.form_matrix(inputs[2])
dt_l, dt = inputs[3], inputs[4]
return -dt**2 / (12 * dt_l * (dt + dt_l)) * f1 + \
(dt**2 + 6*dt*dt_l + 5*dt_l**2) / (12 * dt_l * (dt + dt_l)) * f2 + \
dt_l / (12 * (dt + dt_l)) * f3
def _leqi_f4(chain, inputs):
f1 = chain.form_matrix(inputs[0])
f2 = chain.form_matrix(inputs[1])
f3 = chain.form_matrix(inputs[2])
dt_l, dt = inputs[3], inputs[4]
return -dt**2 / (12 * dt_l * (dt + dt_l)) * f1 + \
(dt**2 + 2*dt*dt_l + dt_l**2) / (12 * dt_l * (dt + dt_l)) * f2 + \
(4 * dt * dt_l + 5 * dt_l**2) / (12 * dt_l * (dt + dt_l)) * f3
def leqi(operator, timesteps, power=None, power_density=None, print_out=True):
r"""Deplete using the LE/QI CFQ4 algorithm.
Implements the LE/QI Predictor-Corrector algorithm using the `fourth order
commutator-free integrator <https://doi.org/10.1137/05063042>`_.
"LE/QI" stands for linear extrapolation on predictor and quadratic
interpolation on corrector. This algorithm is mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_{last} &= A(y_{n-1}, t_n - h_1) \\
A_0 &= A(y_n, t_n) \\
F_1 &= \frac{-h_2^2}{12h_1} A_{last} + \frac{h_2(6h_1+h_2)}{12h_1} A_0 \\
F_2 &= \frac{-5h_2^2}{12h_1} A_{last} + \frac{h_2(6h_1+5h_2)}{12h_1} A_0 \\
y_p &= \text{expm}(F_2) \text{expm}(F_1) y_n \\
A_1 &= A(y_p, t_n + h_2) \\
F_3 &= \frac{-h_2^3}{12 h_1 (h_1 + h_2)} A_{last} +
\frac{h_2 (5 h_1^2 + 6 h_2 h_1 + h_2^2)}{12 h_1 (h_1 + h_2)} A_0 +
\frac{h_2 h_1)}{12 (h_1 + h_2)} A_1 \\
F_4 &= \frac{-h_2^3}{12 h_1 (h_1 + h_2)} A_{last} +
\frac{h_2 (h_1^2 + 2 h_2 h_1 + h_2^2)}{12 h_1 (h_1 + h_2)} A_0 +
\frac{h_2 (5 h_1^2 + 4 h_2 h_1)}{12 h_1 (h_1 + h_2)} A_1 \\
y_{n+1} &= \text{expm}(F_4) \text{expm}(F_3) y_n
\end{aligned}
It is initialized using the CE/LI algorithm.
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res)
chain = operator.chain
for i, (dt, p) in enumerate(zip(timesteps, power)):
# LE/QI needs the last step results to start
# Perform CE/LI CFQ4 or restore results for the first step
if i == 0:
if i_res <= 1:
dt_l = dt
x_new, t, op_res_last = celi_inner(operator, vec, p, i,
i_res, t, dt, print_out)
continue
else:
dt_l = t - operator.prev_res[-2].time[0]
op_res_last = operator.prev_res[-2]
op_res_last.rates = op_res_last.rates[0]
x_new = operator.prev_res[-1].data[0]
# Perform remaining LE/QI
x = [copy.deepcopy(x_new)]
op_results = [operator(x[0], p)]
inputs = list(zip(op_res_last.rates, op_results[0].rates,
repeat(dt_l), repeat(dt)))
time_1, x_new = timed_deplete(
chain, x[0], inputs, dt, print_out, matrix_func=_leqi_f1)
time_2, x_new = timed_deplete(
chain, x_new, inputs, dt, print_out, matrix_func=_leqi_f2)
x.append(x_new)
op_results.append(operator(x[1], p))
inputs = list(zip(op_res_last.rates, op_results[0].rates,
op_results[1].rates, repeat(dt_l), repeat(dt)))
time_3, x_new = timed_deplete(
chain, x[0], inputs, dt, print_out, matrix_func=_leqi_f3)
time_4, x_new = timed_deplete(
chain, x_new, inputs, dt, print_out, matrix_func=_leqi_f4)
# Create results, write to disk
Results.save(
operator, x, op_results, [t, t+dt], p, i_res+i,
time_1 + time_2 + time_3 + time_4)
# update results
op_res_last = copy.deepcopy(op_results[0])
t += dt
dt_l = dt
# Perform one last simulation
x = [copy.deepcopy(x_new)]
op_results = [operator(x[0], power[-1])]
# Create results, write to disk
Results.save(
operator, x, op_results, [t, t], p, i_res + len(timesteps))

View file

@ -1,106 +0,0 @@
"""First-order predictor algorithm."""
import copy
from collections.abc import Iterable
from .cram import timed_deplete
from ..results import Results
def predictor(operator, timesteps, power=None, power_density=None,
print_out=True):
r"""Deplete using a first-order predictor algorithm.
Implements the first-order predictor algorithm. This algorithm is
mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_p &= A(y_n, t_n) \\
y_{n+1} &= \text{expm}(A_p h) y_n
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
proc_time = None
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res) - 1
chain = operator.chain
for i, (dt, p) in enumerate(zip(timesteps, power)):
# Get beginning-of-timestep concentrations and reaction rates
# Avoid doing first transport run if already done in previous
# calculation
if i > 0 or operator.prev_res is None:
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], p)]
# Create results, write to disk
Results.save(operator, x, op_results, [t, t + dt], p, i_res + i, proc_time)
else:
# Get initial concentration
x = [operator.prev_res[-1].data[0]]
# Get rates
op_results = [operator.prev_res[-1]]
op_results[0].rates = op_results[0].rates[0]
# Scale reaction rates by ratio of powers
power_res = operator.prev_res[-1].power
ratio_power = p / power_res
op_results[0].rates *= ratio_power[0]
# Deplete for full timestep
proc_time, x_end = timed_deplete(
chain, x[0], op_results[0].rates, dt, print_out)
# Advance time, update vector
t += dt
vec = copy.deepcopy(x_end)
# Perform one last simulation
x = [copy.deepcopy(vec)]
op_results = [operator(x[0], power[-1])]
# Create results, write to disk
Results.save(operator, x, op_results, [t, t], p, i_res + len(timesteps), proc_time)

View file

@ -1,166 +0,0 @@
"""The SI-CE/LI CFQ4 integrator."""
import copy
from collections.abc import Iterable
from .cram import timed_deplete
from ..results import Results
from ..abc import OperatorResult
from .celi import _celi_f1, _celi_f2
def si_celi(operator, timesteps, power=None, power_density=None,
print_out=True, m=10):
r"""Deplete using the SI-CE/LI CFQ4 algorithm.
Implements the Stochastic Implicit CE/LI Predictor-Corrector algorithm using
the `fourth order commutator-free integrator <https://doi.org/10.1137/05063042>`_.
Detailed algorithm can be found in Section 3.2 in `Colin Josey's thesis
<http://hdl.handle.net/1721.1/113721>`_.
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
m : int, optional
Number of stages.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res)
# Get the concentrations and reaction rates for the first
# beginning-of-timestep (BOS). Compute with m (stage number) times as
# many neutrons as later simulations for statistics reasons if no
# previous calculation results present
if operator.prev_res is None:
x = [copy.deepcopy(vec)]
if hasattr(operator, "settings"):
operator.settings.particles *= m
op_results = [operator(x[0], power[0])]
if hasattr(operator, "settings"):
operator.settings.particles //= m
else:
# Get initial concentration
x = [operator.prev_res[-1].data[0]]
# Get rates
op_results = [operator.prev_res[-1]]
op_results[0].rates = op_results[0].rates[0]
# Set first stage value of keff
op_results[0].k = op_results[0].k[0]
# Scale reaction rates by ratio of powers
power_res = operator.prev_res[-1].power
ratio_power = power[0] / power_res
op_results[0].rates *= ratio_power[0]
for i, (dt, p) in enumerate(zip(timesteps, power)):
x, t, op_results = si_celi_inner(operator, x, op_results, p,
i, i_res, t, dt, print_out, m)
# Create results for last point, write to disk
Results.save(
operator, x, op_results, [t, t], p, i_res + len(timesteps))
def si_celi_inner(operator, x, op_results, p, i, i_res, t, dt, print_out, m=10):
""" The inner loop of SI-CE/LI CFQ4.
Parameters
----------
operator : Operator
The operator object to simulate on.
x : list of nuclide vector
Nuclide vector, beginning of time.
op_results : list of OperatorResult
Operator result at BOS.
p : float
Power of the reactor in [W]
i : int
Current iteration number.
i_res : int
Starting index, for restart calculation.
t : float
Time at start of step.
dt : float
Time step.
print_out : bool
Whether or not to print out time.
m : int, optional
Number of stages.
Returns
-------
list of nuclide vector (numpy.array)
Nuclide vector, end of time.
float
Next time
list of OperatorResult
Operator result at end of time.
"""
chain = operator.chain
# Deplete to end
proc_time, x_new = timed_deplete(
chain, x[0], op_results[0].rates, dt, print_out)
x.append(x_new)
for j in range(m + 1):
op_res = operator(x_new, p)
if j <= 1:
op_res_bar = copy.deepcopy(op_res)
else:
rates = 1/j * op_res.rates + (1 - 1/j) * op_res_bar.rates
k = 1/j * op_res.k + (1 - 1/j) * op_res_bar.k
op_res_bar = OperatorResult(k, rates)
rates = list(zip(op_results[0].rates, op_res_bar.rates))
time_1, x_new = timed_deplete(
chain, x[0], rates, dt, print_out, matrix_func=_celi_f1)
time_2, x_new = timed_deplete(
chain, x_new, rates, dt, print_out, matrix_func=_celi_f2)
proc_time += time_1 + time_2
# Create results, write to disk
op_results.append(op_res_bar)
Results.save(operator, x, op_results, [t, t+dt], p, i_res+i, proc_time)
# return updated time and vectors
return [x_new], t + dt, [op_res_bar]

View file

@ -1,157 +0,0 @@
"""The SI-LE/QI CFQ4 integrator."""
import copy
from collections.abc import Iterable
from itertools import repeat
from .si_celi import si_celi_inner
from .leqi import _leqi_f1, _leqi_f2, _leqi_f3, _leqi_f4
from .cram import timed_deplete
from ..results import Results
from ..abc import OperatorResult
def si_leqi(operator, timesteps, power=None, power_density=None,
print_out=True, m=10):
r"""Deplete using the SI-LE/QI CFQ4 algorithm.
Implements the Stochastic Implicit LE/QI Predictor-Corrector algorithm using
the `fourth order commutator-free integrator <https://doi.org/10.1137/05063042>`_.
Detailed algorithm can be found in Section 3.2 in `Colin Josey's thesis
<http://hdl.handle.net/1721.1/113721>`_.
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that the power is
constant over all timesteps. An iterable indicates potentially different
power levels for each timestep. For a 2D problem, the power can be given
in [W/cm] as long as the "volume" assigned to a depletion material is
actually an area in [cm^2]. Either `power` or `power_density` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by initial
heavy metal inventory to get total power if `power` is not speficied.
print_out : bool, optional
Whether or not to print out time.
m : int, optional
Number of stages.
"""
if power is None:
if power_density is None:
raise ValueError(
"Neither power nor power density was specified.")
if not isinstance(power_density, Iterable):
power = power_density*operator.heavy_metal
else:
power = [i*operator.heavy_metal for i in power_density]
if not isinstance(power, Iterable):
power = [power]*len(timesteps)
# Generate initial conditions
with operator as vec:
# Initialize time and starting index
if operator.prev_res is None:
t = 0.0
i_res = 0
else:
t = operator.prev_res[-1].time[-1]
i_res = len(operator.prev_res)
# Get the concentrations and reaction rates for the first
# beginning-of-timestep (BOS). Compute with m (stage number) times as
# many neutrons as later simulations for statistics reasons if no
# previous calculation results present
if operator.prev_res is None:
x = [copy.deepcopy(vec)]
if hasattr(operator, "settings"):
operator.settings.particles *= m
op_results = [operator(x[0], power[0])]
if hasattr(operator, "settings"):
operator.settings.particles //= m
else:
# Get initial concentration
x = [operator.prev_res[-1].data[0]]
# Get rates
op_results = [operator.prev_res[-1]]
op_results[0].rates = op_results[0].rates[0]
# Set first stage value of keff
op_results[0].k = op_results[0].k[0]
# Scale reaction rates by ratio of powers
power_res = operator.prev_res[-1].power
ratio_power = power[0] / power_res
op_results[0].rates *= ratio_power[0]
chain = operator.chain
for i, (dt, p) in enumerate(zip(timesteps, power)):
# LE/QI needs the last step results to start
# Perform SI-CE/LI CFQ4 or restore results for the first step
if i == 0:
dt_l = dt
if i_res <= 1:
op_res_last = copy.deepcopy(op_results[0])
x, t, op_results = si_celi_inner(operator, x, op_results, p,
i, i_res, t, dt, print_out)
continue
else:
dt_l = t - operator.prev_res[-2].time[0]
op_res_last = operator.prev_res[-2]
op_res_last.rates = op_res_last.rates[0]
x = [operator.prev_res[-1].data[0]]
# Perform remaining LE/QI
inputs = list(zip(op_res_last.rates, op_results[0].rates,
repeat(dt_l), repeat(dt)))
proc_time, x_new = timed_deplete(
chain, x[0], inputs, dt, print_out, matrix_func=_leqi_f1)
time_1, x_new = timed_deplete(
chain, x_new, inputs, dt, print_out, matrix_func=_leqi_f2)
x.append(x_new)
proc_time += time_1
# Loop on inner
for j in range(m + 1):
op_res = operator(x_new, p)
if j <= 1:
op_res_bar = copy.deepcopy(op_res)
else:
rates = 1/j * op_res.rates + (1 - 1/j) * op_res_bar.rates
k = 1/j * op_res.k + (1 - 1/j) * op_res_bar.k
op_res_bar = OperatorResult(k, rates)
inputs = list(zip(op_res_last.rates, op_results[0].rates,
op_res_bar.rates, repeat(dt_l), repeat(dt)))
time_1, x_new = timed_deplete(
chain, x[0], inputs, dt, print_out, matrix_func=_leqi_f3)
time_2, x_new = timed_deplete(
chain, x_new, inputs, dt, print_out, matrix_func=_leqi_f4)
proc_time += time_1 + time_2
# Create results, write to disk
op_results.append(op_res_bar)
Results.save(
operator, x, op_results, [t, t+dt], p, i_res+i, proc_time)
# update results
x = [x_new]
op_res_last = copy.deepcopy(op_results[0])
op_results = [op_res_bar]
t += dt
dt_l = dt
# Create results for last point, write to disk
Results.save(
operator, x, op_results, [t, t], p, i_res+len(timesteps))

View file

@ -0,0 +1,836 @@
import copy
from itertools import repeat
from .abc import Integrator, SIIntegrator, OperatorResult
from .cram import timed_deplete
from ._matrix_funcs import (
cf4_f1, cf4_f2, cf4_f3, cf4_f4, celi_f1, celi_f2,
leqi_f1, leqi_f2, leqi_f3, leqi_f4, rk4_f1, rk4_f4
)
__all__ = [
"PredictorIntegrator", "CECMIntegrator", "CF4Integrator",
"CELIIntegrator", "EPCRK4Integrator", "LEQIIntegrator",
"SICELIIntegrator", "SILEQIIntegrator"]
class PredictorIntegrator(Integrator):
r"""Deplete using a first-order predictor algorithm.
Implements the first-order predictor algorithm. This algorithm is
mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_p &= A(y_n, t_n) \\
y_{n+1} &= \text{expm}(A_p h) y_n
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
"""
_num_stages = 1
def __call__(self, conc, rates, dt, power, _i=None):
"""Perform the integration across one time step
Parameters
----------
conc : numpy.ndarray
Initial concentrations for all nuclides in [atom]
rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
_i : int or None
Iteration index. Not used
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at end of interval
op_results : empty list
Kept for consistency with API. No intermediate calls to
operator with predictor
"""
proc_time, conc_end = timed_deplete(self.chain, conc, rates, dt)
return proc_time, [conc_end], []
class CECMIntegrator(Integrator):
r"""Deplete using the CE/CM algorithm.
Implements the second order `CE/CM predictor-corrector algorithm
<https://doi.org/10.13182/NSE14-92>`_.
"CE/CM" stands for constant extrapolation on predictor and constant
midpoint on corrector. This algorithm is mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_p &= A(y_n, t_n) \\
y_m &= \text{expm}(A_p h/2) y_n \\
A_c &= A(y_m, t_n + h/2) \\
y_{n+1} &= \text{expm}(A_c h) y_n
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
"""
_num_stages = 2
def __call__(self, conc, rates, dt, power, _i=None):
"""Integrate using CE/CM
Parameters
----------
conc : numpy.ndarray
Initial concentrations for all nuclides in [atom]
rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system [W]
_i : int, optional
Current iteration count. Not used
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from transport simulations
"""
# deplete across first half of inteval
time0, x_middle = timed_deplete(self.chain, conc, rates, dt / 2)
res_middle = self.operator(x_middle, power)
# deplete across entire interval with BOS concentrations,
# MOS reaction rates
time1, x_end = timed_deplete(self.chain, conc, res_middle.rates, dt)
return time0 + time1, [x_middle, x_end], [res_middle]
class CF4Integrator(Integrator):
r"""Deplete using the CF4 algorithm.
Implements the fourth order `commutator-free Lie algorithm
<https://doi.org/10.1016/S0167-739X(02)00161-9>`_.
This algorithm is mathematically defined as:
.. math::
\begin{aligned}
F_1 &= h A(y_0) \\
y_1 &= \text{expm}(1/2 F_1) y_0 \\
F_2 &= h A(y_1) \\
y_2 &= \text{expm}(1/2 F_2) y_0 \\
F_3 &= h A(y_2) \\
y_3 &= \text{expm}(-1/2 F_1 + F_3) y_1 \\
F_4 &= h A(y_3) \\
y_4 &= \text{expm}( 1/4 F_1 + 1/6 F_2 + 1/6 F_3 - 1/12 F_4)
\text{expm}(-1/12 F_1 + 1/6 F_2 + 1/6 F_3 + 1/4 F_4) y_0
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
"""
_num_stages = 4
def __call__(self, bos_conc, bos_rates, dt, power, _i=None):
"""Perform the integration across one time step
Parameters
----------
bos_conc : numpy.ndarray
Initial concentrations for all nuclides in [atom]
bos_rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
_i : int, optional
Current depletion step index. Not used
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from intermediate transport
simulations
"""
# Step 1: deplete with matrix 1/2*A(y0)
time1, conc_eos1 = timed_deplete(
self.chain, bos_conc, bos_rates, dt, matrix_func=cf4_f1)
res1 = self.operator(conc_eos1, power)
# Step 2: deplete with matrix 1/2*A(y1)
time2, conc_eos2 = timed_deplete(
self.chain, bos_conc, res1.rates, dt, matrix_func=cf4_f1)
res2 = self.operator(conc_eos2, power)
# Step 3: deplete with matrix -1/2*A(y0)+A(y2)
list_rates = list(zip(bos_rates, res2.rates))
time3, conc_eos3 = timed_deplete(
self.chain, conc_eos1, list_rates, dt, matrix_func=cf4_f2)
res3 = self.operator(conc_eos3, power)
# Step 4: deplete with two matrix exponentials
list_rates = list(zip(bos_rates, res1.rates, res2.rates, res3.rates))
time4, conc_inter = timed_deplete(
self.chain, bos_conc, list_rates, dt, matrix_func=cf4_f3)
time5, conc_eos5 = timed_deplete(
self.chain, conc_inter, list_rates, dt, matrix_func=cf4_f4)
return (time1 + time2 + time3 + time4 + time5,
[conc_eos1, conc_eos2, conc_eos3, conc_eos5],
[res1, res2, res3])
class CELIIntegrator(Integrator):
r"""Deplete using the CE/LI CFQ4 algorithm.
Implements the CE/LI Predictor-Corrector algorithm using the `fourth order
commutator-free integrator <https://doi.org/10.1137/05063042>`_.
"CE/LI" stands for constant extrapolation on predictor and linear
interpolation on corrector. This algorithm is mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_0 &= A(y_n, t_n) \\
y_p &= \text{expm}(h A_0) y_n \\
A_1 &= A(y_p, t_n + h) \\
y_{n+1} &= \text{expm}(\frac{h}{12} A_0 + \frac{5h}{12} A1)
\text{expm}(\frac{5h}{12} A_0 + \frac{h}{12} A1) y_n
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
"""
_num_stages = 2
def __call__(self, bos_conc, rates, dt, power, _i=None):
"""Perform the integration across one time step
Parameters
----------
bos_conc : numpy.ndarray
Initial concentrations for all nuclides in [atom]
rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
_i : int, optional
Current iteration count. Not used
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from intermediate transport
simulation
"""
# deplete to end using BOS rates
proc_time, conc_ce = timed_deplete(self.chain, bos_conc, rates, dt)
res_ce = self.operator(conc_ce, power)
# deplete using two matrix exponentials
list_rates = list(zip(rates, res_ce.rates))
time_le1, conc_inter = timed_deplete(
self.chain, bos_conc, list_rates, dt, matrix_func=celi_f1)
time_le2, conc_end = timed_deplete(
self.chain, conc_inter, list_rates, dt, matrix_func=celi_f2)
return proc_time + time_le1 + time_le1, [conc_ce, conc_end], [res_ce]
class EPCRK4Integrator(Integrator):
r"""Deplete using the EPC-RK4 algorithm.
Implements an extended predictor-corrector algorithm with traditional
Runge-Kutta 4 method. This algorithm is mathematically defined as:
.. math::
\begin{aligned}
F_1 &= h A(y_0) \\
y_1 &= \text{expm}(1/2 F_1) y_0 \\
F_2 &= h A(y_1) \\
y_2 &= \text{expm}(1/2 F_2) y_0 \\
F_3 &= h A(y_2) \\
y_3 &= \text{expm}(F_3) y_0 \\
F_4 &= h A(y_3) \\
y_4 &= \text{expm}(1/6 F_1 + 1/3 F_2 + 1/3 F_3 + 1/6 F_4) y_0
\end{aligned}
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
"""
_num_stages = 4
def __call__(self, conc, rates, dt, power, _i=None):
"""Perform the integration across one time step
Parameters
----------
conc : numpy.ndarray
Initial concentrations for all nuclides in [atom]
rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
_i : int, optional
Current depletion step index, unused.
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from intermediate transport
simulations
"""
# Step 1: deplete with matrix A(y0) / 2
time1, conc1 = timed_deplete(
self.chain, conc, rates, dt, matrix_func=rk4_f1)
res1 = self.operator(conc1, power)
# Step 2: deplete with matrix A(y1) / 2
time2, conc2 = timed_deplete(
self.chain, conc, res1.rates, dt, matrix_func=rk4_f1)
res2 = self.operator(conc2, power)
# Step 3: deplete with matrix A(y2)
time3, conc3 = timed_deplete(
self.chain, conc, res2.rates, dt)
res3 = self.operator(conc3, power)
# Step 4: deplete with matrix built from weighted rates
list_rates = list(zip(rates, res1.rates, res2.rates, res3.rates))
time4, conc4 = timed_deplete(
self.chain, conc, list_rates, dt, matrix_func=rk4_f4)
return (time1 + time2 + time3 + time4, [conc1, conc2, conc3, conc4],
[res1, res2, res3])
class LEQIIntegrator(Integrator):
r"""Deplete using the LE/QI CFQ4 algorithm.
Implements the LE/QI Predictor-Corrector algorithm using the `fourth order
commutator-free integrator <https://doi.org/10.1137/05063042>`_.
"LE/QI" stands for linear extrapolation on predictor and quadratic
interpolation on corrector. This algorithm is mathematically defined as:
.. math::
\begin{aligned}
y' &= A(y, t) y(t) \\
A_{last} &= A(y_{n-1}, t_n - h_1) \\
A_0 &= A(y_n, t_n) \\
F_1 &= \frac{-h_2^2}{12h_1} A_{last} + \frac{h_2(6h_1+h_2)}{12h_1} A_0 \\
F_2 &= \frac{-5h_2^2}{12h_1} A_{last} + \frac{h_2(6h_1+5h_2)}{12h_1} A_0 \\
y_p &= \text{expm}(F_2) \text{expm}(F_1) y_n \\
A_1 &= A(y_p, t_n + h_2) \\
F_3 &= \frac{-h_2^3}{12 h_1 (h_1 + h_2)} A_{last} +
\frac{h_2 (5 h_1^2 + 6 h_2 h_1 + h_2^2)}{12 h_1 (h_1 + h_2)} A_0 +
\frac{h_2 h_1)}{12 (h_1 + h_2)} A_1 \\
F_4 &= \frac{-h_2^3}{12 h_1 (h_1 + h_2)} A_{last} +
\frac{h_2 (h_1^2 + 2 h_2 h_1 + h_2^2)}{12 h_1 (h_1 + h_2)} A_0 +
\frac{h_2 (5 h_1^2 + 4 h_2 h_1)}{12 h_1 (h_1 + h_2)} A_1 \\
y_{n+1} &= \text{expm}(F_4) \text{expm}(F_3) y_n
\end{aligned}
It is initialized using the CE/LI algorithm.
Parameters
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
"""
_num_stages = 2
def __call__(self, bos_conc, bos_rates, dt, power, i):
"""Perform the integration across one time step
Parameters
----------
conc : numpy.ndarray
Initial concentrations for all nuclides in [atom]
rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
i : int
Current depletion step index
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from intermediate transport
simulation
"""
if i == 0:
if self._i_res < 1: # need at least previous transport solution
self._prev_rates = bos_rates
return CELIIntegrator.__call__(
self, bos_conc, bos_rates, dt, power, i)
prev_res = self.operator.prev_res[-2]
prev_dt = self.timesteps[i] - prev_res.time[0]
self._prev_rates = prev_res.rates[0]
else:
prev_dt = self.timesteps[i - 1]
# Remaining LE/QI
bos_res = self.operator(bos_conc, power)
le_inputs = list(zip(
self._prev_rates, bos_res.rates, repeat(prev_dt), repeat(dt)))
time1, conc_inter = timed_deplete(
self.chain, bos_conc, le_inputs, dt, matrix_func=leqi_f1)
time2, conc_eos0 = timed_deplete(
self.chain, conc_inter, le_inputs, dt, matrix_func=leqi_f2)
res_inter = self.operator(conc_eos0, power)
qi_inputs = list(zip(
self._prev_rates, bos_res.rates, res_inter.rates,
repeat(prev_dt), repeat(dt)))
time3, conc_inter = timed_deplete(
self.chain, bos_conc, qi_inputs, dt, matrix_func=leqi_f3)
time4, conc_eos1 = timed_deplete(
self.chain, conc_inter, qi_inputs, dt, matrix_func=leqi_f4)
# store updated rates
self._prev_rates = copy.deepcopy(bos_res.rates)
return (
time1 + time2 + time3 + time4, [conc_eos0, conc_eos1],
[bos_res, res_inter])
class SICELIIntegrator(SIIntegrator):
r"""Deplete using the SI-CE/LI CFQ4 algorithm.
Implements the stochastic implicit CE/LI predictor-corrector algorithm
using the `fourth order commutator-free integrator
<https://doi.org/10.1137/05063042>`_.
Detailed algorithm can be found in section 3.2 in `Colin Josey's thesis
<http://hdl.handle.net/1721.1/113721>`_.
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
n_steps : int, optional
Number of stochastic iterations per depletion interval.
Must be greater than zero. Default : 10
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
n_steps : int
Number of stochastic iterations per depletion interval
"""
_num_stages = 2
def __call__(self, bos_conc, bos_rates, dt, power, _i=None):
"""Perform the integration across one time step
Parameters
----------
bos_conc : numpy.ndarray
Initial bos_concentrations for all nuclides in [atom]
bos_rates : openmc.deplete.ReactionRates
Reaction rates from operator
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
_i : int, optional
Current depletion step index. Not used
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
bos_conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final bos_concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from intermediate transport
simulations
"""
proc_time, eos_conc = timed_deplete(
self.chain, bos_conc, bos_rates, dt)
inter_conc = copy.deepcopy(eos_conc)
# Begin iteration
for j in range(self.n_steps + 1):
inter_res = self.operator(inter_conc, power)
if j <= 1:
res_bar = copy.deepcopy(inter_res)
else:
rates = 1/j * inter_res.rates + (1 - 1 / j) * res_bar.rates
k = 1/j * inter_res.k + (1 - 1 / j) * res_bar.k
res_bar = OperatorResult(k, rates)
list_rates = list(zip(bos_rates, res_bar.rates))
time1, inter_conc = timed_deplete(
self.chain, bos_conc, list_rates, dt, matrix_func=celi_f1)
time2, inter_conc = timed_deplete(
self.chain, inter_conc, list_rates, dt, matrix_func=celi_f2)
proc_time += time1 + time2
# end iteration
return proc_time, [eos_conc, inter_conc], [res_bar]
class SILEQIIntegrator(SIIntegrator):
r"""Deplete using the SI-LE/QI CFQ4 algorithm.
Implements the Stochastic Implicit LE/QI Predictor-Corrector algorithm
using the `fourth order commutator-free integrator
<https://doi.org/10.1137/05063042>`_.
Detailed algorithm can be found in Section 3.2 in `Colin Josey's thesis
<http://hdl.handle.net/1721.1/113721>`_.
Parameters
----------
operator : openmc.deplete.TransportOperator
The operator object to simulate on.
timesteps : iterable of float
Array of timesteps in units of [s]. Note that values are not
cumulative.
power : float or iterable of float, optional
Power of the reactor in [W]. A single value indicates that
the power is constant over all timesteps. An iterable
indicates potentially different power levels for each timestep.
For a 2D problem, the power can be given in [W/cm] as long
as the "volume" assigned to a depletion material is actually
an area in [cm^2]. Either ``power`` or ``power_density`` must be
specified.
power_density : float or iterable of float, optional
Power density of the reactor in [W/gHM]. It is multiplied by
initial heavy metal inventory to get total power if ``power``
is not speficied.
n_steps : int, optional
Number of stochastic iterations per depletion interval.
Must be greater than zero. Default : 10
Attributes
----------
operator : openmc.deplete.TransportOperator
Operator to perform transport simulations
chain : openmc.deplete.Chain
Depletion chain
timesteps : iterable of float
Size of each depletion interval in [s]
power : iterable of float
Power of the reactor in [W] for each interval in :attr:`timesteps`
n_steps : int
Number of stochastic iterations per depletion interval
"""
_num_stages = 2
def __call__(self, bos_conc, bos_rates, dt, power, i):
"""Perform the integration across one time step
Parameters
----------
bos_conc : list of numpy.ndarray
Initial concentrations for all nuclides in [atom] for
all depletable materials
bos_rates : list of openmc.deplete.ReactionRates
Reaction rates from operator for all depletable materials
dt : float
Time in [s] for the entire depletion interval
power : float
Power of the system in [W]
i : int
Current depletion step index
Returns
-------
proc_time : float
Time spent in CRAM routines for all materials in [s]
conc_list : list of numpy.ndarray
Concentrations at each of the intermediate points with
the final concentration as the last element
op_results : list of openmc.deplete.OperatorResult
Eigenvalue and reaction rates from intermediate transport
simulation
"""
if i == 0:
if self._i_res < 1:
self._prev_rates = bos_rates
# Perform CELI for initial steps
return SICELIIntegrator.__call__(
self, bos_conc, bos_rates, dt, power, i)
prev_res = self.operator.prev_res[-2]
prev_dt = self.timesteps[i] - prev_res.time[0]
self._prev_rates = prev_res.rates[0]
else:
prev_dt = self.timesteps[i - 1]
# Perform remaining LE/QI
inputs = list(zip(self._prev_rates, bos_rates,
repeat(prev_dt), repeat(dt)))
proc_time, inter_conc = timed_deplete(
self.chain, bos_conc, inputs, dt, matrix_func=leqi_f1)
time1, eos_conc = timed_deplete(
self.chain, inter_conc, inputs, dt, matrix_func=leqi_f2)
proc_time += time1
inter_conc = copy.deepcopy(eos_conc)
for j in range(self.n_steps + 1):
inter_res = self.operator(inter_conc, power)
if j <= 1:
res_bar = copy.deepcopy(inter_res)
else:
rates = 1 / j * inter_res.rates + (1 - 1 / j) * res_bar.rates
k = 1 / j * inter_res.k + (1 - 1 / j) * res_bar.k
res_bar = OperatorResult(k, rates)
inputs = list(zip(self._prev_rates, bos_rates, res_bar.rates,
repeat(prev_dt), repeat(dt)))
time1, inter_conc = timed_deplete(
self.chain, bos_conc, inputs, dt, matrix_func=leqi_f3)
time2, inter_conc = timed_deplete(
self.chain, inter_conc, inputs, dt, matrix_func=leqi_f4)
proc_time += time1 + time2
return proc_time, [eos_conc, inter_conc], [res_bar]

View file

@ -3,12 +3,20 @@
Contains the per-nuclide components of a depletion chain.
"""
from collections import namedtuple
import bisect
from collections.abc import Mapping
from collections import namedtuple, defaultdict
from warnings import warn
from numbers import Real
try:
import lxml.etree as ET
except ImportError:
import xml.etree.ElementTree as ET
from numpy import empty
from openmc.checkvalue import check_type
DecayTuple = namedtuple('DecayTuple', 'type target branching_ratio')
DecayTuple.__doc__ = """\
@ -61,11 +69,16 @@ except AttributeError:
class Nuclide(object):
"""Decay modes, reactions, and fission yields for a single nuclide.
Parameters
----------
name : str, optional
GND name of this nuclide, e.g. ``"He4"``, ``"Am242_m1"``
Attributes
----------
name : str
name : str or None
Name of nuclide.
half_life : float
half_life : float or None
Half life of nuclide in [s].
decay_energy : float
Energy deposited from decay in [eV].
@ -79,17 +92,16 @@ class Nuclide(object):
reactions : list of openmc.deplete.ReactionTuple
Reaction information. Each element of the list is a named tuple with
attribute 'type', 'target', 'Q', and 'branching_ratio'.
yield_data : dict of float to list
Maps tabulated energy to list of (product, yield) for all
neutron-induced fission products.
yield_energies : list of float
Energies at which fission product yiels exist
yield_data : FissionYieldDistribution or None
Fission product yields at tabulated energies for this nuclide. Can be
treated as a nested dictionary ``{energy: {product: yield}}``
yield_energies : tuple of float or None
Energies at which fission product yields exist
"""
def __init__(self):
def __init__(self, name=None):
# Information about the nuclide
self.name = None
self.name = name
self.half_life = None
self.decay_energy = 0.0
@ -100,8 +112,7 @@ class Nuclide(object):
self.reactions = []
# Neutron fission yields, if present
self.yield_data = {}
self.yield_energies = []
self._yield_data = None
@property
def n_decay_modes(self):
@ -111,6 +122,29 @@ class Nuclide(object):
def n_reaction_paths(self):
return len(self.reactions)
@property
def yield_data(self):
if self._yield_data is None:
return None
return self._yield_data
@yield_data.setter
def yield_data(self, fission_yields):
if fission_yields is None:
self._yield_data = None
else:
check_type("fission_yields", fission_yields, Mapping)
if isinstance(fission_yields, FissionYieldDistribution):
self._yield_data = fission_yields
else:
self._yield_data = FissionYieldDistribution(fission_yields)
@property
def yield_energies(self):
if self._yield_data is None:
return None
return self.yield_data.energies
@classmethod
def from_xml(cls, element, fission_q=None):
"""Read nuclide from an XML element.
@ -165,13 +199,7 @@ class Nuclide(object):
fpy_elem = element.find('neutron_fission_yields')
if fpy_elem is not None:
for yields_elem in fpy_elem.iter('fission_yields'):
E = float(yields_elem.get('energy'))
products = yields_elem.find('products').text.split()
yields = [float(y) for y in
yields_elem.find('data').text.split()]
nuc.yield_data[E] = list(zip(products, yields))
nuc.yield_energies = list(sorted(nuc.yield_data.keys()))
nuc.yield_data = FissionYieldDistribution.from_xml_element(fpy_elem)
return nuc
@ -211,14 +239,328 @@ class Nuclide(object):
fpy_elem = ET.SubElement(elem, 'neutron_fission_yields')
energy_elem = ET.SubElement(fpy_elem, 'energies')
energy_elem.text = ' '.join(str(E) for E in self.yield_energies)
for E in self.yield_energies:
yields_elem = ET.SubElement(fpy_elem, 'fission_yields')
yields_elem.set('energy', str(E))
products_elem = ET.SubElement(yields_elem, 'products')
products_elem.text = ' '.join(x[0] for x in self.yield_data[E])
data_elem = ET.SubElement(yields_elem, 'data')
data_elem.text = ' '.join(str(x[1]) for x in self.yield_data[E])
self.yield_data.to_xml_element(fpy_elem)
return elem
def validate(self, strict=True, quiet=False, tolerance=1e-4):
"""Search for possible inconsistencies
The following checks are performed:
1) for all non-fission reactions and decay modes,
does the sum of branching ratios equal about one?
2) for fission reactions, does the sum of fission yield
fractions equal about two?
Parameters
----------
strict : bool, optional
Raise exceptions at the first inconsistency if true.
Otherwise mark a warning
quiet : bool, optional
Flag to suppress warnings and return immediately at
the first inconsistency. Used only if
``strict`` does not evaluate to ``True``.
tolerance : float, optional
Absolute tolerance for comparisons. Used to compare computed
value ``x`` to intended value ``y`` as::
valid = (y - tolerance <= x <= y + tolerance)
Returns
-------
valid : bool
True if no inconsistencies were found
Raises
------
ValueError
If ``strict`` evaluates to ``True`` and an inconistency was
found
See Also
--------
openmc.deplete.Chain.validate
"""
msg_func = ("Nuclide {name} has {prop} that sum to {actual} "
"instead of {expected} +/- {tol:7.4e}").format
valid = True
# check decay modes
if self.decay_modes:
sum_br = sum(m.branching_ratio for m in self.decay_modes)
stat = 1.0 - tolerance <= sum_br <= 1.0 + tolerance
if not stat:
msg = msg_func(
name=self.name, actual=sum_br, expected=1.0, tol=tolerance,
prop="decay mode branch ratios")
if strict:
raise ValueError(msg)
elif quiet:
return False
warn(msg)
valid = False
if self.reactions:
type_map = defaultdict(set)
for reaction in self.reactions:
type_map[reaction.type].add(reaction)
for rxn_type, reactions in type_map.items():
sum_rxn = sum(rx.branching_ratio for rx in reactions)
stat = 1.0 - tolerance <= sum_rxn <= 1.0 + tolerance
if stat:
continue
msg = msg_func(
name=self.name, actual=sum_br, expected=1.0, tol=tolerance,
prop="{} reaction branch ratios".format(rxn_type))
if strict:
raise ValueError(msg)
elif quiet:
return False
warn(msg)
valid = False
if self.yield_data:
for energy, fission_yield in self.yield_data.items():
sum_yield = fission_yield.yields.sum()
stat = 2.0 - tolerance <= sum_yield <= 2.0 + tolerance
if stat:
continue
msg = msg_func(
name=self.name, actual=sum_yield,
expected=2.0, tol=tolerance,
prop="fission yields (E = {:7.4e} eV)".format(energy))
if strict:
raise ValueError(msg)
elif quiet:
return False
warn(msg)
valid = False
return valid
class FissionYieldDistribution(Mapping):
"""Energy-dependent fission product yields for a single nuclide
Can be used as a dictionary mapping energies and products to fission
yields::
>>> fydist = FissionYieldDistribution{
... {0.0253: {"Xe135": 0.021}})
>>> fydist[0.0253]["Xe135"]
0.021
Parameters
----------
fission_yields : dict
Dictionary of energies and fission product yields for that energy.
Expected to be of the form ``{float: {str: float}}``. The first
float is the energy, typically in eV, that represents this
distribution. The underlying dictionary maps fission products
to their respective yields.
Attributes
----------
energies : tuple
Energies for which fission yields exist. Sorted by
increasing energy
products : tuple
Fission products produced at all energies. Sorted by name.
yield_matrix : numpy.ndarray
Array ``(n_energy, n_products)`` where
``yield_matrix[g, j]`` is the fission yield of product
``j`` for energy group ``g``.
See Also
--------
* :meth:`from_xml_element` - Construction methods
* :class:`FissionYield` - Class used for storing yields at a given energy
"""
def __init__(self, fission_yields):
# mapping {energy: {product: value}}
energies = sorted(fission_yields)
# Get a consistent set of products to produce a matrix of yields
shared_prod = set.union(*(set(x) for x in fission_yields.values()))
ordered_prod = sorted(shared_prod)
yield_matrix = empty((len(energies), len(shared_prod)))
for g_index, energy in enumerate(energies):
prod_map = fission_yields[energy]
for prod_ix, product in enumerate(ordered_prod):
yield_val = prod_map.get(product)
yield_matrix[g_index, prod_ix] = (
0.0 if yield_val is None else yield_val)
self.energies = tuple(energies)
self.products = tuple(ordered_prod)
self.yield_matrix = yield_matrix
def __len__(self):
return len(self.energies)
def __getitem__(self, energy):
if energy not in self.energies:
raise KeyError(energy)
return FissionYield(
self.products, self.yield_matrix[self.energies.index(energy)])
def __iter__(self):
return iter(self.energies)
def __repr__(self):
return "<{} with {} products at {} energies>".format(
self.__class__.__name__, self.yield_matrix.shape[1],
len(self.energies))
@classmethod
def from_xml_element(cls, element):
"""Construct a distribution from a depletion chain xml file
Parameters
----------
element : xml.etree.ElementTree.Element
XML element to pull fission yield data from
Returns
-------
FissionYieldDistribution
"""
all_yields = {}
for elem_index, yield_elem in enumerate(element.iter("fission_yields")):
energy = float(yield_elem.get("energy"))
products = yield_elem.find("products").text.split()
yields = map(float, yield_elem.find("data").text.split())
# Get a map of products to their corresponding yield
all_yields[energy] = dict(zip(products, yields))
return cls(all_yields)
def to_xml_element(self, root):
"""Write fission yield data to an xml element
Parameters
----------
root : xml.etree.ElementTree.Element
Element to write distribution data to
"""
for energy, yield_obj in self.items():
yield_element = ET.SubElement(root, "fission_yields")
yield_element.set("energy", str(energy))
product_elem = ET.SubElement(yield_element, "products")
product_elem.text = " ".join(map(str, yield_obj.products))
data_elem = ET.SubElement(yield_element, "data")
data_elem.text = " ".join(map(str, yield_obj.yields))
class FissionYield(Mapping):
"""Mapping for fission yields of a parent at a specific energy
Separated to support nested dictionary-like behavior for
:class:`FissionYieldDistribution`, and allowing math operations
on a single vector of yields. Can in turn be used like a
dictionary to fetch fission yields.
Supports multiplication of a scalar to scale the fission
yields and addition of another set of yields.
Does not support resizing / inserting new products that do
not exist.
Parameters
----------
products : tuple of str
Products for this specific distribution
yields : numpy.ndarray
Fission product yields for each product in ``products``
Attributes
----------
products : tuple of str
Products for this specific distribution
yields : numpy.ndarray
Fission product yields for each product in ``products``
Examples
--------
>>> import numpy
>>> fy_vector = FissionYield(
... ("Xe135", "I129", "Sm149"),
... numpy.array((0.002, 0.001, 0.0003)))
>>> fy_vector["Xe135"]
0.002
>>> new = fy_vector.copy()
>>> fy_vector *= 2
>>> fy_vector["Xe135"]
0.004
>>> new["Xe135"]
0.002
>>> (new + fy_vector)["Sm149"]
0.0009
>>> dict(new)
{"Xe135": 0.002, "I129": 0.001, "Sm149": 0.0003}
"""
def __init__(self, products, yields):
self.products = products
self.yields = yields
def __contains__(self, product):
ix = bisect.bisect_left(self.products, product)
return ix != len(self.products) and self.products[ix] == product
def __getitem__(self, product):
ix = bisect.bisect_left(self.products, product)
if ix == len(self.products) or self.products[ix] != product:
raise KeyError(product)
return self.yields[ix]
def __len__(self):
return len(self.products)
def __iter__(self):
return iter(self.products)
def items(self):
"""Return pairs of product, yield"""
return zip(self.products, self.yields)
def __add__(self, other):
if not isinstance(other, FissionYield):
return NotImplemented
new = FissionYield(self.products, self.yields.copy())
new += other
return new
def __iadd__(self, other):
"""Increment value from other fission yield"""
if not isinstance(other, FissionYield):
return NotImplemented
self.yields += other.yields
return self
def __radd__(self, other):
return self + other
def __imul__(self, scalar):
if not isinstance(scalar, Real):
return NotImplemented
self.yields *= scalar
return self
def __mul__(self, scalar):
if not isinstance(scalar, Real):
return NotImplemented
new = FissionYield(self.products, self.yields.copy())
new *= scalar
return new
def __rmul__(self, scalar):
return self * scalar
def __repr__(self):
return "<{} containing {} products and yields>".format(
self.__class__.__name__, len(self))

View file

@ -16,6 +16,7 @@ import xml.etree.ElementTree as ET
import h5py
import numpy as np
from uncertainties import ufloat
import openmc
import openmc.capi
@ -23,7 +24,10 @@ from . import comm
from .abc import TransportOperator, OperatorResult
from .atom_number import AtomNumber
from .reaction_rates import ReactionRates
from .helpers import DirectReactionRateHelper, ChainFissionHelper
from .results_list import ResultsList
from .helpers import (
DirectReactionRateHelper, ChainFissionHelper, ConstantFissionYieldHelper,
FissionYieldCutoffHelper, AveragedFissionYieldHelper)
def _distribute(items):
@ -55,7 +59,7 @@ class Operator(TransportOperator):
Instances of this class can be used to perform depletion using OpenMC as the
transport operator. Normally, a user needn't call methods of this class
directly. Instead, an instance of this class is passed to an integrator
function, such as :func:`openmc.deplete.integrator.cecm`.
class, such as :class:`openmc.deplete.CECMIntegrator`.
Parameters
----------
@ -72,7 +76,8 @@ class Operator(TransportOperator):
specified, the depletion calculation will start from the latest state
in the previous results.
diff_burnable_mats : bool, optional
Whether to differentiate burnable materials with multiple instances
Whether to differentiate burnable materials with multiple instances.
Default: False.
fission_q : dict, optional
Dictionary of nuclides and their fission Q values [eV]. If not given,
values will be pulled from the ``chain_file``.
@ -81,6 +86,21 @@ class Operator(TransportOperator):
in initial condition to ensure they exist in the decay chain.
Only done for nuclides with reaction rates.
Defaults to 1.0e3.
fission_yield_mode : {"constant", "cutoff", "average"}
Key indicating what fission product yield scheme to use. The
key determines what fission energy helper is used:
* "constant": :class:`~openmc.deplete.helpers.ConstantFissionYieldHelper`
* "cutoff": :class:`~openmc.deplete.helpers.FissionYieldCutoffHelper`
* "average": :class:`~openmc.deplete.helpers.AveragedFissionYieldHelper`
The documentation on these classes describe their methodology
and differences. Default: ``"constant"``
fission_yield_opts : dict of str to option, optional
Optional arguments to pass to the helper determined by
``fission_yield_mode``. Will be passed directly on to the
helper. Passing a value of None will use the defaults for
the associated helper.
Attributes
----------
@ -111,29 +131,33 @@ class Operator(TransportOperator):
Initial heavy metal inventory
local_mats : list of str
All burnable material IDs being managed by a single process
prev_res : ResultsList
Results from a previous depletion calculation
prev_res : ResultsList or None
Results from a previous depletion calculation. ``None`` if no
results are to be used.
diff_burnable_mats : bool
Whether to differentiate burnable materials with multiple instances
"""
_fission_helpers = {
"average": AveragedFissionYieldHelper,
"constant": ConstantFissionYieldHelper,
"cutoff": FissionYieldCutoffHelper,
}
def __init__(self, geometry, settings, chain_file=None, prev_results=None,
diff_burnable_mats=False, fission_q=None,
dilute_initial=1.0e3):
super().__init__(chain_file, fission_q, dilute_initial)
dilute_initial=1.0e3, fission_yield_mode="constant",
fission_yield_opts=None):
if fission_yield_mode not in self._fission_helpers:
raise KeyError(
"fission_yield_mode must be one of {}, not {}".format(
", ".join(self._fission_helpers), fission_yield_mode))
super().__init__(chain_file, fission_q, dilute_initial, prev_results)
self.round_number = False
self.prev_res = None
self.settings = settings
self.geometry = geometry
self.diff_burnable_mats = diff_burnable_mats
if prev_results is not None:
# Reload volumes into geometry
prev_results[-1].transfer_volumes(geometry)
# Store previous results in operator
self.prev_res = prev_results
else:
self.prev_res = None
# Differentiate burnable materials with multiple instances
if self.diff_burnable_mats:
self._differentiate_burnable_mats()
@ -147,6 +171,21 @@ class Operator(TransportOperator):
self._mat_index_map = {
lm: self.burnable_mats.index(lm) for lm in self.local_mats}
if self.prev_res is not None:
# Reload volumes into geometry
prev_results[-1].transfer_volumes(geometry)
# Store previous results in operator
# Distribute reaction rates according to those tracked
# on this process
if comm.size == 1:
self.prev_res = prev_results
else:
self.prev_res = ResultsList()
mat_indexes = _distribute(range(len(self.burnable_mats)))
for res_obj in prev_results:
new_res = res_obj.distribute(self.local_mats, mat_indexes)
self.prev_res.append(new_res)
# Determine which nuclides have incident neutron data
self.nuclides_with_data = self._get_nuclides_with_data()
@ -167,7 +206,14 @@ class Operator(TransportOperator):
self.reaction_rates.n_nuc, self.reaction_rates.n_react)
self._energy_helper = ChainFissionHelper()
def __call__(self, vec, power, print_out=True):
# Select and create fission yield helper
fission_helper = self._fission_helpers[fission_yield_mode]
fission_yield_opts = (
{} if fission_yield_opts is None else fission_yield_opts)
self._yield_helper = fission_helper.from_operator(
self, **fission_yield_opts)
def __call__(self, vec, power):
"""Runs a simulation.
Parameters
@ -176,8 +222,6 @@ class Operator(TransportOperator):
Total atoms to be used in function.
power : float
Power of the reactor in [W]
print_out : bool, optional
Whether or not to print out time.
Returns
-------
@ -195,8 +239,10 @@ class Operator(TransportOperator):
# Update material compositions and tally nuclides
self._update_materials()
self._rate_helper.nuclides = self._get_tally_nuclides()
self._energy_helper.nuclides = self._rate_helper.nuclides
nuclides = self._get_tally_nuclides()
self._rate_helper.nuclides = nuclides
self._energy_helper.nuclides = nuclides
self._yield_helper.update_tally_nuclides(nuclides)
# Run OpenMC
openmc.capi.reset()
@ -207,15 +253,21 @@ class Operator(TransportOperator):
# Extract results
op_result = self._unpack_tallies_and_normalize(power)
if comm.rank == 0:
time_unpack = time.time()
if print_out:
print("Time to openmc: ", time_openmc - time_start)
print("Time to unpack: ", time_unpack - time_openmc)
return copy.deepcopy(op_result)
@staticmethod
def write_bos_data(step):
"""Write a state-point file with beginning of step data
Parameters
----------
step : int
Current depletion step including restarts
"""
openmc.capi.statepoint_write(
"openmc_simulation_n{}.h5".format(step),
write_source=False)
def _differentiate_burnable_mats(self):
"""Assign distribmats for each burnable material
@ -394,6 +446,10 @@ class Operator(TransportOperator):
self._rate_helper.generate_tallies(materials, self.chain.reactions)
self._energy_helper.prepare(
self.chain.nuclides, self.reaction_rates.index_nuc, materials)
# Tell fission yield helper what materials this process is
# responsible for
self._yield_helper.generate_tallies(
materials, tuple(sorted(self._mat_index_map.values())))
# Return number density vector
return list(self.number.get_mat_slice(np.s_[:]))
@ -525,7 +581,7 @@ class Operator(TransportOperator):
rates.fill(0.0)
# Get k and uncertainty
k_combined = openmc.capi.keff()
k_combined = ufloat(*openmc.capi.keff())
# Extract tally bins
nuclides = self._rate_helper.nuclides
@ -539,6 +595,10 @@ class Operator(TransportOperator):
# Keep track of energy produced from all reactions in eV per source
# particle
self._energy_helper.reset()
self._yield_helper.unpack()
# Store fission yield dictionaries
fission_yields = []
# Create arrays to store fission Q values, reaction rates, and nuclide
# numbers, zeroed out in material iteration
@ -561,6 +621,9 @@ class Operator(TransportOperator):
tally_rates = self._rate_helper.get_material_rates(
mat_index, nuc_ind, react_ind)
# Compute fission yields for this material
fission_yields.append(self._yield_helper.weighted_yields(i))
# Accumulate energy from fission
self._energy_helper.update(tally_rates[:, fission_ind], mat_index)
@ -574,6 +637,9 @@ class Operator(TransportOperator):
# Scale reaction rates to obtain units of reactions/sec
rates *= power / energy
# Store new fission yields on the chain
self.chain.fission_yields = fission_yields
return OperatorResult(k_combined, rates)
def _get_nuclides_with_data(self):

View file

@ -21,8 +21,8 @@ class Results(object):
Attributes
----------
k : list of float
Eigenvalue for each substep.
k : list of (float, float)
Eigenvalue and uncertainty for each substep.
time : list of float
Time at beginning, end of step, in seconds.
power : float
@ -153,6 +153,37 @@ class Results(object):
# Create storage array
self.data = np.zeros((stages, self.n_mat, self.n_nuc))
def distribute(self, local_materials, ranges):
"""Create a new object containing data for distributed materials
Parameters
----------
local_materials : iterable of str
Materials for this process
ranges : iterable of int
Slice-like object indicating indicies of ``local_materials``
in the material dimension of :attr:`data` and each element
in :attr:`rates`
Returns
-------
Results
New results object
"""
new = Results()
new.volume = {lm: self.volume[lm] for lm in local_materials}
new.mat_to_ind = dict(zip(
local_materials, range(len(local_materials))))
# Direct transfer
direct_attrs = ("time", "k", "power", "nuc_to_ind",
"mat_to_hdf5_ind", "proc_time")
for attr in direct_attrs:
setattr(new, attr, getattr(self, attr))
# Get applicable slice of data
new.data = self.data[:, ranges]
new.rates = [r[ranges] for r in self.rates]
return new
def export_to_hdf5(self, filename, step):
"""Export results to an HDF5 file
@ -425,16 +456,7 @@ class Results(object):
# Get indexing terms
vol_dict, nuc_list, burn_list, full_burn_list = op.get_results_info()
# For a restart calculation, limit number of stages saved to meet the
# format of the hdf5 file
stages = len(x)
offset = 0
if op.prev_res is not None and op.prev_res[0].n_stages < stages:
offset = stages - op.prev_res[0].n_stages
stages = min(stages, op.prev_res[0].n_stages)
warn("Number of restart integrator stages saved limited by initial"
" depletion integrator choice to {}"
.format(op.prev_res[0].n_stages))
# Create results
results = Results()
@ -444,9 +466,9 @@ class Results(object):
for i in range(stages):
for mat_i in range(n_mat):
results[i, mat_i, :] = x[offset + i][mat_i][:]
results[i, mat_i, :] = x[i][mat_i]
results.k = [r.k for r in op_results]
results.k = [(r.k.nominal_value, r.k.std_dev) for r in op_results]
results.rates = [r.rates for r in op_results]
results.time = t
results.power = power

View file

@ -8,22 +8,34 @@ from openmc.checkvalue import check_filetype_version
class ResultsList(list):
"""A list of openmc.deplete.Results objects
Parameters
----------
filename : str
The filename to read from.
It is recommended to use :meth:`from_hdf5` over
direct creation.
"""
def __init__(self, filename):
super().__init__()
@classmethod
def from_hdf5(cls, filename):
"""Load in depletion results from a previous file
Parameters
----------
filename : str
Path to depletion result file
Returns
-------
new : ResultsList
New instance of depletion results
"""
with h5py.File(str(filename), "r") as fh:
check_filetype_version(fh, 'depletion results', _VERSION_RESULTS[0])
new = cls()
# Get number of results stored
n = fh["number"][...].shape[0]
for i in range(n):
self.append(Results.from_hdf5(fh, i))
new.append(Results.from_hdf5(fh, i))
return new
def get_atoms(self, mat, nuc):
"""Get number of nuclides over time from a single material

View file

@ -6,6 +6,8 @@
# Note 32 of the 255 nuclides appeare twice as they are both activation
# nuclides (category 1) and fission product nuclides (category 3).
# Te129 has been added due to it's link to I129 production.
CASL_CHAIN = {
# Nuclide: (Stable, CAT, IFPY, Special yield treatment)
# Stable: True if nuclide has no decay reactions
@ -187,6 +189,7 @@ CASL_CHAIN = {
'Sb127': (False, 3, 2, None),
'Te127': (False, 3, -1, None),
'Te127_m1': (False, 3, -1, None),
'Te129': (False, 3, 1, None),
'Te129_m1': (False, 3, 2, None),
'Te132': (False, 3, 2, None),
'I127': (True, 3, 1, None),

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3
import glob
import os
from pathlib import Path
from zipfile import ZipFile
from openmc._utils import download
@ -15,15 +15,28 @@ URLS = [
]
def main():
for url in URLS:
basename = download(url)
with ZipFile(basename, 'r') as zf:
print('Extracting {}...'.format(basename))
zf.extractall()
endf_dir = os.environ.get("OPENMC_ENDF_DATA")
if endf_dir is not None:
endf_dir = Path(endf_dir)
elif all(os.path.isdir(lib) for lib in ("neutrons", "decay", "nfy")):
endf_dir = Path(".")
else:
for url in URLS:
basename = download(url)
with ZipFile(basename, 'r') as zf:
print('Extracting {}...'.format(basename))
zf.extractall()
endf_dir = Path(".")
decay_files = glob.glob(os.path.join('decay', '*.endf'))
nfy_files = glob.glob(os.path.join('nfy', '*.endf'))
neutron_files = glob.glob(os.path.join('neutrons', '*.endf'))
decay_files = tuple((endf_dir / "decay").glob("*endf"))
neutron_files = tuple((endf_dir / "neutrons").glob("*endf"))
nfy_files = tuple((endf_dir / "nfy").glob("*endf"))
# check files exist
for flist, ftype in [(decay_files, "decay"), (neutron_files, "neutron"),
(nfy_files, "neutron fission product yield")]:
if not flist:
raise IOError("No {} endf files found in {}".format(ftype, endf_dir))
chain = openmc.deplete.Chain.from_endf(decay_files, nfy_files, neutron_files)
chain.export_to_xml('chain_endfb71.xml')

View file

@ -16,6 +16,7 @@
#include "openmc/hdf5_interface.h"
#include "openmc/lattice.h"
#include "openmc/material.h"
#include "openmc/nuclide.h"
#include "openmc/settings.h"
#include "openmc/surface.h"
#include "openmc/xml_interface.h"
@ -244,6 +245,16 @@ Cell::temperature(int32_t instance) const
void
Cell::set_temperature(double T, int32_t instance)
{
if (settings::temperature_method == TEMPERATURE_INTERPOLATION) {
if (T < data::temperature_min) {
throw std::runtime_error{"Temperature is below minimum temperature at "
"which data is available."};
} else if (T > data::temperature_max) {
throw std::runtime_error{"Temperature is above maximum temperature at "
"which data is available."};
}
}
if (instance >= 0) {
sqrtkT_.at(instance) = std::sqrt(K_BOLTZMANN * T);
} else {
@ -1057,7 +1068,6 @@ openmc_cell_set_fill(int32_t index, int type, int32_t n,
return 0;
}
//TODO: make sure data is loaded for this temperature
extern "C" int
openmc_cell_set_temperature(int32_t index, double T, const int32_t* instance)
{

View file

@ -357,6 +357,12 @@ read_ce_cross_sections(const std::vector<std::vector<double>>& nuc_temps,
}
}
// Show minimum/maximum temperature
write_message("Minimum neutron data temperature: " +
std::to_string(data::temperature_min) + " K", 4);
write_message("Maximum neutron data temperature: " +
std::to_string(data::temperature_max) + " K", 4);
// If the user wants multipole, make sure we found a multipole library.
if (settings::temperature_multipole) {
bool mp_found = false;

View file

@ -172,7 +172,7 @@ void load_dagmc_geometry()
// notify user if UWUW materials are going to be used
if (using_uwuw) {
std::cout << "Found UWUW Materials in the DAGMC geometry file.\n";
write_message("Found UWUW Materials in the DAGMC geometry file.", 6);
}
int32_t dagmc_univ_id = 0; // universe is always 0 for DAGMC runs

View file

@ -119,6 +119,8 @@ int openmc_finalize()
data::energy_max = {INFTY, INFTY};
data::energy_min = {0.0, 0.0};
data::temperature_min = 0.0;
data::temperature_max = INFTY;
model::root_universe = -1;
openmc::openmc_set_seed(DEFAULT_SEED);
@ -127,7 +129,9 @@ int openmc_finalize()
// Free all MPI types
#ifdef OPENMC_MPI
MPI_Type_free(&mpi::bank);
int init_called;
MPI_Initialized(&init_called);
if (init_called) MPI_Type_free(&mpi::bank);
#endif
return 0;

View file

@ -8,8 +8,8 @@ int n_procs {1};
bool master {true};
#ifdef OPENMC_MPI
MPI_Comm intracomm;
MPI_Datatype bank;
MPI_Comm intracomm {MPI_COMM_NULL};
MPI_Datatype bank {MPI_DATATYPE_NULL};
#endif
extern "C" bool openmc_master() { return mpi::master; }

View file

@ -18,7 +18,7 @@
#include "xtensor/xbuilder.hpp"
#include "xtensor/xview.hpp"
#include <algorithm> // for sort
#include <algorithm> // for sort, min_element
#include <string> // for to_string, stoi
namespace openmc {
@ -30,6 +30,8 @@ namespace openmc {
namespace data {
std::array<double, 2> energy_min {0.0, 0.0};
std::array<double, 2> energy_max {INFTY, INFTY};
double temperature_min {0.0};
double temperature_max {INFTY};
std::vector<std::unique_ptr<Nuclide>> nuclides;
std::unordered_map<std::string, int> nuclide_map;
} // namespace data
@ -154,6 +156,12 @@ Nuclide::Nuclide(hid_t group, const std::vector<double>& temperature, int i_nucl
// Sort temperatures to read
std::sort(temps_to_read.begin(), temps_to_read.end());
double T_min_read = *std::min_element(temps_to_read.cbegin(), temps_to_read.cend());
double T_max_read = *std::max_element(temps_to_read.cbegin(), temps_to_read.cend());
data::temperature_min = std::max(data::temperature_min, T_min_read);
data::temperature_max = std::min(data::temperature_max, T_max_read);
hid_t energy_group = open_group(group, "energy");
for (const auto& T : temps_to_read) {
std::string dset {std::to_string(T) + "K"};

View file

@ -211,6 +211,7 @@ extern "C" void print_particle(Particle* p)
void print_plot()
{
header("PLOTTING SUMMARY", 5);
if (settings::verbosity < 5) return;
for (auto pl : model::plots) {
// Plot id
@ -453,6 +454,7 @@ void print_runtime()
// display header block
header("Timing Statistics", 6);
if (settings::verbosity < 6) return;
// Save state of cout
auto f {std::cout.flags()};
@ -537,6 +539,7 @@ void print_results()
// display header block for results
header("Results", 4);
if (settings::verbosity < 4) return;
// Calculate t-value for confidence intervals
int n = simulation::n_realizations;

View file

@ -231,6 +231,10 @@ std::string reaction_name(int mt)
return "(n,Xa)";
} else if (mt == 301) {
return "heating";
} else if (mt == 318) {
return "fission-heating";
} else if (mt == 999) {
return "non-fission-heating";
} else if (mt == 444) {
return "damage-energy";
} else if (mt == COHERENT) {

View file

@ -742,7 +742,7 @@ void write_tally_results_nr(hid_t file_id)
} else {
// Receive buffer not significant at other processors
#ifdef OPENMC_MPI
MPI_Reduce(values.data(), nullptr, values.size(), MPI_REAL8, MPI_SUM,
MPI_Reduce(values.data(), nullptr, values.size(), MPI_DOUBLE, MPI_SUM,
0, mpi::intracomm);
#endif
}

View file

@ -21,12 +21,37 @@ EnergyFunctionFilter::from_xml(pugi::xml_node node)
if (!check_for_node(node, "energy"))
fatal_error("Energy grid not specified for EnergyFunction filter.");
energy_ = get_node_array<double>(node, "energy");
auto energy = get_node_array<double>(node, "energy");
if (!check_for_node(node, "y"))
fatal_error("y values not specified for EnergyFunction filter.");
y_ = get_node_array<double>(node, "y");
auto y = get_node_array<double>(node, "y");
this->set_data(energy, y);
}
void
EnergyFunctionFilter::set_data(gsl::span<const double> energy,
gsl::span<const double> y)
{
// Check for consistent sizes with new data
if (energy.size() != y.size()) {
fatal_error("Energy grid and y values are not consistent");
}
energy_.clear();
energy_.reserve(energy.size());
y_.clear();
y_.reserve(y.size());
// Copy over energy values, ensuring they are valid
for (gsl::index i = 0; i < energy.size(); ++i) {
if (i > 0 && energy[i] <= energy[i - 1]) {
throw std::runtime_error{"Energy bins must be monotonically increasing."};
}
energy_.push_back(energy[i]);
y_.push_back(y[i]);
}
}
void
@ -65,4 +90,72 @@ EnergyFunctionFilter::text_label(int bin) const
return out.str();
}
//==============================================================================
// C-API functions
//==============================================================================
extern "C" int
openmc_energyfunc_filter_set_data(int32_t index, size_t n, const double* energy,
const double* y)
{
// Ensure this is a valid index to allocated filter
if (int err = verify_filter(index)) return err;
// Get a pointer to the filter
const auto& filt_base = model::tally_filters[index].get();
// Downcast to EnergyFunctionFilter
auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
// Check if a valid filter was produced
if (!filt) {
set_errmsg("Tried to set interpolation data for non-energy function filter.");
return OPENMC_E_INVALID_TYPE;
}
filt->set_data({energy, n}, {y, n});
return 0;
}
extern "C" int
openmc_energyfunc_filter_get_energy(int32_t index, size_t *n, const double** energy)
{
// ensure this is a valid index to allocated filter
if (int err = verify_filter(index)) return err;
// get a pointer to the filter
const auto& filt_base = model::tally_filters[index].get();
// downcast to EnergyFunctionFilter
auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
// check if a valid filter was produced
if (!filt) {
set_errmsg("Tried to set interpolation data for non-energy function filter.");
return OPENMC_E_INVALID_TYPE;
}
*energy = filt->energy().data();
*n = filt->energy().size();
return 0;
}
extern "C" int
openmc_energyfunc_filter_get_y(int32_t index, size_t *n, const double** y)
{
// ensure this is a valid index to allocated filter
if (int err = verify_filter(index)) return err;
// get a pointer to the filter
const auto& filt_base = model::tally_filters[index].get();
// downcast to EnergyFunctionFilter
auto* filt = dynamic_cast<EnergyFunctionFilter*>(filt_base);
// check if a valid filter was produced
if (!filt) {
set_errmsg("Tried to set interpolation data for non-energy function filter.");
return OPENMC_E_INVALID_TYPE;
}
*y = filt->y().data();
*n = filt->y().size();
return 0;
}
} // namespace openmc

View file

@ -171,6 +171,140 @@ score_fission_delayed_dg(int i_tally, int d_bin, double score, int score_index)
dg_match.bins_[i_bin] = original_bin;
}
//! Helper function to retrieve fission q value from a nuclide
double get_nuc_fission_q(const Nuclide& nuc, const Particle* p, int score_bin)
{
if (score_bin == SCORE_FISS_Q_PROMPT) {
if (nuc.fission_q_prompt_) {
return (*nuc.fission_q_prompt_)(p->E_last_);
}
} else if (score_bin == SCORE_FISS_Q_RECOV) {
if (nuc.fission_q_recov_) {
return (*nuc.fission_q_recov_)(p->E_last_);
}
}
return 0.0;
}
//! Helper function to score fission energy
//
//! Pulled out to support both the fission_q scores and energy deposition
//! score
double score_fission_q(const Particle* p, int score_bin, const Tally& tally,
double flux, int i_nuclide, double atom_density)
{
if (tally.estimator_ == ESTIMATOR_ANALOG) {
const Nuclide& nuc {*data::nuclides[p->event_nuclide_]};
if (settings::survival_biasing) {
// No fission events occur if survival biasing is on -- need to
// calculate fraction of absorptions that would have resulted in
// fission scaled by the Q-value
if (p->neutron_xs_[p->event_nuclide_].absorption > 0) {
return p->wgt_absorb_ * get_nuc_fission_q(nuc, p, score_bin)
* p->neutron_xs_[p->event_nuclide_].fission * flux
/ p->neutron_xs_[p->event_nuclide_].absorption;
}
} else {
// Skip any non-absorption events
if (p->event_ == EVENT_SCATTER) return 0.0;
// All fission events will contribute, so again we can use particle's
// weight entering the collision as the estimate for the fission
// reaction rate
if (p->neutron_xs_[p->event_nuclide_].absorption > 0) {
return p->wgt_last_ * get_nuc_fission_q(nuc, p, score_bin)
* p->neutron_xs_[p->event_nuclide_].fission * flux
/ p->neutron_xs_[p->event_nuclide_].absorption;
}
}
} else {
if (i_nuclide >= 0) {
const Nuclide& nuc {*data::nuclides[i_nuclide]};
return get_nuc_fission_q(nuc, p, score_bin) * atom_density * flux
* p->neutron_xs_[i_nuclide].fission;
} else {
if (p->material_ != MATERIAL_VOID) {
const Material& material {*model::materials[p->material_]};
double score {0.0};
for (auto i = 0; i < material.nuclide_.size(); ++i) {
auto j_nuclide = material.nuclide_[i];
auto atom_density = material.atom_density_(i);
const Nuclide& nuc {*data::nuclides[j_nuclide]};
score += get_nuc_fission_q(nuc, p, score_bin) * atom_density
* p->neutron_xs_[j_nuclide].fission;
}
return score * flux;
}
}
}
return 0.0;
}
//! Helper function to obtain the kerma coefficient for a given nuclide
double get_nuclide_neutron_heating(const Particle* p, const Nuclide& nuc,
int rxn_index, int i_nuclide)
{
size_t mt = nuc.reaction_index_[rxn_index];
if (mt == C_NONE) return 0.0;
auto i_temp = p->neutron_xs_[i_nuclide].index_temp;
if (i_temp < 0) return 0.0; // Can be true due to multipole
const auto& rxn {*nuc.reactions_[mt]};
const auto& xs {rxn.xs_[i_temp]};
auto i_grid = p->neutron_xs_[i_nuclide].index_grid;
if (i_grid < xs.threshold) return 0.0;
auto f = p->neutron_xs_[i_nuclide].interp_factor;
return (1.0 - f) * xs.value[i_grid-xs.threshold]
+ f * xs.value[i_grid-xs.threshold+1];
}
//! Helper function to obtain neutron heating [eV]
double score_neutron_heating(const Particle* p, const Tally& tally, double flux,
int rxn_bin, int i_nuclide, double atom_density)
{
double score;
// Get heating macroscopic "cross section"
double heating_xs;
if (i_nuclide >= 0) {
const Nuclide& nuc {*data::nuclides[i_nuclide]};
heating_xs = get_nuclide_neutron_heating(p, nuc, rxn_bin, i_nuclide);
if (tally.estimator_ == ESTIMATOR_ANALOG) {
heating_xs /= p->neutron_xs_[i_nuclide].total;
} else {
heating_xs *= atom_density;
}
} else {
if (p->material_ != MATERIAL_VOID) {
heating_xs = 0.0;
const Material& material {*model::materials[p->material_]};
for (auto i = 0; i< material.nuclide_.size(); ++i) {
int j_nuclide = material.nuclide_[i];
double atom_density {material.atom_density_(i)};
const Nuclide& nuc {*data::nuclides[j_nuclide]};
heating_xs += atom_density * get_nuclide_neutron_heating(p, nuc, rxn_bin, j_nuclide);
}
if (tally.estimator_ == ESTIMATOR_ANALOG) {
heating_xs /= p->macro_xs_.total;
}
}
}
score = heating_xs * flux;
if (tally.estimator_ == ESTIMATOR_ANALOG) {
// All events score to a heating tally bin. We actually use a
// collision estimator in place of an analog one since there is no
// reaction-wise heating cross section
if (settings::survival_biasing) {
// Account for the fact that some weight has been absorbed
score *= p->wgt_last_ + p->wgt_absorb_;
} else {
score *= p->wgt_last_;
}
}
return score;
}
//! Helper function for nu-fission tallies with energyout filters.
//
//! In this case, we may need to score to multiple bins if there were multiple
@ -323,7 +457,7 @@ void
score_general_ce(Particle* p, int i_tally, int start_index,
int filter_index, int i_nuclide, double atom_density, double flux)
{
auto& tally {*model::tallies[i_tally]};
Tally& tally {*model::tallies[i_tally]};
// Get the pre-collision energy of the particle.
auto E = p->E_last_;
@ -1032,83 +1166,8 @@ score_general_ce(Particle* p, int i_tally, int start_index,
case SCORE_FISS_Q_PROMPT:
case SCORE_FISS_Q_RECOV:
//continue;
if (p->macro_xs_.absorption == 0.) continue;
score = 0.;
if (tally.estimator_ == ESTIMATOR_ANALOG) {
if (settings::survival_biasing) {
// No fission events occur if survival biasing is on -- need to
// calculate fraction of absorptions that would have resulted in
// fission scaled by the Q-value
const auto& nuc {*data::nuclides[p->event_nuclide_]};
if (p->neutron_xs_[p->event_nuclide_].absorption > 0) {
double q_value = 0.;
if (score_bin == SCORE_FISS_Q_PROMPT) {
if (nuc.fission_q_prompt_)
q_value = (*nuc.fission_q_prompt_)(p->E_last_);
} else if (score_bin == SCORE_FISS_Q_RECOV) {
if (nuc.fission_q_recov_)
q_value = (*nuc.fission_q_recov_)(p->E_last_);
}
score = p->wgt_absorb_ * q_value
* p->neutron_xs_[p->event_nuclide_].fission
/ p->neutron_xs_[p->event_nuclide_].absorption * flux;
}
} else {
// Skip any non-absorption events
if (p->event_ == EVENT_SCATTER) continue;
// All fission events will contribute, so again we can use particle's
// weight entering the collision as the estimate for the fission
// reaction rate
const auto& nuc {*data::nuclides[p->event_nuclide_]};
if (p->neutron_xs_[p->event_nuclide_].absorption > 0) {
double q_value = 0.;
if (score_bin == SCORE_FISS_Q_PROMPT) {
if (nuc.fission_q_prompt_)
q_value = (*nuc.fission_q_prompt_)(p->E_last_);
} else if (score_bin == SCORE_FISS_Q_RECOV) {
if (nuc.fission_q_recov_)
q_value = (*nuc.fission_q_recov_)(p->E_last_);
}
score = p->wgt_last_ * q_value
* p->neutron_xs_[p->event_nuclide_].fission
/ p->neutron_xs_[p->event_nuclide_].absorption * flux;
}
}
} else {
if (i_nuclide >= 0) {
const auto& nuc {*data::nuclides[i_nuclide]};
double q_value = 0.;
if (score_bin == SCORE_FISS_Q_PROMPT) {
if (nuc.fission_q_prompt_)
q_value = (*nuc.fission_q_prompt_)(p->E_last_);
} else if (score_bin == SCORE_FISS_Q_RECOV) {
if (nuc.fission_q_recov_)
q_value = (*nuc.fission_q_recov_)(p->E_last_);
}
score = q_value * p->neutron_xs_[i_nuclide].fission
* atom_density * flux;
} else {
if (p->material_ != MATERIAL_VOID) {
const Material& material {*model::materials[p->material_]};
for (auto i = 0; i < material.nuclide_.size(); ++i) {
auto j_nuclide = material.nuclide_[i];
auto atom_density = material.atom_density_(i);
const auto& nuc {*data::nuclides[j_nuclide]};
double q_value = 0.;
if (score_bin == SCORE_FISS_Q_PROMPT) {
if (nuc.fission_q_prompt_)
q_value = (*nuc.fission_q_prompt_)(p->E_last_);
} else if (score_bin == SCORE_FISS_Q_RECOV) {
if (nuc.fission_q_recov_)
q_value = (*nuc.fission_q_recov_)(p->E_last_);
}
score += q_value * p->neutron_xs_[j_nuclide].fission
* atom_density * flux;
}
}
}
}
score = score_fission_q(p, score_bin, tally, flux, i_nuclide, atom_density);
break;
@ -1154,105 +1213,8 @@ score_general_ce(Particle* p, int i_tally, int start_index,
case SCORE_HEATING:
score = 0.;
if (p->type_ == Particle::Type::neutron) {
if (tally.estimator_ == ESTIMATOR_ANALOG) {
// All events score to a heating tally bin. We actually use a
// collision estimator in place of an analog one since there is no
// reaction-wise heating cross section
if (settings::survival_biasing) {
// We need to account for the fact that some weight was already
// absorbed
score = p->wgt_last_ + p->wgt_absorb_;
} else {
score = p->wgt_last_;
}
if (i_nuclide >= 0) {
// Calculate nuclide heating cross section
double macro_heating = 0.;
const auto& nuc {*data::nuclides[i_nuclide]};
auto m = nuc.reaction_index_[NEUTRON_HEATING];
if (m == C_NONE) continue;
const auto& rxn {*nuc.reactions_[m]};
auto i_temp = p->neutron_xs_[i_nuclide].index_temp;
if (i_temp >= 0) { // Can be false due to multipole
auto i_grid = p->neutron_xs_[i_nuclide].index_grid;
auto f = p->neutron_xs_[i_nuclide].interp_factor;
const auto& xs {rxn.xs_[i_temp]};
if (i_grid >= xs.threshold) {
macro_heating = ((1.0 - f) * xs.value[i_grid-xs.threshold]
+ f * xs.value[i_grid-xs.threshold+1]);
}
}
score *= macro_heating * flux / p->neutron_xs_[i_nuclide].total;
} else {
if (p->material_ != MATERIAL_VOID) {
// Calculate material heating cross section
double macro_heating = 0.;
const Material& material {*model::materials[p->material_]};
for (auto i = 0; i < material.nuclide_.size(); ++i) {
auto j_nuclide = material.nuclide_[i];
auto atom_density = material.atom_density_(i);
const auto& nuc {*data::nuclides[j_nuclide]};
auto m = nuc.reaction_index_[NEUTRON_HEATING];
if (m == C_NONE) continue;
const auto& rxn {*nuc.reactions_[m]};
auto i_temp = p->neutron_xs_[j_nuclide].index_temp;
if (i_temp >= 0) { // Can be false due to multipole
auto i_grid = p->neutron_xs_[j_nuclide].index_grid;
auto f = p->neutron_xs_[j_nuclide].interp_factor;
const auto& xs {rxn.xs_[i_temp]};
if (i_grid >= xs.threshold) {
macro_heating += ((1.0 - f) * xs.value[i_grid-xs.threshold]
+ f * xs.value[i_grid-xs.threshold+1]) * atom_density;
}
}
}
score *= macro_heating * flux / p->macro_xs_.total;
} else {
score = 0.;
}
}
} else {
// Calculate neutron heating cross section on-the-fly
if (i_nuclide >= 0) {
const auto& nuc {*data::nuclides[i_nuclide]};
auto m = nuc.reaction_index_[NEUTRON_HEATING];
if (m == C_NONE) continue;
const auto& rxn {*nuc.reactions_[m]};
auto i_temp = p->neutron_xs_[i_nuclide].index_temp;
if (i_temp >= 0) { // Can be false due to multipole
auto i_grid = p->neutron_xs_[i_nuclide].index_grid;
auto f = p->neutron_xs_[i_nuclide].interp_factor;
const auto& xs {rxn.xs_[i_temp]};
if (i_grid >= xs.threshold) {
score = ((1.0 - f) * xs.value[i_grid-xs.threshold]
+ f * xs.value[i_grid-xs.threshold+1]) * atom_density * flux;
}
}
} else {
if (p->material_ != MATERIAL_VOID) {
const Material& material {*model::materials[p->material_]};
for (auto i = 0; i < material.nuclide_.size(); ++i) {
auto j_nuclide = material.nuclide_[i];
auto atom_density = material.atom_density_(i);
const auto& nuc {*data::nuclides[j_nuclide]};
auto m = nuc.reaction_index_[NEUTRON_HEATING];
if (m == C_NONE) continue;
const auto& rxn {*nuc.reactions_[m]};
auto i_temp = p->neutron_xs_[j_nuclide].index_temp;
if (i_temp >= 0) { // Can be false due to multipole
auto i_grid = p->neutron_xs_[j_nuclide].index_grid;
auto f = p->neutron_xs_[j_nuclide].interp_factor;
const auto& xs {rxn.xs_[i_temp]};
if (i_grid >= xs.threshold) {
score += ((1.0 - f) * xs.value[i_grid-xs.threshold]
+ f * xs.value[i_grid-xs.threshold+1]) * atom_density
* flux;
}
}
}
}
}
}
score = score_neutron_heating(p, tally, flux, NEUTRON_HEATING,
i_nuclide, atom_density);
} else if (p->type_ == Particle::Type::photon) {
if (tally.estimator_ == ESTIMATOR_ANALOG) {
// Score direct energy deposition in the collision

View file

@ -1,7 +1,119 @@
from collections import namedtuple
import numpy as np
import scipy.sparse as sp
from uncertainties import ufloat
from openmc.deplete.reaction_rates import ReactionRates
from openmc.deplete.abc import TransportOperator, OperatorResult
from openmc.deplete import (
CECMIntegrator, PredictorIntegrator, CELIIntegrator, LEQIIntegrator,
EPCRK4Integrator, CF4Integrator, SICELIIntegrator, SILEQIIntegrator
)
# Bundle for nicely passing test data to depletion unit tests
# solver should be a concrete subclass of openmc.deplete.abc.Integrator
# atoms_1 should be the number of atoms of type 1 through the simulation
# similar for atoms_2, but for type 2. This includes the first step
# Solutions should be the exact solution that can be obtained using
# the DummyOperator depletion matrix with two 0.75 second time steps
DepletionSolutionTuple = namedtuple(
"DepletionSolutionTuple", "solver atoms_1 atoms_2")
predictor_solution = DepletionSolutionTuple(
PredictorIntegrator, np.array([1.0, 2.46847546272295, 4.11525874568034]),
np.array([1.0, 0.986431226850467, -0.0581692232513460]))
cecm_solution = DepletionSolutionTuple(
CECMIntegrator, np.array([1.0, 1.86872629872102, 2.18097439443550]),
np.array([1.0, 1.395525772416039, 2.69429754646747]))
cf4_solution = DepletionSolutionTuple(
CF4Integrator, np.array([1.0, 2.06101629, 2.57241318]),
np.array([1.0, 1.37783588, 2.63731630]))
epc_rk4_solution = DepletionSolutionTuple(
EPCRK4Integrator, np.array([1.0, 2.01978516, 2.05246421]),
np.array([1.0, 1.42038037, 3.06177191]))
celi_solution = DepletionSolutionTuple(
CELIIntegrator, np.array([1.0, 1.82078767, 2.68441779]),
np.array([1.0, 0.97122898, 0.05125966]))
si_celi_solution = DepletionSolutionTuple(
SICELIIntegrator, np.array([1.0, 2.03325094, 2.69291933]),
np.array([1.0, 1.16826254, 0.37907772]))
leqi_solution = DepletionSolutionTuple(
LEQIIntegrator, np.array([1.0, 1.82078767, 2.74526197]),
np.array([1.0, 0.97122898, 0.23339915]))
si_leqi_solution = DepletionSolutionTuple(
SILEQIIntegrator, np.array([1.0, 2.03325094, 2.92711288]),
np.array([1.0, 1.16826254, 0.53753236]))
SCHEMES = {
"predictor": predictor_solution,
"cecm": cecm_solution,
"celi": celi_solution,
"cf4": cf4_solution,
"epc_rk4": epc_rk4_solution,
"leqi": leqi_solution,
"si_leqi": si_leqi_solution,
"si_celi": si_celi_solution,
}
class TestChain(object):
"""Empty chain to assist with unit testing depletion routines
Only really provides the form_matrix function, but acts like
a real Chain
"""
fission_yields = [None]
@staticmethod
def get_thermal_fission_yields():
return None
def form_matrix(self, rates, _fission_yields=None):
"""Forms the f(y) matrix in y' = f(y)y.
Nominally a depletion matrix, this is abstracted on the off chance
that the function f has nothing to do with depletion at all.
Parameters
----------
rates : numpy.ndarray
Slice of reaction rates for a single material
_fission_yields : optional
Not used
Returns
-------
scipy.sparse.csr_matrix
Sparse matrix representing f(y).
"""
y_1 = rates[0, 0]
y_2 = rates[1, 0]
a11 = np.sin(y_2)
a12 = np.cos(y_1)
a21 = -np.cos(y_2)
a22 = np.sin(y_1)
return sp.csr_matrix(np.array([[a11, a12], [a21, a22]]))
class DummyOperator(TransportOperator):
@ -19,6 +131,8 @@ class DummyOperator(TransportOperator):
"""
def __init__(self, previous_results=None):
self.prev_res = previous_results
self.chain = TestChain()
self.output_dir = "."
def __call__(self, vec, power, print_out=False):
"""Evaluates F(y)
@ -48,39 +162,7 @@ class DummyOperator(TransportOperator):
reaction_rates[0, 1, 0] = vec[0][1]
# Create a fake rates object
return OperatorResult(0.0, reaction_rates)
@property
def chain(self):
return self
def form_matrix(self, rates):
"""Forms the f(y) matrix in y' = f(y)y.
Nominally a depletion matrix, this is abstracted on the off chance
that the function f has nothing to do with depletion at all.
Parameters
----------
rates : numpy.ndarray
Slice of reaction rates for a single material
Returns
-------
scipy.sparse.csr_matrix
Sparse matrix representing f(y).
"""
y_1 = rates[0, 0]
y_2 = rates[1, 0]
mat = np.zeros((2, 2))
a11 = np.sin(y_2)
a12 = np.cos(y_1)
a21 = -np.cos(y_2)
a22 = np.sin(y_1)
return sp.csr_matrix(np.array([[a11, a12], [a21, a22]]))
return OperatorResult(ufloat(0.0, 0.0), reaction_rates)
@property
def volume(self):
@ -104,7 +186,8 @@ class DummyOperator(TransportOperator):
def local_mats(self):
"""
local_mats : list of str
A list of all material IDs to be burned. Used for sorting the simulation.
A list of all material IDs to be burned. Used for sorting the
simulation.
"""
return ["1"]
@ -114,6 +197,9 @@ class DummyOperator(TransportOperator):
"""Maps cell name to index in global geometry."""
return self.local_mats
@staticmethod
def write_bos_data(_step):
"""Empty method but avoids calls to C API"""
@property
def reaction_rates(self):
@ -148,7 +234,8 @@ class DummyOperator(TransportOperator):
nuc_list : list of str
A list of all nuclide names. Used for sorting the simulation.
burn_list : list of int
A list of all cell IDs to be burned. Used for sorting the simulation.
A list of all cell IDs to be burned. Used for sorting the
simulation.
full_burn_list : OrderedDict of str to int
Maps cell name to index in global geometry.

View file

@ -39,7 +39,7 @@ def test_full(run_in_tmpdir):
space = openmc.stats.Box(lower_left, upper_right)
settings.source = openmc.Source(space=space)
settings.seed = 1
settings.verbosity = 3
settings.verbosity = 1
# Create operator
chain_file = Path(__file__).parents[2] / 'chain_simple.xml'
@ -54,7 +54,7 @@ def test_full(run_in_tmpdir):
power = 2.337e15*4*JOULE_PER_EV*1e6 # MeV/second cm from CASMO
# Perform simulation using the predictor algorithm
openmc.deplete.integrator.predictor(op, dt, power)
openmc.deplete.PredictorIntegrator(op, dt, power).integrate()
# Get path to test and reference results
path_test = op.output_dir / 'depletion_results.h5'
@ -66,8 +66,8 @@ def test_full(run_in_tmpdir):
return
# Load the reference/test results
res_test = openmc.deplete.ResultsList(path_test)
res_ref = openmc.deplete.ResultsList(path_reference)
res_test = openmc.deplete.ResultsList.from_hdf5(path_test)
res_ref = openmc.deplete.ResultsList.from_hdf5(path_reference)
# Assert same mats
for mat in res_ref[0].mat_to_ind:
@ -101,3 +101,18 @@ def test_full(run_in_tmpdir):
assert correct, "Discrepancy in mat {} and nuc {}\n{}\n{}".format(
mat, nuc, y_old, y_test)
# Compare statepoint files with depletion results
t_test, k_test = res_test.get_eigenvalue()
t_ref, k_ref = res_ref.get_eigenvalue()
k_state = np.empty_like(k_ref)
# Get statepoint files for all BOS points and EOL
for n in range(N + 1):
statepoint = openmc.StatePoint("openmc_simulation_n{}.h5".format(n))
k_n = statepoint.k_combined
k_state[n] = [k_n.nominal_value, k_n.std_dev]
# Look for exact match pulling from statepoint and depletion_results
assert np.all(k_state == k_test)
assert np.allclose(k_test, k_ref)

View file

@ -1,5 +0,0 @@
<?xml version="1.0"?>
<geometry>
<surface id="1" type="sphere" coeffs="0 0 0 100" boundary="vacuum"/>
<cell id="1" material="1" region="-1" />
</geometry>

View file

@ -0,0 +1,23 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell id="1" material="1" region="-1" universe="1" />
<surface boundary="reflective" coeffs="0.0 0.0 0.0 100.0" id="1" type="sphere" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1">
<density units="g/cm3" value="20.0" />
<nuclide ao="1.0" name="U233" />
<nuclide ao="1.0" name="Am244" />
<nuclide ao="1.0" name="H2" />
<nuclide ao="1.0" name="Na23" />
<nuclide ao="1.0" name="Ta181" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>1000</particles>
<batches>10</batches>
<inactive>5</inactive>
</settings>

View file

@ -1,10 +0,0 @@
<?xml version="1.0"?>
<materials>
<material id="1">
<density value="20" units="g/cc" />
<nuclide name="U233" ao="1.0" />
<nuclide name="H2" ao="1.0" />
<nuclide name="Na23" ao="1.0" />
<nuclide name="Ta181" ao="1.0" />
</material>
</materials>

View file

@ -1,2 +1,2 @@
k-combined:
2.122164E+00 1.946222E-02
2.466441E+00 1.500183E-02

View file

@ -1,10 +0,0 @@
<?xml version="1.0"?>
<settings>
<run_mode>eigenvalue</run_mode>
<batches>10</batches>
<inactive>5</inactive>
<particles>1000</particles>
<source>
<space type="point" parameters="0. 0. 0." />
</source>
</settings>

View file

@ -2,23 +2,51 @@
are not covered in other tests. It has a single material with the following
nuclides:
U-233: Only nuclide that has a Watt fission spectrum
U233: Only nuclide that has a Watt fission spectrum
H-2: Only nuclide that has an N-body phase space distribution, in this case for
Am244: One of a few nuclides that has a Maxwell fission spectrum
H2: Only nuclide that has an N-body phase space distribution, in this case for
(n,2n)
Na-23: Has an evaporation spectrum and also has reactions that have multiple
Na23: Has an evaporation spectrum and also has reactions that have multiple
angle-energy distributions, so it provides coverage for both of those
situations.
Ta-181: One of a few nuclides that has reactions with Kalbach-Mann distributions
Ta181: One of a few nuclides that has reactions with Kalbach-Mann distributions
that use linear-linear interpolation.
"""
from tests.testing_harness import TestHarness
import openmc
import pytest
from tests.testing_harness import PyAPITestHarness
def test_energy_laws():
harness = TestHarness('statepoint.10.h5')
@pytest.fixture
def model():
model = openmc.model.Model()
m = openmc.Material()
m.set_density('g/cm3', 20.0)
m.add_nuclide('U233', 1.0)
m.add_nuclide('Am244', 1.0)
m.add_nuclide('H2', 1.0)
m.add_nuclide('Na23', 1.0)
m.add_nuclide('Ta181', 1.0)
s = openmc.Sphere(r=100.0, boundary_type='reflective')
c = openmc.Cell(fill=m, region=-s)
model.geometry = openmc.Geometry([c])
model.settings.batches = 10
model.settings.inactive = 5
model.settings.particles = 1000
return model
def test_energy_laws(model):
harness = PyAPITestHarness('statepoint.10.h5', model)
harness.main()

View file

@ -1,312 +1,21 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell fill="200" id="1" region="-6 34 -35" universe="0" />
<cell fill="201" id="2" region="-6 35 -36" universe="0" />
<cell id="3" material="8" region="-7 31 -32" universe="0" />
<cell id="4" material="9" region="-5 32 -33" universe="0" />
<cell id="5" material="12" region="-5 33 -34" universe="0" />
<cell id="6" material="11" region="-5 36 -37" universe="0" />
<cell id="7" material="10" region="-5 37 -38" universe="0" />
<cell id="8" material="7" region="-7 38 -39" universe="0" />
<cell id="9" material="9" region="6 -7 32 -38" universe="0" />
<cell id="10" material="5" region="7 -8 31 -39" universe="0" />
<cell id="11" material="6" region="5 -6 32 -34" universe="0" />
<cell id="12" material="7" region="5 -6 36 -38" universe="0" />
<cell id="21" material="1" region="-1" universe="1" />
<cell id="22" material="2" region="1 -2" universe="1" />
<cell id="23" material="3" region="2" universe="1" />
<cell id="24" material="3" region="-3" universe="2" />
<cell id="25" material="2" region="3 -4" universe="2" />
<cell id="26" material="3" region="4" universe="2" />
<cell id="27" material="1" region="-1" universe="3" />
<cell id="28" material="2" region="1 -2" universe="3" />
<cell id="29" material="4" region="2" universe="3" />
<cell id="30" material="4" region="-3" universe="4" />
<cell id="31" material="2" region="3 -4" universe="4" />
<cell id="32" material="4" region="4" universe="4" />
<cell id="50" material="3" region="34 -35" universe="5" />
<cell fill="100" id="60" region="34 -35" universe="6" />
<cell id="70" material="4" region="35 -36" universe="7" />
<cell fill="101" id="80" region="35 -36" universe="8" />
<lattice id="100" name="Fuel assembly (lower half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 </universes>
</lattice>
<lattice id="101" name="Fuel assembly (upper half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </universes>
</lattice>
<lattice id="200" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 </universes>
</lattice>
<lattice id="201" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 </universes>
</lattice>
<surface coeffs="0.0 0.0 0.41" id="1" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.475" id="2" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.56" id="3" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.62" id="4" type="z-cylinder" />
<surface coeffs="0.0 0.0 187.6" id="5" type="z-cylinder" />
<surface coeffs="0.0 0.0 209.0" id="6" type="z-cylinder" />
<surface coeffs="0.0 0.0 229.0" id="7" type="z-cylinder" />
<surface boundary="vacuum" coeffs="0.0 0.0 249.0" id="8" type="z-cylinder" />
<surface boundary="vacuum" coeffs="-229.0" id="31" type="z-plane" />
<surface coeffs="-199.0" id="32" type="z-plane" />
<surface coeffs="-193.0" id="33" type="z-plane" />
<surface coeffs="-183.0" id="34" type="z-plane" />
<surface coeffs="0.0" id="35" type="z-plane" />
<surface coeffs="183.0" id="36" type="z-plane" />
<surface coeffs="203.0" id="37" type="z-plane" />
<surface coeffs="215.0" id="38" type="z-plane" />
<surface boundary="vacuum" coeffs="223.0" id="39" type="z-plane" />
<cell id="1" material="1" region="-1" universe="1" />
<surface boundary="vacuum" coeffs="0.0 0.0 0.0 100.0" id="1" type="sphere" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1" name="UOX fuel">
<density units="g/cm3" value="10.062" />
<nuclide ao="4.9476e-06" name="U234" />
<nuclide ao="0.00048218" name="U235" />
<nuclide ao="0.021504" name="U238" />
<nuclide ao="1.0801e-08" name="Xe135" />
<nuclide ao="0.045737" name="O16" />
</material>
<material depletable="true" id="2" name="Zircaloy">
<density units="g/cm3" value="5.77" />
<nuclide ao="0.5145" name="Zr90" />
<nuclide ao="0.1122" name="Zr91" />
<nuclide ao="0.1715" name="Zr92" />
<nuclide ao="0.1738" name="Zr94" />
<nuclide ao="0.028" name="Zr96" />
<nuclide ao="1e-07" name="Am241" />
</material>
<material id="3" name="Cold borated water">
<density units="atom/b-cm" value="0.07416" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="4" name="Hot borated water">
<density units="atom/b-cm" value="0.06614" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="5" name="Reactor pressure vessel steel">
<density units="g/cm3" value="7.9" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
</material>
<material id="6" name="Lower radial reflector">
<density units="g/cm3" value="4.32" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-05" />
<nuclide name="B11" wo="0.000140499" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Mn55" wo="0.018287" />
<nuclide name="Cr52" wo="0.145407678031" />
<sab name="c_H_in_H2O" />
</material>
<material id="7" name="Upper radial reflector / Top plate region">
<density units="g/cm3" value="4.28" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-05" />
<nuclide name="B11" wo="0.000126481" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Cr52" wo="0.146766614995" />
<sab name="c_H_in_H2O" />
</material>
<material id="8" name="Bottom plate region">
<density units="g/cm3" value="7.184" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-06" />
<nuclide name="B11" wo="1.68974e-05" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Mn55" wo="0.019794" />
<nuclide name="Cr52" wo="0.157390026871" />
<sab name="c_H_in_H2O" />
</material>
<material id="9" name="Bottom nozzle region">
<density units="g/cm3" value="2.53" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-05" />
<nuclide name="B11" wo="0.000359854" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Cr52" wo="0.124142524198" />
<sab name="c_H_in_H2O" />
</material>
<material id="10" name="Top nozzle region">
<density units="g/cm3" value="1.746" />
<nuclide name="H1" wo="0.035887" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="0.000115699" />
<nuclide name="B11" wo="0.000527075" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Cr52" wo="0.107931450781" />
<sab name="c_H_in_H2O" />
</material>
<material id="11" name="Top of fuel assemblies">
<density units="g/cm3" value="3.044" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-05" />
<nuclide name="B11" wo="0.000239272" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<material id="12" name="Bottom of fuel assemblies">
<density units="g/cm3" value="1.762" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-05" />
<nuclide name="B11" wo="0.00043012" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
<material depletable="true" id="1">
<density units="g/cm3" value="10.0" />
<nuclide ao="1.0" name="Am241" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<batches>10</batches>
<inactive>5</inactive>
<source strength="1.0">
<space type="box">
<parameters>-160 -160 -183 160 160 183</parameters>
</space>
</source>
<particles>1000</particles>
<batches>5</batches>
<inactive>0</inactive>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>

View file

@ -1,2 +1,2 @@
energyfunction nuclide score mean std. dev.
0 d2effa26cb3cf2 Am241 ((n,gamma) / (n,gamma)) 1.00e-01 9.97e-03
0 d2effa26cb3cf2 Am241 ((n,gamma) / (n,gamma)) 1.74e-01 3.55e-03

View file

@ -1,36 +1,51 @@
import openmc
import pytest
from tests.testing_harness import PyAPITestHarness
@pytest.fixture
def model():
model = openmc.model.Model()
m = openmc.Material()
m.set_density('g/cm3', 10.0)
m.add_nuclide('Am241', 1.0)
model.materials.append(m)
s = openmc.Sphere(r=100.0, boundary_type='vacuum')
c = openmc.Cell(fill=m, region=-s)
model.geometry = openmc.Geometry([c])
model.settings.batches = 5
model.settings.inactive = 0
model.settings.particles = 1000
# Define Am242m / Am242 branching ratio from ENDF/B-VII.1 data.
x = [1e-5, 3.69e-1, 1e3, 1e5, 6e5, 1e6, 2e6, 4e6, 3e7]
y = [0.1, 0.1, 0.1333, 0.158, 0.18467, 0.25618, 0.4297, 0.48, 0.48]
# Make an EnergyFunctionFilter directly from the x and y lists.
filt1 = openmc.EnergyFunctionFilter(x, y)
# Also make a filter with the .from_tabulated1d constructor. Make sure
# the filters are identical.
tab1d = openmc.data.Tabulated1D(x, y)
filt2 = openmc.EnergyFunctionFilter.from_tabulated1d(tab1d)
assert filt1 == filt2, 'Error with the .from_tabulated1d constructor'
# Make tallies
tallies = [openmc.Tally(), openmc.Tally()]
for t in tallies:
t.scores = ['(n,gamma)']
t.nuclides = ['Am241']
tallies[1].filters = [filt1]
model.tallies.extend(tallies)
return model
class FilterEnergyFunHarness(PyAPITestHarness):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Add Am241 to the fuel.
self._model.materials[1].add_nuclide('Am241', 1e-7)
# Define Am242m / Am242 branching ratio from ENDF/B-VII.1 data.
x = [1e-5, 3.69e-1, 1e3, 1e5, 6e5, 1e6, 2e6, 4e6, 3e7]
y = [0.1, 0.1, 0.1333, 0.158, 0.18467, 0.25618, 0.4297, 0.48, 0.48]
# Make an EnergyFunctionFilter directly from the x and y lists.
filt1 = openmc.EnergyFunctionFilter(x, y)
# Also make a filter with the .from_tabulated1d constructor. Make sure
# the filters are identical.
tab1d = openmc.data.Tabulated1D(x, y)
filt2 = openmc.EnergyFunctionFilter.from_tabulated1d(tab1d)
assert filt1 == filt2, 'Error with the .from_tabulated1d constructor'
# Make tallies.
tallies = [openmc.Tally(1), openmc.Tally(2)]
for t in tallies:
t.scores = ['(n,gamma)']
t.nuclides = ['Am241']
tallies[1].filters = [filt1]
self._model.tallies = tallies
def _get_results(self):
# Read the statepoint file.
sp = openmc.StatePoint(self._sp_name)
@ -42,6 +57,6 @@ class FilterEnergyFunHarness(PyAPITestHarness):
return br_tally.get_pandas_dataframe().to_string() + '\n'
def test_filter_energyfun():
harness = FilterEnergyFunHarness('statepoint.10.h5')
def test_filter_energyfun(model):
harness = FilterEnergyFunHarness('statepoint.5.h5', model)
harness.main()

View file

@ -1,333 +1,57 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell fill="200" id="1" region="-6 34 -35" universe="0" />
<cell fill="201" id="2" region="-6 35 -36" universe="0" />
<cell id="3" material="8" region="-7 31 -32" universe="0" />
<cell id="4" material="9" region="-5 32 -33" universe="0" />
<cell id="5" material="12" region="-5 33 -34" universe="0" />
<cell id="6" material="11" region="-5 36 -37" universe="0" />
<cell id="7" material="10" region="-5 37 -38" universe="0" />
<cell id="8" material="7" region="-7 38 -39" universe="0" />
<cell id="9" material="9" region="6 -7 32 -38" universe="0" />
<cell id="10" material="5" region="7 -8 31 -39" universe="0" />
<cell id="11" material="6" region="5 -6 32 -34" universe="0" />
<cell id="12" material="7" region="5 -6 36 -38" universe="0" />
<cell id="21" material="1" region="-1" universe="1" />
<cell id="22" material="2" region="1 -2" universe="1" />
<cell id="23" material="3" region="2" universe="1" />
<cell id="24" material="3" region="-3" universe="2" />
<cell id="25" material="2" region="3 -4" universe="2" />
<cell id="26" material="3" region="4" universe="2" />
<cell id="27" material="1" region="-1" universe="3" />
<cell id="28" material="2" region="1 -2" universe="3" />
<cell id="29" material="4" region="2" universe="3" />
<cell id="30" material="4" region="-3" universe="4" />
<cell id="31" material="2" region="3 -4" universe="4" />
<cell id="32" material="4" region="4" universe="4" />
<cell id="50" material="3" region="34 -35" universe="5" />
<cell fill="100" id="60" region="34 -35" universe="6" />
<cell id="70" material="4" region="35 -36" universe="7" />
<cell fill="101" id="80" region="35 -36" universe="8" />
<lattice id="100" name="Fuel assembly (lower half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 </universes>
</lattice>
<lattice id="101" name="Fuel assembly (upper half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </universes>
</lattice>
<lattice id="200" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 </universes>
</lattice>
<lattice id="201" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 </universes>
</lattice>
<surface coeffs="0.0 0.0 0.41" id="1" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.475" id="2" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.56" id="3" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.62" id="4" type="z-cylinder" />
<surface coeffs="0.0 0.0 187.6" id="5" type="z-cylinder" />
<surface coeffs="0.0 0.0 209.0" id="6" type="z-cylinder" />
<surface coeffs="0.0 0.0 229.0" id="7" type="z-cylinder" />
<surface boundary="vacuum" coeffs="0.0 0.0 249.0" id="8" type="z-cylinder" />
<surface boundary="vacuum" coeffs="-229.0" id="31" type="z-plane" />
<surface coeffs="-199.0" id="32" type="z-plane" />
<surface coeffs="-193.0" id="33" type="z-plane" />
<surface coeffs="-183.0" id="34" type="z-plane" />
<surface coeffs="0.0" id="35" type="z-plane" />
<surface coeffs="183.0" id="36" type="z-plane" />
<surface coeffs="203.0" id="37" type="z-plane" />
<surface coeffs="215.0" id="38" type="z-plane" />
<surface boundary="vacuum" coeffs="223.0" id="39" type="z-plane" />
<cell id="1" material="1" region="1 -2 3 -4 10 -9" universe="1" />
<cell id="2" material="2" region="~(1 -2 3 -4) (5 -6 7 -8) 10 -9" universe="1" />
<surface coeffs="-5.0" id="1" name="minimum x" type="x-plane" />
<surface coeffs="5.0" id="2" name="maximum x" type="x-plane" />
<surface coeffs="-5.0" id="3" name="minimum y" type="y-plane" />
<surface coeffs="5.0" id="4" name="maximum y" type="y-plane" />
<surface boundary="reflective" coeffs="-10.0" id="5" name="minimum x" type="x-plane" />
<surface boundary="reflective" coeffs="10.0" id="6" name="maximum x" type="x-plane" />
<surface boundary="reflective" coeffs="-10.0" id="7" name="minimum y" type="y-plane" />
<surface boundary="reflective" coeffs="10.0" id="8" name="maximum y" type="y-plane" />
<surface boundary="vacuum" coeffs="10.0" id="9" type="z-plane" />
<surface boundary="vacuum" coeffs="-10.0" id="10" type="z-plane" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1" name="UOX fuel">
<density units="g/cm3" value="10.062" />
<nuclide ao="4.9476e-06" name="U234" />
<nuclide ao="0.00048218" name="U235" />
<nuclide ao="0.021504" name="U238" />
<nuclide ao="1.0801e-08" name="Xe135" />
<nuclide ao="0.045737" name="O16" />
<material depletable="true" id="1">
<density units="g/cm3" value="10.0" />
<nuclide ao="1.0" name="U235" />
</material>
<material id="2" name="Zircaloy">
<density units="g/cm3" value="5.77" />
<nuclide ao="0.5145" name="Zr90" />
<nuclide ao="0.1122" name="Zr91" />
<nuclide ao="0.1715" name="Zr92" />
<nuclide ao="0.1738" name="Zr94" />
<nuclide ao="0.028" name="Zr96" />
</material>
<material id="3" name="Cold borated water">
<density units="atom/b-cm" value="0.07416" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="4" name="Hot borated water">
<density units="atom/b-cm" value="0.06614" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="5" name="Reactor pressure vessel steel">
<density units="g/cm3" value="7.9" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
</material>
<material id="6" name="Lower radial reflector">
<density units="g/cm3" value="4.32" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-05" />
<nuclide name="B11" wo="0.000140499" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Mn55" wo="0.018287" />
<nuclide name="Cr52" wo="0.145407678031" />
<sab name="c_H_in_H2O" />
</material>
<material id="7" name="Upper radial reflector / Top plate region">
<density units="g/cm3" value="4.28" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-05" />
<nuclide name="B11" wo="0.000126481" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Cr52" wo="0.146766614995" />
<sab name="c_H_in_H2O" />
</material>
<material id="8" name="Bottom plate region">
<density units="g/cm3" value="7.184" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-06" />
<nuclide name="B11" wo="1.68974e-05" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Mn55" wo="0.019794" />
<nuclide name="Cr52" wo="0.157390026871" />
<sab name="c_H_in_H2O" />
</material>
<material id="9" name="Bottom nozzle region">
<density units="g/cm3" value="2.53" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-05" />
<nuclide name="B11" wo="0.000359854" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Cr52" wo="0.124142524198" />
<sab name="c_H_in_H2O" />
</material>
<material id="10" name="Top nozzle region">
<density units="g/cm3" value="1.746" />
<nuclide name="H1" wo="0.035887" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="0.000115699" />
<nuclide name="B11" wo="0.000527075" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Cr52" wo="0.107931450781" />
<sab name="c_H_in_H2O" />
</material>
<material id="11" name="Top of fuel assemblies">
<density units="g/cm3" value="3.044" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-05" />
<nuclide name="B11" wo="0.000239272" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<material id="12" name="Bottom of fuel assemblies">
<density units="g/cm3" value="1.762" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-05" />
<nuclide name="B11" wo="0.00043012" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
<material id="2">
<density units="g/cm3" value="1.0" />
<nuclide ao="1.0" name="Zr90" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<batches>10</batches>
<inactive>5</inactive>
<source strength="1.0">
<space type="box">
<parameters>-160 -160 -183 160 160 183</parameters>
</space>
</source>
<particles>1000</particles>
<batches>5</batches>
<inactive>0</inactive>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>
<mesh id="1">
<dimension>17</dimension>
<lower_left>-182.07</lower_left>
<upper_right>182.07</upper_right>
<dimension>5</dimension>
<lower_left>-7.5</lower_left>
<upper_right>7.5</upper_right>
</mesh>
<mesh id="2">
<dimension>17 17</dimension>
<lower_left>-182.07 -182.07</lower_left>
<upper_right>182.07 182.07</upper_right>
<dimension>5 5</dimension>
<lower_left>-7.5 -7.5</lower_left>
<upper_right>7.5 7.5</upper_right>
</mesh>
<mesh id="3">
<dimension>17 17 17</dimension>
<lower_left>-182.07 -182.07 -183.0</lower_left>
<upper_right>182.07 182.07 183.0</upper_right>
<dimension>5 5 5</dimension>
<lower_left>-7.5 -7.5 -7.5</lower_left>
<upper_right>7.5 7.5 7.5</upper_right>
</mesh>
<mesh id="4" type="rectilinear">
<x_grid>-182.07 -160.65 -139.23 -117.81 -96.39 -74.97 -53.55000000000001 -32.129999999999995 -10.710000000000008 10.70999999999998 32.129999999999995 53.54999999999998 74.96999999999997 96.38999999999999 117.81 139.22999999999996 160.64999999999998 182.07</x_grid>
<y_grid>-182.07 -160.65 -139.23 -117.81 -96.39 -74.97 -53.55000000000001 -32.129999999999995 -10.710000000000008 10.70999999999998 32.129999999999995 53.54999999999998 74.96999999999997 96.38999999999999 117.81 139.22999999999996 160.64999999999998 182.07</y_grid>
<z_grid>1.0 1.683624003879018 2.8345897864376153 4.772383405596668 8.034899257376447 13.52774925846868 22.77564337001445 38.34561988154435 64.55960607618856 108.69410247084474 182.99999999999991</z_grid>
<x_grid>-7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5</x_grid>
<y_grid>-7.5 -6.617647058823529 -5.735294117647059 -4.852941176470589 -3.9705882352941178 -3.0882352941176467 -2.2058823529411766 -1.3235294117647065 -0.4411764705882355 0.4411764705882355 1.3235294117647065 2.2058823529411757 3.0882352941176467 3.9705882352941178 4.852941176470587 5.735294117647058 6.617647058823529 7.5</y_grid>
<z_grid>1.0 1.223224374241637 1.4962778697388448 1.8302835609029084 2.2388474634702153 2.7386127875258306 3.3499379133114306 4.09772570775871 5.012437964687018 6.131336292779302 7.500000000000001</z_grid>
</mesh>
<filter id="1" type="mesh">
<bins>1</bins>
@ -353,35 +77,35 @@
<filter id="8" type="meshsurface">
<bins>4</bins>
</filter>
<tally id="1" name="tally 1">
<tally id="1">
<filters>1</filters>
<scores>total</scores>
</tally>
<tally id="2" name="tally 2">
<tally id="2">
<filters>5</filters>
<scores>current</scores>
</tally>
<tally id="3" name="tally 3">
<tally id="3">
<filters>2</filters>
<scores>total</scores>
</tally>
<tally id="4" name="tally 4">
<tally id="4">
<filters>6</filters>
<scores>current</scores>
</tally>
<tally id="5" name="tally 5">
<tally id="5">
<filters>3</filters>
<scores>total</scores>
</tally>
<tally id="6" name="tally 6">
<tally id="6">
<filters>7</filters>
<scores>current</scores>
</tally>
<tally id="7" name="tally 7">
<tally id="7">
<filters>4</filters>
<scores>total</scores>
</tally>
<tally id="8" name="tally 8">
<tally id="8">
<filters>8</filters>
<scores>current</scores>
</tally>

View file

@ -1 +1 @@
35f04a6f062ef64116ef4eb0e9b803cd44cff7e185e2b53c9174afad8a26ca1a436ca9b800d6a228e006a9129f4536d7dce289d7a11cd56c6949d71d6a201b31
c3560155c2f713e5e2ad84451ddcd40484942faf94e2829db77df9b648ea880b3fba35c2a80dd1502e1ba62843e19e746638b2fe4961bde4ded3ce98624a2447

View file

@ -1,87 +1,84 @@
import numpy as np
import openmc
import pytest
from tests.testing_harness import HashedPyAPITestHarness
class FilterMeshTestHarness(HashedPyAPITestHarness):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@pytest.fixture
def model():
model = openmc.model.Model()
# Initialize Meshes
mesh_1d = openmc.RegularMesh(mesh_id=1)
mesh_1d.dimension = [17]
mesh_1d.lower_left = [-182.07]
mesh_1d.upper_right = [182.07]
fuel = openmc.Material()
fuel.set_density('g/cm3', 10.0)
fuel.add_nuclide('U235', 1.0)
zr = openmc.Material()
zr.set_density('g/cm3', 1.0)
zr.add_nuclide('Zr90', 1.0)
model.materials.extend([fuel, zr])
mesh_2d = openmc.RegularMesh(mesh_id=2)
mesh_2d.dimension = [17, 17]
mesh_2d.lower_left = [-182.07, -182.07]
mesh_2d.upper_right = [182.07, 182.07]
box1 = openmc.model.rectangular_prism(10.0, 10.0)
box2 = openmc.model.rectangular_prism(20.0, 20.0, boundary_type='reflective')
top = openmc.ZPlane(z0=10.0, boundary_type='vacuum')
bottom = openmc.ZPlane(z0=-10.0, boundary_type='vacuum')
cell1 = openmc.Cell(fill=fuel, region=box1 & +bottom & -top)
cell2 = openmc.Cell(fill=zr, region=~box1 & box2 & +bottom & -top)
model.geometry = openmc.Geometry([cell1, cell2])
mesh_3d = openmc.RegularMesh(mesh_id=3)
mesh_3d.dimension = [17, 17, 17]
mesh_3d.lower_left = [-182.07, -182.07, -183.00]
mesh_3d.upper_right = [182.07, 182.07, 183.00]
model.settings.batches = 5
model.settings.inactive = 0
model.settings.particles = 1000
recti_mesh = openmc.RectilinearMesh(mesh_id=4)
recti_mesh.x_grid = np.linspace(-182.07, 182.07, 18)
recti_mesh.y_grid = np.linspace(-182.07, 182.07, 18)
recti_mesh.z_grid = np.logspace(0, np.log10(183), 11)
# Create meshes
mesh_1d = openmc.RegularMesh()
mesh_1d.dimension = [5]
mesh_1d.lower_left = [-7.5]
mesh_1d.upper_right = [7.5]
# Initialize the filters
mesh_1d_filter = openmc.MeshFilter(mesh_1d)
mesh_2d_filter = openmc.MeshFilter(mesh_2d)
mesh_3d_filter = openmc.MeshFilter(mesh_3d)
recti_mesh_filter = openmc.MeshFilter(recti_mesh)
meshsurf_1d_filter = openmc.MeshSurfaceFilter(mesh_1d)
meshsurf_2d_filter = openmc.MeshSurfaceFilter(mesh_2d)
meshsurf_3d_filter = openmc.MeshSurfaceFilter(mesh_3d)
recti_meshsurf_filter = openmc.MeshSurfaceFilter(recti_mesh)
mesh_2d = openmc.RegularMesh()
mesh_2d.dimension = [5, 5]
mesh_2d.lower_left = [-7.5, -7.5]
mesh_2d.upper_right = [7.5, 7.5]
# Initialized the tallies
tally = openmc.Tally(name='tally 1')
tally.filters = [mesh_1d_filter]
mesh_3d = openmc.RegularMesh()
mesh_3d.dimension = [5, 5, 5]
mesh_3d.lower_left = [-7.5, -7.5, -7.5]
mesh_3d.upper_right = [7.5, 7.5, 7.5]
recti_mesh = openmc.RectilinearMesh()
recti_mesh.x_grid = np.linspace(-7.5, 7.5, 18)
recti_mesh.y_grid = np.linspace(-7.5, 7.5, 18)
recti_mesh.z_grid = np.logspace(0, np.log10(7.5), 11)
# Create filters
reg_filters = [
openmc.MeshFilter(mesh_1d),
openmc.MeshFilter(mesh_2d),
openmc.MeshFilter(mesh_3d),
openmc.MeshFilter(recti_mesh)
]
surf_filters = [
openmc.MeshSurfaceFilter(mesh_1d),
openmc.MeshSurfaceFilter(mesh_2d),
openmc.MeshSurfaceFilter(mesh_3d),
openmc.MeshSurfaceFilter(recti_mesh)
]
# Create tallies
for f1, f2 in zip(reg_filters, surf_filters):
tally = openmc.Tally()
tally.filters = [f1]
tally.scores = ['total']
self._model.tallies.append(tally)
tally = openmc.Tally(name='tally 2')
tally.filters = [meshsurf_1d_filter]
model.tallies.append(tally)
tally = openmc.Tally()
tally.filters = [f2]
tally.scores = ['current']
self._model.tallies.append(tally)
model.tallies.append(tally)
tally = openmc.Tally(name='tally 3')
tally.filters = [mesh_2d_filter]
tally.scores = ['total']
self._model.tallies.append(tally)
tally = openmc.Tally(name='tally 4')
tally.filters = [meshsurf_2d_filter]
tally.scores = ['current']
self._model.tallies.append(tally)
tally = openmc.Tally(name='tally 5')
tally.filters = [mesh_3d_filter]
tally.scores = ['total']
self._model.tallies.append(tally)
tally = openmc.Tally(name='tally 6')
tally.filters = [meshsurf_3d_filter]
tally.scores = ['current']
self._model.tallies.append(tally)
tally = openmc.Tally(name='tally 7')
tally.filters = [recti_mesh_filter]
tally.scores = ['total']
self._model.tallies.append(tally)
tally = openmc.Tally(name='tally 8')
tally.filters = [recti_meshsurf_filter]
tally.scores = ['current']
self._model.tallies.append(tally)
return model
def test_filter_mesh():
harness = FilterMeshTestHarness('statepoint.10.h5')
def test_filter_mesh(model):
harness = HashedPyAPITestHarness('statepoint.5.h5', model)
harness.main()

View file

@ -1,181 +0,0 @@
<?xml version="1.0"?>
<geometry>
<surface id="1" type="z-cylinder" coeffs="0. 0. 0.41" />
<surface id="2" type="z-cylinder" coeffs="0. 0. 0.475" />
<surface id="3" type="z-cylinder" coeffs="0. 0. 0.56" />
<surface id="4" type="z-cylinder" coeffs="0. 0. 0.62" />
<surface id="5" type="z-cylinder" coeffs="0. 0. 187.6" />
<surface id="6" type="z-cylinder" coeffs="0. 0. 209.0" />
<surface id="7" type="z-cylinder" coeffs="0. 0. 229.0" />
<surface id="8" type="z-cylinder" coeffs="0. 0. 249.0" boundary="vacuum" />
<surface id="31" type="z-plane" coeffs="-229.0" boundary="vacuum" />
<surface id="32" type="z-plane" coeffs="-199.0" />
<surface id="33" type="z-plane" coeffs="-193.0" />
<surface id="34" type="z-plane" coeffs="-183.0" />
<surface id="35" type="z-plane" coeffs="0.0" />
<surface id="36" type="z-plane" coeffs="183.0" />
<surface id="37" type="z-plane" coeffs="203.0" />
<surface id="38" type="z-plane" coeffs="215.0" />
<surface id="39" type="z-plane" coeffs="223.0" boundary="vacuum" />
<!-- All geometry on base universe -->
<cell id="1" fill="200" region=" -6 34 -35" /> <!-- Lower core -->
<cell id="2" fill="201" region=" -6 35 -36" /> <!-- Upper core -->
<cell id="3" material="8" region=" -7 31 -32" /> <!-- Lower core plate region -->
<cell id="4" material="9" region=" -5 32 -33" /> <!-- Bottom nozzle region -->
<cell id="5" material="12" region=" -5 33 -34" /> <!-- Bottom FA region -->
<cell id="6" material="11" region=" -5 36 -37" /> <!-- Top FA region -->
<cell id="7" material="10" region=" -5 37 -38" /> <!-- Top nozzle region -->
<cell id="8" material="7" region=" -7 38 -39" /> <!-- Upper plate region -->
<cell id="9" material="4" region="6 -7 32 -38" /> <!-- Downcomer -->
<cell id="10" material="5" region="7 -8 31 -39" /> <!-- RPV -->
<cell id="11" material="6" region="5 -6 32 -34" /> <!-- Bottom of radial reflector -->
<cell id="12" material="7" region="5 -6 36 -38" /> <!-- Top of radial reflector -->
<!-- Fuel pin, cladding, cold water -->
<cell id="21" universe="1" material="1" region="-1" />
<cell id="22" universe="1" material="2" region="1 -2" />
<cell id="23" universe="1" material="3" region="2" />
<!-- Instrumentation guide tube -->
<cell id="24" universe="2" material="3" region="-3" />
<cell id="25" universe="2" material="2" region="3 -4" />
<cell id="26" universe="2" material="3" region="4" />
<!-- Fuel pin, cladding, hot water -->
<cell id="27" universe="3" material="1" region="-1" />
<cell id="28" universe="3" material="2" region="1 -2" />
<cell id="29" universe="3" material="4" region="2" />
<!-- Instrumentation guide tube -->
<cell id="30" universe="4" material="4" region="-3" />
<cell id="31" universe="4" material="2" region="3 -4" />
<cell id="32" universe="4" material="4" region="4" />
<!-- cell for water assembly (cold) -->
<cell id="50" universe="5" material="4" region="34 -35" />
<!-- containing cell for fuel assembly -->
<cell id="60" universe="6" fill="100" region="34 -35" />
<!-- cell for water assembly (hot) -->
<cell id="70" universe="7" material="3" region="35 -36" />
<!-- containing cell for fuel assembly -->
<cell id="80" universe="8" fill="101" region="35 -36" />
<!-- Fuel Assembly (Lower Half) -->
<lattice id="100">
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<pitch>1.26 1.26</pitch>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
</universes>
</lattice>
<!-- Fuel Assembly (Upper Half) -->
<lattice id="101">
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<pitch>1.26 1.26</pitch>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
</universes>
</lattice>
<!-- Core Lattice (Lower Half) -->
<lattice id="200">
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<pitch>21.42 21.42</pitch>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
</universes>
</lattice>
<!-- Core Lattice (Upper Half) -->
<lattice id="201">
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<pitch>21.42 21.42</pitch>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
</universes>
</lattice>
</geometry>

View file

@ -0,0 +1,53 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell id="1" material="1" region="-1" universe="1" />
<cell id="2" material="2" region="1" universe="1" />
<cell id="3" material="1" region="-2" universe="2" />
<cell id="4" material="2" region="2" universe="2" />
<cell fill="3" id="5" universe="4" />
<cell fill="5" id="6" region="3 -4 5 -6" universe="6" />
<lattice id="3">
<pitch>1.2 1.2</pitch>
<outer>1</outer>
<dimension>2 2</dimension>
<lower_left>-1.2 -1.2</lower_left>
<universes>
2 1
1 1 </universes>
</lattice>
<lattice id="5">
<pitch>2.4 2.4</pitch>
<dimension>2 2</dimension>
<lower_left>-2.4 -2.4</lower_left>
<universes>
4 4
4 4 </universes>
</lattice>
<surface coeffs="0.0 0.0 0.4" id="1" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.5" id="2" type="z-cylinder" />
<surface boundary="reflective" coeffs="-2.4" id="3" name="minimum x" type="x-plane" />
<surface boundary="reflective" coeffs="2.4" id="4" name="maximum x" type="x-plane" />
<surface boundary="reflective" coeffs="-2.4" id="5" name="minimum y" type="y-plane" />
<surface boundary="reflective" coeffs="2.4" id="6" name="maximum y" type="y-plane" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1" name="UO2">
<density units="g/cm3" value="10.0" />
<nuclide ao="1.0" name="U235" />
<nuclide ao="2.0" name="O16" />
</material>
<material id="2" name="light water">
<density units="g/cm3" value="1.0" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<sab name="c_H_in_H2O" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>1000</particles>
<batches>10</batches>
<inactive>5</inactive>
</settings>

View file

@ -1,270 +0,0 @@
<?xml version="1.0"?>
<materials>
<!-- Fuel composition -->
<material id="1">
<density value="10.062" units="g/cm3" />
<nuclide name="U234" ao="4.9476e-6" />
<nuclide name="U235" ao="4.8218e-4" />
<nuclide name="U236" ao="9.0402e-5" />
<nuclide name="U238" ao="2.1504e-2" />
<nuclide name="Np237" ao="7.3733e-6" />
<nuclide name="Pu238" ao="1.5148e-6" />
<nuclide name="Pu239" ao="1.3955e-4" />
<nuclide name="Pu240" ao="3.4405e-5" />
<nuclide name="Pu241" ao="2.1439e-5" />
<nuclide name="Pu242" ao="3.7422e-6" />
<nuclide name="Am241" ao="4.5041e-7" />
<nuclide name="Am242_m1" ao="9.2301e-9" />
<nuclide name="Am243" ao="4.7878e-7" />
<nuclide name="Cm242" ao="1.0485e-7" />
<nuclide name="Cm243" ao="1.4268e-9" />
<nuclide name="Cm244" ao="8.8756e-8" />
<nuclide name="Cm245" ao="3.5285e-9" />
<nuclide name="Mo95" ao="2.6497e-5" />
<nuclide name="Tc99" ao="3.2772e-5" />
<nuclide name="Ru101" ao="3.0742e-5" />
<nuclide name="Ru103" ao="2.3505e-6" />
<nuclide name="Ag109" ao="2.0009e-6" />
<nuclide name="Xe135" ao="1.0801e-8" />
<nuclide name="Cs133" ao="3.4612e-5" />
<nuclide name="Nd143" ao="2.6078e-5" />
<nuclide name="Nd145" ao="1.9898e-5" />
<nuclide name="Sm147" ao="1.6128e-6" />
<nuclide name="Sm149" ao="1.1627e-7" />
<nuclide name="Sm150" ao="7.1727e-6" />
<nuclide name="Sm151" ao="5.4947e-7" />
<nuclide name="Sm152" ao="3.0221e-6" />
<nuclide name="Eu153" ao="2.6209e-6" />
<nuclide name="Gd155" ao="1.5369e-9" />
<nuclide name="O16" ao="4.5737e-2" />
</material>
<!-- Cladding composition -->
<material id="2">
<density value="5.77" units="g/cm3" />
<nuclide name="Zr90" ao="0.5145" />
<nuclide name="Zr91" ao="0.1122" />
<nuclide name="Zr92" ao="0.1715" />
<nuclide name="Zr94" ao="0.1738" />
<nuclide name="Zr96" ao="0.0280" />
</material>
<!-- Cold borated water -->
<material id="3">
<density value="0.07416" units="atom/b-cm" />
<nuclide name="H1" ao="2.0" />
<nuclide name="O16" ao="1.0" />
<nuclide name="B10" ao="6.490e-4" />
<nuclide name="B11" ao="2.689e-3" />
<sab name="c_H_in_H2O" />
</material>
<!-- Hot borated water -->
<material id="4">
<density value="0.06614" units="atom/b-cm" />
<nuclide name="H1" ao="2.0" />
<nuclide name="O16" ao="1.0" />
<nuclide name="B10" ao="6.490e-4" />
<nuclide name="B11" ao="2.689e-3" />
<sab name="c_H_in_H2O" />
</material>
<!-- RPV Composition -->
<material id="5">
<density value="7.9" units="g/cm3" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Ni61" wo="0.0001183" />
<nuclide name="Ni62" wo="0.0003835" />
<nuclide name="Ni64" wo="0.0001008" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Mo92" wo="0.000849" />
<nuclide name="Mo94" wo="0.0005418" />
<nuclide name="Mo95" wo="0.0009438" />
<nuclide name="Mo96" wo="0.0010002" />
<nuclide name="Mo97" wo="0.0005796" />
<nuclide name="Mo98" wo="0.0014814" />
<nuclide name="Mo100" wo="0.0006042" />
<nuclide name="Si28" wo="0.00367464" />
<nuclide name="Si29" wo="0.00019336" />
<nuclide name="Si30" wo="0.000132" />
<nuclide name="Cr50" wo="0.00010435" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="Cr53" wo="0.00024185" />
<nuclide name="Cr54" wo="6.1325e-05" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
<nuclide name="Cu65" wo="0.0006304" />
</material>
<!-- Lower radial reflector -->
<material id="6">
<density value="4.32" units="g/cm3" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-5" />
<nuclide name="B11" wo="1.40499e-4" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Ni60" wo="0.022034425592" />
<nuclide name="Ni61" wo="0.000973510811" />
<nuclide name="Ni62" wo="0.003155886695" />
<nuclide name="Ni64" wo="0.000829500336" />
<nuclide name="Mn55" wo="0.0182870" />
<nuclide name="Si28" wo="0.00839976771" />
<nuclide name="Si29" wo="0.00044199679" />
<nuclide name="Si30" wo="0.0003017355" />
<nuclide name="Cr50" wo="0.007251360806" />
<nuclide name="Cr52" wo="0.145407678031" />
<nuclide name="Cr53" wo="0.016806340306" />
<nuclide name="Cr54" wo="0.004261520857" />
<sab name="c_H_in_H2O" />
</material>
<!-- Upper radial reflector / Top plate region -->
<material id="7">
<density value="4.28" units="g/cm3" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-5" />
<nuclide name="B11" wo="1.26481e-4" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Ni60" wo="0.022240333032" />
<nuclide name="Ni61" wo="0.000982608081" />
<nuclide name="Ni62" wo="0.003185377845" />
<nuclide name="Ni64" wo="0.000837251856" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Si28" wo="0.00847831314" />
<nuclide name="Si29" wo="0.00044612986" />
<nuclide name="Si30" wo="0.000304557" />
<nuclide name="Cr50" wo="0.00731912987" />
<nuclide name="Cr52" wo="0.146766614995" />
<nuclide name="Cr53" wo="0.01696340737" />
<nuclide name="Cr54" wo="0.004301347765" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom plate region -->
<material id="8">
<density value="7.184" units="g/cm3" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-6" />
<nuclide name="B11" wo="1.68974e-5" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Ni60" wo="0.023850159704" />
<nuclide name="Ni61" wo="0.001053732407" />
<nuclide name="Ni62" wo="0.003415945715" />
<nuclide name="Ni64" wo="0.000897854832" />
<nuclide name="Mn55" wo="0.0197940" />
<nuclide name="Si28" wo="0.00909197802" />
<nuclide name="Si29" wo="0.00047842098" />
<nuclide name="Si30" wo="0.000326601" />
<nuclide name="Cr50" wo="0.007848910646" />
<nuclide name="Cr52" wo="0.157390026871" />
<nuclide name="Cr53" wo="0.018191270146" />
<nuclide name="Cr54" wo="0.004612692337" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom nozzle region -->
<material id="9">
<density value="2.53" units="g/cm3" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-5" />
<nuclide name="B11" wo="3.59854e-4" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Ni60" wo="0.018811987544" />
<nuclide name="Ni61" wo="0.000831139127" />
<nuclide name="Ni62" wo="0.002694352115" />
<nuclide name="Ni64" wo="0.000708189552" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Si28" wo="0.007171335558" />
<nuclide name="Si29" wo="0.000377356542" />
<nuclide name="Si30" wo="0.0002576079" />
<nuclide name="Cr50" wo="0.006190885148" />
<nuclide name="Cr52" wo="0.124142524198" />
<nuclide name="Cr53" wo="0.014348496148" />
<nuclide name="Cr54" wo="0.003638294506" />
<sab name="c_H_in_H2O" />
</material>
<!-- Top nozzle region -->
<material id="10">
<density value="1.746" units="g/cm3" />
<nuclide name="H1" wo="0.0358870" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="1.15699e-4" />
<nuclide name="B11" wo="5.27075e-4" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Ni60" wo="0.0163554502" />
<nuclide name="Ni61" wo="0.000722605975" />
<nuclide name="Ni62" wo="0.002342513875" />
<nuclide name="Ni64" wo="0.0006157116" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Si28" wo="0.006234853554" />
<nuclide name="Si29" wo="0.000328078746" />
<nuclide name="Si30" wo="0.0002239677" />
<nuclide name="Cr50" wo="0.005382452306" />
<nuclide name="Cr52" wo="0.107931450781" />
<nuclide name="Cr53" wo="0.012474806806" />
<nuclide name="Cr54" wo="0.003163190107" />
<sab name="c_H_in_H2O" />
</material>
<!-- Top of Fuel Assemblies -->
<material id="11">
<density value="3.044" units="g/cm3" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-5" />
<nuclide name="B11" wo="2.39272e-4" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom of Fuel Assemblies -->
<material id="12">
<density value="1.762" units="g/cm3" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-5" />
<nuclide name="B11" wo="4.30120e-4" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
</material>
</materials>

View file

@ -1,2 +1,2 @@
k-combined:
9.581522E-01 4.261828E-02
1.831313E+00 6.958576E-04

View file

@ -1,18 +0,0 @@
<?xml version="1.0"?>
<settings>
<run_mode>eigenvalue</run_mode>
<batches>10</batches>
<inactive>5</inactive>
<particles>100</particles>
<source>
<space type="box">
<parameters>
-160 -160 -183
160 160 183
</parameters>
</space>
</source>
</settings>

View file

@ -1,6 +1,58 @@
from tests.testing_harness import TestHarness
import numpy as np
import openmc
import pytest
from tests.testing_harness import PyAPITestHarness
def test_lattice_multiple():
harness = TestHarness('statepoint.10.h5')
@pytest.fixture
def model():
model = openmc.model.Model()
uo2 = openmc.Material(name='UO2')
uo2.set_density('g/cm3', 10.0)
uo2.add_nuclide('U235', 1.0)
uo2.add_nuclide('O16', 2.0)
water = openmc.Material(name='light water')
water.add_nuclide('H1', 2.0)
water.add_nuclide('O16', 1.0)
water.set_density('g/cm3', 1.0)
water.add_s_alpha_beta('c_H_in_H2O')
model.materials.extend([uo2, water])
cyl = openmc.ZCylinder(r=0.4)
big_cyl = openmc.ZCylinder(r=0.5)
pin = openmc.model.pin([cyl], [uo2, water])
big_pin = openmc.model.pin([big_cyl], [uo2, water])
d = 1.2
inner_lattice = openmc.RectLattice()
inner_lattice.lower_left = (-d, -d)
inner_lattice.pitch = (d, d)
inner_lattice.outer = pin
inner_lattice.universes = [
[big_pin, pin],
[pin, pin],
]
inner_cell = openmc.Cell(fill=inner_lattice)
inner_univ = openmc.Universe(cells=[inner_cell])
lattice = openmc.RectLattice()
lattice.lower_left = (-2*d, -2*d)
lattice.pitch = (2*d, 2*d)
lattice.universes = np.full((2, 2), inner_univ)
box = openmc.model.rectangular_prism(4*d, 4*d, boundary_type='reflective')
main_cell = openmc.Cell(fill=lattice, region=box)
model.geometry = openmc.Geometry([main_cell])
model.settings.batches = 10
model.settings.inactive = 5
model.settings.particles = 1000
return model
def test_lattice_multiple(model):
harness = PyAPITestHarness('statepoint.10.h5', model)
harness.main()

View file

@ -1,311 +1,35 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell fill="200" id="1" region="-6 34 -35" universe="0" />
<cell fill="201" id="2" region="-6 35 -36" universe="0" />
<cell id="3" material="8" region="-7 31 -32" universe="0" />
<cell id="4" material="9" region="-5 32 -33" universe="0" />
<cell id="5" material="12" region="-5 33 -34" universe="0" />
<cell id="6" material="11" region="-5 36 -37" universe="0" />
<cell id="7" material="10" region="-5 37 -38" universe="0" />
<cell id="8" material="7" region="-7 38 -39" universe="0" />
<cell id="9" material="9" region="6 -7 32 -38" universe="0" />
<cell id="10" material="5" region="7 -8 31 -39" universe="0" />
<cell id="11" material="6" region="5 -6 32 -34" universe="0" />
<cell id="12" material="7" region="5 -6 36 -38" universe="0" />
<cell id="21" material="1" region="-1" universe="1" />
<cell id="22" material="2" region="1 -2" universe="1" />
<cell id="23" material="3" region="2" universe="1" />
<cell id="24" material="3" region="-3" universe="2" />
<cell id="25" material="2" region="3 -4" universe="2" />
<cell id="26" material="3" region="4" universe="2" />
<cell id="27" material="1" region="-1" universe="3" />
<cell id="28" material="2" region="1 -2" universe="3" />
<cell id="29" material="4" region="2" universe="3" />
<cell id="30" material="4" region="-3" universe="4" />
<cell id="31" material="2" region="3 -4" universe="4" />
<cell id="32" material="4" region="4" universe="4" />
<cell id="50" material="3" region="34 -35" universe="5" />
<cell fill="100" id="60" region="34 -35" universe="6" />
<cell id="70" material="4" region="35 -36" universe="7" />
<cell fill="101" id="80" region="35 -36" universe="8" />
<lattice id="100" name="Fuel assembly (lower half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 </universes>
</lattice>
<lattice id="101" name="Fuel assembly (upper half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </universes>
</lattice>
<lattice id="200" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 </universes>
</lattice>
<lattice id="201" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 </universes>
</lattice>
<surface coeffs="0.0 0.0 0.41" id="1" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.475" id="2" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.56" id="3" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.62" id="4" type="z-cylinder" />
<surface coeffs="0.0 0.0 187.6" id="5" type="z-cylinder" />
<surface coeffs="0.0 0.0 209.0" id="6" type="z-cylinder" />
<surface coeffs="0.0 0.0 229.0" id="7" type="z-cylinder" />
<surface boundary="vacuum" coeffs="0.0 0.0 249.0" id="8" type="z-cylinder" />
<surface boundary="vacuum" coeffs="-229.0" id="31" type="z-plane" />
<surface coeffs="-199.0" id="32" type="z-plane" />
<surface coeffs="-193.0" id="33" type="z-plane" />
<surface coeffs="-183.0" id="34" type="z-plane" />
<surface coeffs="0.0" id="35" type="z-plane" />
<surface coeffs="183.0" id="36" type="z-plane" />
<surface coeffs="203.0" id="37" type="z-plane" />
<surface coeffs="215.0" id="38" type="z-plane" />
<surface boundary="vacuum" coeffs="223.0" id="39" type="z-plane" />
<cell id="1" material="1" region="1 -2 3 -4 10 -9" universe="1" />
<cell id="2" material="2" region="~(1 -2 3 -4) (5 -6 7 -8) 10 -9" universe="1" />
<surface coeffs="-5.0" id="1" name="minimum x" type="x-plane" />
<surface coeffs="5.0" id="2" name="maximum x" type="x-plane" />
<surface coeffs="-5.0" id="3" name="minimum y" type="y-plane" />
<surface coeffs="5.0" id="4" name="maximum y" type="y-plane" />
<surface boundary="reflective" coeffs="-10.0" id="5" name="minimum x" type="x-plane" />
<surface boundary="reflective" coeffs="10.0" id="6" name="maximum x" type="x-plane" />
<surface boundary="reflective" coeffs="-10.0" id="7" name="minimum y" type="y-plane" />
<surface boundary="reflective" coeffs="10.0" id="8" name="maximum y" type="y-plane" />
<surface boundary="vacuum" coeffs="10.0" id="9" type="z-plane" />
<surface boundary="vacuum" coeffs="-10.0" id="10" type="z-plane" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1" name="UOX fuel">
<density units="g/cm3" value="10.062" />
<nuclide ao="4.9476e-06" name="U234" />
<nuclide ao="0.00048218" name="U235" />
<nuclide ao="0.021504" name="U238" />
<nuclide ao="1.0801e-08" name="Xe135" />
<nuclide ao="0.045737" name="O16" />
<material depletable="true" id="1">
<density units="g/cm3" value="10.0" />
<nuclide ao="1.0" name="U235" />
</material>
<material id="2" name="Zircaloy">
<density units="g/cm3" value="5.77" />
<nuclide ao="0.5145" name="Zr90" />
<nuclide ao="0.1122" name="Zr91" />
<nuclide ao="0.1715" name="Zr92" />
<nuclide ao="0.1738" name="Zr94" />
<nuclide ao="0.028" name="Zr96" />
</material>
<material id="3" name="Cold borated water">
<density units="atom/b-cm" value="0.07416" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="4" name="Hot borated water">
<density units="atom/b-cm" value="0.06614" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="5" name="Reactor pressure vessel steel">
<density units="g/cm3" value="7.9" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
</material>
<material id="6" name="Lower radial reflector">
<density units="g/cm3" value="4.32" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-05" />
<nuclide name="B11" wo="0.000140499" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Mn55" wo="0.018287" />
<nuclide name="Cr52" wo="0.145407678031" />
<sab name="c_H_in_H2O" />
</material>
<material id="7" name="Upper radial reflector / Top plate region">
<density units="g/cm3" value="4.28" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-05" />
<nuclide name="B11" wo="0.000126481" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Cr52" wo="0.146766614995" />
<sab name="c_H_in_H2O" />
</material>
<material id="8" name="Bottom plate region">
<density units="g/cm3" value="7.184" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-06" />
<nuclide name="B11" wo="1.68974e-05" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Mn55" wo="0.019794" />
<nuclide name="Cr52" wo="0.157390026871" />
<sab name="c_H_in_H2O" />
</material>
<material id="9" name="Bottom nozzle region">
<density units="g/cm3" value="2.53" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-05" />
<nuclide name="B11" wo="0.000359854" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Cr52" wo="0.124142524198" />
<sab name="c_H_in_H2O" />
</material>
<material id="10" name="Top nozzle region">
<density units="g/cm3" value="1.746" />
<nuclide name="H1" wo="0.035887" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="0.000115699" />
<nuclide name="B11" wo="0.000527075" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Cr52" wo="0.107931450781" />
<sab name="c_H_in_H2O" />
</material>
<material id="11" name="Top of fuel assemblies">
<density units="g/cm3" value="3.044" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-05" />
<nuclide name="B11" wo="0.000239272" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<material id="12" name="Bottom of fuel assemblies">
<density units="g/cm3" value="1.762" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-05" />
<nuclide name="B11" wo="0.00043012" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
<material id="2">
<density units="g/cm3" value="1.0" />
<nuclide ao="1.0" name="Zr90" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<batches>10</batches>
<inactive>5</inactive>
<source strength="1.0">
<space type="box">
<parameters>-160 -160 -183 160 160 183</parameters>
</space>
</source>
<particles>1000</particles>
<batches>5</batches>
<inactive>0</inactive>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>

View file

@ -1,310 +1,310 @@
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.762544 0.085298
2 1 2 1 1 total 0.644837 0.088457
1 2 1 1 1 total 0.653375 0.153317
3 2 2 1 1 total 0.676480 0.094215
0 1 1 1 1 total 0.105390 0.006421
2 1 2 1 1 total 0.105466 0.003175
1 2 1 1 1 total 0.106221 0.004040
3 2 2 1 1 total 0.102641 0.002129
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.473988 0.088732
2 1 2 1 1 total 0.399254 0.091318
1 2 1 1 1 total 0.379821 0.167092
3 2 2 1 1 total 0.424265 0.099551
0 1 1 1 1 total 0.078603 0.006888
2 1 2 1 1 total 0.075950 0.003755
1 2 1 1 1 total 0.074519 0.004589
3 2 2 1 1 total 0.072616 0.002838
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.473988 0.088732
2 1 2 1 1 total 0.399254 0.091318
1 2 1 1 1 total 0.379821 0.167092
3 2 2 1 1 total 0.424265 0.099551
0 1 1 1 1 total 0.078605 0.006892
2 1 2 1 1 total 0.075989 0.003746
1 2 1 1 1 total 0.074571 0.004600
3 2 2 1 1 total 0.072586 0.002824
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.027288 0.005813
2 1 2 1 1 total 0.020262 0.003701
1 2 1 1 1 total 0.019449 0.004420
3 2 2 1 1 total 0.021266 0.002869
0 1 1 1 1 total 0.013600 0.000926
2 1 2 1 1 total 0.013584 0.000551
1 2 1 1 1 total 0.013692 0.000712
3 2 2 1 1 total 0.013022 0.000430
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.016037 0.006339
2 1 2 1 1 total 0.013018 0.003521
1 2 1 1 1 total 0.012153 0.003804
3 2 2 1 1 total 0.012965 0.002454
0 1 1 1 1 total 0.001333 0.001105
2 1 2 1 1 total 0.001339 0.000693
1 2 1 1 1 total 0.001330 0.000885
3 2 2 1 1 total 0.001260 0.000534
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.011251 0.003050
2 1 2 1 1 total 0.007243 0.001219
1 2 1 1 1 total 0.007296 0.001795
3 2 2 1 1 total 0.008301 0.001066
0 1 1 1 1 total 0.012266 0.000830
2 1 2 1 1 total 0.012244 0.000486
1 2 1 1 1 total 0.012361 0.000650
3 2 2 1 1 total 0.011762 0.000376
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.027498 0.007445
2 1 2 1 1 total 0.017954 0.003077
1 2 1 1 1 total 0.017912 0.004426
3 2 2 1 1 total 0.020469 0.002617
0 1 1 1 1 total 0.032001 0.002161
2 1 2 1 1 total 0.031882 0.001271
1 2 1 1 1 total 0.032193 0.001701
3 2 2 1 1 total 0.030726 0.001000
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 2.177345e+06 589804.301157
2 1 2 1 1 total 1.404096e+06 236476.852674
1 2 1 1 1 total 1.413154e+06 347806.623478
3 2 2 1 1 total 1.608259e+06 206502.707123
0 1 1 1 1 total 2.372379e+06 160440.303797
2 1 2 1 1 total 2.368109e+06 93914.371991
1 2 1 1 1 total 2.390701e+06 125743.883417
3 2 2 1 1 total 2.274785e+06 72785.094827
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.735256 0.080216
2 1 2 1 1 total 0.624575 0.084974
1 2 1 1 1 total 0.633925 0.149098
3 2 2 1 1 total 0.655214 0.091422
0 1 1 1 1 total 0.091790 0.005503
2 1 2 1 1 total 0.091883 0.002653
1 2 1 1 1 total 0.092530 0.003354
3 2 2 1 1 total 0.089619 0.001721
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.763779 0.070696
2 1 2 1 1 total 0.628158 0.064356
1 2 1 1 1 total 0.640809 0.158369
3 2 2 1 1 total 0.645171 0.080467
0 1 1 1 1 total 0.087817 0.005624
2 1 2 1 1 total 0.090790 0.005246
1 2 1 1 1 total 0.093736 0.005609
3 2 2 1 1 total 0.092035 0.003633
mesh 1 group in group out legendre nuclide mean std. dev.
x y z
0 1 1 1 1 1 P0 total 0.763779 0.070696
1 1 1 1 1 1 P1 total 0.288556 0.024446
2 1 1 1 1 1 P2 total 0.082441 0.011443
3 1 1 1 1 1 P3 total -0.005627 0.012638
8 1 2 1 1 1 P0 total 0.628158 0.064356
9 1 2 1 1 1 P1 total 0.245583 0.022676
10 1 2 1 1 1 P2 total 0.086370 0.007833
11 1 2 1 1 1 P3 total 0.019590 0.005345
4 2 1 1 1 1 P0 total 0.640809 0.158369
5 2 1 1 1 1 P1 total 0.273553 0.066437
6 2 1 1 1 1 P2 total 0.108446 0.024435
7 2 1 1 1 1 P3 total 0.012229 0.003785
12 2 2 1 1 1 P0 total 0.645171 0.080467
13 2 2 1 1 1 P1 total 0.252215 0.032154
14 2 2 1 1 1 P2 total 0.089251 0.009734
15 2 2 1 1 1 P3 total 0.004748 0.002987
0 1 1 1 1 1 P0 total 0.087684 0.005584
1 1 1 1 1 1 P1 total 0.026787 0.002493
2 1 1 1 1 1 P2 total 0.014937 0.001035
3 1 1 1 1 1 P3 total 0.007893 0.001109
8 1 2 1 1 1 P0 total 0.090687 0.005242
9 1 2 1 1 1 P1 total 0.029516 0.002004
10 1 2 1 1 1 P2 total 0.016952 0.001093
11 1 2 1 1 1 P3 total 0.008019 0.001095
4 2 1 1 1 1 P0 total 0.093670 0.005616
5 2 1 1 1 1 P1 total 0.031703 0.002177
6 2 1 1 1 1 P2 total 0.017922 0.001352
7 2 1 1 1 1 P3 total 0.011171 0.001055
12 2 2 1 1 1 P0 total 0.091808 0.003617
13 2 2 1 1 1 P1 total 0.030025 0.001876
14 2 2 1 1 1 P2 total 0.015181 0.002277
15 2 2 1 1 1 P3 total 0.009550 0.001713
mesh 1 group in group out legendre nuclide mean std. dev.
x y z
0 1 1 1 1 1 P0 total 0.763779 0.070696
1 1 1 1 1 1 P1 total 0.288556 0.024446
2 1 1 1 1 1 P2 total 0.082441 0.011443
3 1 1 1 1 1 P3 total -0.005627 0.012638
8 1 2 1 1 1 P0 total 0.628158 0.064356
9 1 2 1 1 1 P1 total 0.245583 0.022676
10 1 2 1 1 1 P2 total 0.086370 0.007833
11 1 2 1 1 1 P3 total 0.019590 0.005345
4 2 1 1 1 1 P0 total 0.640809 0.158369
5 2 1 1 1 1 P1 total 0.273553 0.066437
6 2 1 1 1 1 P2 total 0.108446 0.024435
7 2 1 1 1 1 P3 total 0.012229 0.003785
12 2 2 1 1 1 P0 total 0.645171 0.080467
13 2 2 1 1 1 P1 total 0.252215 0.032154
14 2 2 1 1 1 P2 total 0.089251 0.009734
15 2 2 1 1 1 P3 total 0.004748 0.002987
mesh 1 group in group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 1.0 0.108337
2 1 2 1 1 1 total 1.0 0.113128
1 2 1 1 1 1 total 1.0 0.238517
3 2 2 1 1 1 total 1.0 0.132597
0 1 1 1 1 1 P0 total 0.087817 0.005624
1 1 1 1 1 1 P1 total 0.026785 0.002504
2 1 1 1 1 1 P2 total 0.014973 0.001041
3 1 1 1 1 1 P3 total 0.007913 0.001144
8 1 2 1 1 1 P0 total 0.090790 0.005246
9 1 2 1 1 1 P1 total 0.029477 0.001987
10 1 2 1 1 1 P2 total 0.016940 0.001094
11 1 2 1 1 1 P3 total 0.008033 0.001104
4 2 1 1 1 1 P0 total 0.093736 0.005609
5 2 1 1 1 1 P1 total 0.031651 0.002201
6 2 1 1 1 1 P2 total 0.017953 0.001364
7 2 1 1 1 1 P3 total 0.011158 0.001044
12 2 2 1 1 1 P0 total 0.092035 0.003633
13 2 2 1 1 1 P1 total 0.030055 0.001856
14 2 2 1 1 1 P2 total 0.015245 0.002274
15 2 2 1 1 1 P3 total 0.009534 0.001700
mesh 1 group in group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 0.015584 0.003404
2 1 2 1 1 1 total 0.017684 0.002499
1 2 1 1 1 1 total 0.014200 0.003676
3 2 2 1 1 1 total 0.022409 0.002481
0 1 1 1 1 1 total 1.001515 0.075311
2 1 2 1 1 1 total 1.001135 0.061671
1 2 1 1 1 1 total 1.000704 0.055977
3 2 2 1 1 1 total 1.002471 0.042246
mesh 1 group in group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 0.031246 0.001839
2 1 2 1 1 1 total 0.032452 0.002365
1 2 1 1 1 1 total 0.032568 0.002068
3 2 2 1 1 1 total 0.031529 0.001639
mesh 1 group in group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 1.0 0.108337
2 1 2 1 1 1 total 1.0 0.113128
1 2 1 1 1 1 total 1.0 0.238517
3 2 2 1 1 1 total 1.0 0.132597
0 1 1 1 1 1 total 1.0 0.074891
2 1 2 1 1 1 total 1.0 0.061618
1 2 1 1 1 1 total 1.0 0.056068
3 2 2 1 1 1 total 1.0 0.042067
mesh 1 group in group out legendre nuclide mean std. dev.
x y z
0 1 1 1 1 1 P0 total 0.735256 0.113047
1 1 1 1 1 1 P1 total 0.277780 0.041434
2 1 1 1 1 1 P2 total 0.079362 0.014706
3 1 1 1 1 1 P3 total -0.005417 0.012184
8 1 2 1 1 1 P0 total 0.624575 0.110512
9 1 2 1 1 1 P1 total 0.244182 0.041824
10 1 2 1 1 1 P2 total 0.085877 0.014634
11 1 2 1 1 1 P3 total 0.019478 0.006012
4 2 1 1 1 1 P0 total 0.633925 0.212349
5 2 1 1 1 1 P1 total 0.270615 0.089799
6 2 1 1 1 1 P2 total 0.107281 0.034246
7 2 1 1 1 1 P3 total 0.012098 0.004637
12 2 2 1 1 1 P0 total 0.655214 0.126119
13 2 2 1 1 1 P1 total 0.256141 0.049765
14 2 2 1 1 1 P2 total 0.090641 0.016563
15 2 2 1 1 1 P3 total 0.004822 0.003115
0 1 1 1 1 1 P0 total 0.091790 0.008806
1 1 1 1 1 1 P1 total 0.028042 0.003295
2 1 1 1 1 1 P2 total 0.015636 0.001560
3 1 1 1 1 1 P3 total 0.008263 0.001304
8 1 2 1 1 1 P0 total 0.091883 0.006252
9 1 2 1 1 1 P1 total 0.029905 0.002297
10 1 2 1 1 1 P2 total 0.017175 0.001268
11 1 2 1 1 1 P3 total 0.008124 0.001147
4 2 1 1 1 1 P0 total 0.092530 0.006177
5 2 1 1 1 1 P1 total 0.031317 0.002339
6 2 1 1 1 1 P2 total 0.017704 0.001433
7 2 1 1 1 1 P3 total 0.011035 0.001092
12 2 2 1 1 1 P0 total 0.089619 0.004144
13 2 2 1 1 1 P1 total 0.029309 0.001964
14 2 2 1 1 1 P2 total 0.014820 0.002251
15 2 2 1 1 1 P3 total 0.009322 0.001687
mesh 1 group in group out legendre nuclide mean std. dev.
x y z
0 1 1 1 1 1 P0 total 0.735256 0.138292
1 1 1 1 1 1 P1 total 0.277780 0.051210
2 1 1 1 1 1 P2 total 0.079362 0.017035
3 1 1 1 1 1 P3 total -0.005417 0.012198
8 1 2 1 1 1 P0 total 0.624575 0.131169
9 1 2 1 1 1 P1 total 0.244182 0.050123
10 1 2 1 1 1 P2 total 0.085877 0.017565
11 1 2 1 1 1 P3 total 0.019478 0.006403
4 2 1 1 1 1 P0 total 0.633925 0.260681
5 2 1 1 1 1 P1 total 0.270615 0.110590
6 2 1 1 1 1 P2 total 0.107281 0.042750
7 2 1 1 1 1 P3 total 0.012098 0.005462
12 2 2 1 1 1 P0 total 0.655214 0.153147
13 2 2 1 1 1 P1 total 0.256141 0.060250
14 2 2 1 1 1 P2 total 0.090641 0.020464
15 2 2 1 1 1 P3 total 0.004822 0.003180
0 1 1 1 1 1 P0 total 0.091929 0.011205
1 1 1 1 1 1 P1 total 0.028084 0.003918
2 1 1 1 1 1 P2 total 0.015660 0.001956
3 1 1 1 1 1 P3 total 0.008276 0.001447
8 1 2 1 1 1 P0 total 0.091987 0.008443
9 1 2 1 1 1 P1 total 0.029939 0.002948
10 1 2 1 1 1 P2 total 0.017195 0.001653
11 1 2 1 1 1 P3 total 0.008134 0.001253
4 2 1 1 1 1 P0 total 0.092595 0.008065
5 2 1 1 1 1 P1 total 0.031339 0.002924
6 2 1 1 1 1 P2 total 0.017716 0.001743
7 2 1 1 1 1 P3 total 0.011042 0.001255
12 2 2 1 1 1 P0 total 0.089840 0.005621
13 2 2 1 1 1 P1 total 0.029381 0.002326
14 2 2 1 1 1 P2 total 0.014856 0.002342
15 2 2 1 1 1 P3 total 0.009345 0.001737
mesh 1 group out nuclide mean std. dev.
x y z
0 1 1 1 1 total 1.0 0.300047
2 1 2 1 1 total 1.0 0.178169
1 2 1 1 1 total 1.0 0.262180
3 2 2 1 1 total 1.0 0.104797
0 1 1 1 1 total 1.0 0.066520
2 1 2 1 1 total 1.0 0.087934
1 2 1 1 1 total 1.0 0.063390
3 2 2 1 1 total 1.0 0.063791
mesh 1 group out nuclide mean std. dev.
x y z
0 1 1 1 1 total 1.0 0.300047
2 1 2 1 1 total 1.0 0.178169
1 2 1 1 1 total 1.0 0.262180
3 2 2 1 1 total 1.0 0.108931
0 1 1 1 1 total 1.0 0.068463
2 1 2 1 1 total 1.0 0.091776
1 2 1 1 1 total 1.0 0.064705
3 2 2 1 1 total 1.0 0.063003
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 7.097008e-07 1.458546e-07
2 1 2 1 1 total 4.407745e-07 7.903907e-08
1 2 1 1 1 total 3.984535e-07 1.157576e-07
3 2 2 1 1 total 4.750476e-07 6.207437e-08
0 1 1 1 1 total 8.735713e-10 4.530341e-11
2 1 2 1 1 total 8.821319e-10 3.206094e-11
1 2 1 1 1 total 8.699208e-10 2.515246e-11
3 2 2 1 1 total 8.738762e-10 1.734562e-11
mesh 1 group in nuclide mean std. dev.
x y z
0 1 1 1 1 total 0.027311 0.007397
2 1 2 1 1 total 0.017820 0.003054
1 2 1 1 1 total 0.017783 0.004394
3 2 2 1 1 total 0.020320 0.002598
0 1 1 1 1 total 0.031799 0.002147
2 1 2 1 1 total 0.031680 0.001263
1 2 1 1 1 total 0.031989 0.001691
3 2 2 1 1 total 0.030533 0.000994
mesh 1 group in group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 0.015584 0.003404
2 1 2 1 1 1 total 0.017684 0.002499
1 2 1 1 1 1 total 0.014200 0.003676
3 2 2 1 1 1 total 0.022259 0.002508
0 1 1 1 1 1 total 0.031056 0.001862
2 1 2 1 1 1 total 0.032188 0.002420
1 2 1 1 1 1 total 0.032304 0.002073
3 2 2 1 1 1 total 0.031336 0.001614
mesh 1 delayedgroup group in nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 0.000006 1.689606e-06
1 1 1 1 2 1 total 0.000033 8.718916e-06
2 1 1 1 3 1 total 0.000032 8.323051e-06
3 1 1 1 4 1 total 0.000072 1.866015e-05
4 1 1 1 5 1 total 0.000031 7.654909e-06
5 1 1 1 6 1 total 0.000013 3.206343e-06
12 1 2 1 1 1 total 0.000004 6.723192e-07
13 1 2 1 2 1 total 0.000022 3.706235e-06
14 1 2 1 3 1 total 0.000022 3.674263e-06
15 1 2 1 4 1 total 0.000052 8.774048e-06
16 1 2 1 5 1 total 0.000024 4.168024e-06
17 1 2 1 6 1 total 0.000010 1.726268e-06
6 2 1 1 1 1 total 0.000004 1.003100e-06
7 2 1 1 2 1 total 0.000022 5.425275e-06
8 2 1 1 3 1 total 0.000021 5.324236e-06
9 2 1 1 4 1 total 0.000050 1.251572e-05
10 2 1 1 5 1 total 0.000022 5.762184e-06
11 2 1 1 6 1 total 0.000009 2.391676e-06
18 2 2 1 1 1 total 0.000005 5.962367e-07
19 2 2 1 2 1 total 0.000025 3.200900e-06
20 2 2 1 3 1 total 0.000025 3.127442e-06
21 2 2 1 4 1 total 0.000058 7.296157e-06
22 2 2 1 5 1 total 0.000026 3.298196e-06
23 2 2 1 6 1 total 0.000011 1.370918e-06
0 1 1 1 1 1 total 0.000007 4.734745e-07
1 1 1 1 2 1 total 0.000036 2.443930e-06
2 1 1 1 3 1 total 0.000035 2.333188e-06
3 1 1 1 4 1 total 0.000078 5.231199e-06
4 1 1 1 5 1 total 0.000032 2.144718e-06
5 1 1 1 6 1 total 0.000013 8.984148e-07
12 1 2 1 1 1 total 0.000007 2.770884e-07
13 1 2 1 2 1 total 0.000036 1.430245e-06
14 1 2 1 3 1 total 0.000035 1.365436e-06
15 1 2 1 4 1 total 0.000078 3.061421e-06
16 1 2 1 5 1 total 0.000032 1.255139e-06
17 1 2 1 6 1 total 0.000013 5.257735e-07
6 2 1 1 1 1 total 0.000007 3.731284e-07
7 2 1 1 2 1 total 0.000037 1.925974e-06
8 2 1 1 3 1 total 0.000035 1.838702e-06
9 2 1 1 4 1 total 0.000079 4.122522e-06
10 2 1 1 5 1 total 0.000032 1.690176e-06
11 2 1 1 6 1 total 0.000014 7.080087e-07
18 2 2 1 1 1 total 0.000007 2.050310e-07
19 2 2 1 2 1 total 0.000035 1.058307e-06
20 2 2 1 3 1 total 0.000033 1.010352e-06
21 2 2 1 4 1 total 0.000075 2.265292e-06
22 2 2 1 5 1 total 0.000031 9.287379e-07
23 2 2 1 6 1 total 0.000013 3.890451e-07
mesh 1 delayedgroup group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 0.0 0.000000
1 1 1 1 2 1 total 0.0 0.000000
2 1 1 1 3 1 total 0.0 0.000000
3 1 1 1 4 1 total 0.0 0.000000
4 1 1 1 5 1 total 0.0 0.000000
1 1 1 1 2 1 total 1.0 1.414214
2 1 1 1 3 1 total 1.0 0.868831
3 1 1 1 4 1 total 1.0 1.414214
4 1 1 1 5 1 total 1.0 1.414214
5 1 1 1 6 1 total 0.0 0.000000
12 1 2 1 1 1 total 0.0 0.000000
13 1 2 1 2 1 total 0.0 0.000000
13 1 2 1 2 1 total 1.0 0.866827
14 1 2 1 3 1 total 0.0 0.000000
15 1 2 1 4 1 total 0.0 0.000000
16 1 2 1 5 1 total 0.0 0.000000
15 1 2 1 4 1 total 1.0 0.455171
16 1 2 1 5 1 total 1.0 0.868553
17 1 2 1 6 1 total 0.0 0.000000
6 2 1 1 1 1 total 0.0 0.000000
7 2 1 1 2 1 total 0.0 0.000000
8 2 1 1 3 1 total 0.0 0.000000
9 2 1 1 4 1 total 0.0 0.000000
10 2 1 1 5 1 total 0.0 0.000000
11 2 1 1 6 1 total 0.0 0.000000
18 2 2 1 1 1 total 0.0 0.000000
19 2 2 1 2 1 total 0.0 0.000000
7 2 1 1 2 1 total 1.0 1.414214
8 2 1 1 3 1 total 1.0 1.414214
9 2 1 1 4 1 total 1.0 0.674843
10 2 1 1 5 1 total 1.0 1.414214
11 2 1 1 6 1 total 1.0 0.866033
18 2 2 1 1 1 total 1.0 1.414214
19 2 2 1 2 1 total 1.0 1.414214
20 2 2 1 3 1 total 1.0 1.414214
21 2 2 1 4 1 total 0.0 0.000000
21 2 2 1 4 1 total 1.0 0.579059
22 2 2 1 5 1 total 0.0 0.000000
23 2 2 1 6 1 total 0.0 0.000000
23 2 2 1 6 1 total 1.0 1.414214
mesh 1 delayedgroup group in nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 0.000228 0.000084
1 1 1 1 2 1 total 0.001195 0.000438
2 1 1 1 3 1 total 0.001153 0.000420
3 1 1 1 4 1 total 0.002629 0.000950
4 1 1 1 5 1 total 0.001125 0.000398
5 1 1 1 6 1 total 0.000470 0.000166
12 1 2 1 1 1 total 0.000225 0.000044
13 1 2 1 2 1 total 0.001232 0.000242
14 1 2 1 3 1 total 0.001216 0.000239
15 1 2 1 4 1 total 0.002882 0.000570
16 1 2 1 5 1 total 0.001345 0.000270
17 1 2 1 6 1 total 0.000558 0.000112
6 2 1 1 1 1 total 0.000228 0.000057
7 2 1 1 2 1 total 0.001222 0.000309
8 2 1 1 3 1 total 0.001193 0.000304
9 2 1 1 4 1 total 0.002780 0.000713
10 2 1 1 5 1 total 0.001250 0.000328
11 2 1 1 6 1 total 0.000520 0.000136
18 2 2 1 1 1 total 0.000227 0.000027
19 2 2 1 2 1 total 0.001225 0.000143
20 2 2 1 3 1 total 0.001201 0.000140
21 2 2 1 4 1 total 0.002815 0.000326
22 2 2 1 5 1 total 0.001284 0.000147
23 2 2 1 6 1 total 0.000533 0.000061
0 1 1 1 1 1 total 0.000221 0.000019
1 1 1 1 2 1 total 0.001139 0.000096
2 1 1 1 3 1 total 0.001087 0.000092
3 1 1 1 4 1 total 0.002437 0.000206
4 1 1 1 5 1 total 0.000999 0.000084
5 1 1 1 6 1 total 0.000419 0.000035
12 1 2 1 1 1 total 0.000222 0.000012
13 1 2 1 2 1 total 0.001144 0.000060
14 1 2 1 3 1 total 0.001092 0.000057
15 1 2 1 4 1 total 0.002448 0.000129
16 1 2 1 5 1 total 0.001004 0.000053
17 1 2 1 6 1 total 0.000420 0.000022
6 2 1 1 1 1 total 0.000221 0.000015
7 2 1 1 2 1 total 0.001143 0.000078
8 2 1 1 3 1 total 0.001091 0.000075
9 2 1 1 4 1 total 0.002446 0.000167
10 2 1 1 5 1 total 0.001003 0.000069
11 2 1 1 6 1 total 0.000420 0.000029
18 2 2 1 1 1 total 0.000220 0.000009
19 2 2 1 2 1 total 0.001136 0.000047
20 2 2 1 3 1 total 0.001084 0.000045
21 2 2 1 4 1 total 0.002431 0.000100
22 2 2 1 5 1 total 0.000997 0.000041
23 2 2 1 6 1 total 0.000417 0.000017
mesh 1 delayedgroup group in nuclide mean std. dev.
x y z
0 1 1 1 1 1 total 0.013345 0.004923
1 1 1 1 2 1 total 0.032674 0.011850
2 1 1 1 3 1 total 0.120923 0.043307
3 1 1 1 4 1 total 0.304289 0.106753
4 1 1 1 5 1 total 0.855760 0.286466
5 1 1 1 6 1 total 2.874120 0.965609
12 1 2 1 1 1 total 0.013367 0.002548
13 1 2 1 2 1 total 0.032520 0.006266
14 1 2 1 3 1 total 0.121250 0.023544
15 1 2 1 4 1 total 0.307552 0.060464
16 1 2 1 5 1 total 0.867665 0.175131
17 1 2 1 6 1 total 2.914635 0.587161
6 2 1 1 1 1 total 0.013357 0.003345
7 2 1 1 2 1 total 0.032590 0.008273
8 2 1 1 3 1 total 0.121103 0.031074
9 2 1 1 4 1 total 0.306111 0.080011
10 2 1 1 5 1 total 0.862660 0.235694
11 2 1 1 6 1 total 2.897534 0.788926
18 2 2 1 1 1 total 0.013360 0.001587
19 2 2 1 2 1 total 0.032564 0.003810
20 2 2 1 3 1 total 0.121158 0.014038
21 2 2 1 4 1 total 0.306653 0.035052
22 2 2 1 5 1 total 0.864587 0.096680
23 2 2 1 6 1 total 2.904111 0.325170
mesh 1 delayedgroup group in group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 1 total 0.00000 0.000000
1 1 1 1 2 1 1 total 0.00000 0.000000
2 1 1 1 3 1 1 total 0.00000 0.000000
3 1 1 1 4 1 1 total 0.00000 0.000000
4 1 1 1 5 1 1 total 0.00000 0.000000
5 1 1 1 6 1 1 total 0.00000 0.000000
12 1 2 1 1 1 1 total 0.00000 0.000000
13 1 2 1 2 1 1 total 0.00000 0.000000
14 1 2 1 3 1 1 total 0.00000 0.000000
15 1 2 1 4 1 1 total 0.00000 0.000000
16 1 2 1 5 1 1 total 0.00000 0.000000
17 1 2 1 6 1 1 total 0.00000 0.000000
6 2 1 1 1 1 1 total 0.00000 0.000000
7 2 1 1 2 1 1 total 0.00000 0.000000
8 2 1 1 3 1 1 total 0.00000 0.000000
9 2 1 1 4 1 1 total 0.00000 0.000000
10 2 1 1 5 1 1 total 0.00000 0.000000
11 2 1 1 6 1 1 total 0.00000 0.000000
18 2 2 1 1 1 1 total 0.00000 0.000000
19 2 2 1 2 1 1 total 0.00000 0.000000
20 2 2 1 3 1 1 total 0.00015 0.000151
21 2 2 1 4 1 1 total 0.00000 0.000000
22 2 2 1 5 1 1 total 0.00000 0.000000
23 2 2 1 6 1 1 total 0.00000 0.000000
0 1 1 1 1 1 total 0.013336 0.001120
1 1 1 1 2 1 total 0.032739 0.002751
2 1 1 1 3 1 total 0.120780 0.010147
3 1 1 1 4 1 total 0.302780 0.025438
4 1 1 1 5 1 total 0.849490 0.071370
5 1 1 1 6 1 total 2.853000 0.239696
12 1 2 1 1 1 total 0.013336 0.000695
13 1 2 1 2 1 total 0.032739 0.001707
14 1 2 1 3 1 total 0.120780 0.006296
15 1 2 1 4 1 total 0.302780 0.015784
16 1 2 1 5 1 total 0.849490 0.044285
17 1 2 1 6 1 total 2.853000 0.148730
6 2 1 1 1 1 total 0.013336 0.000906
7 2 1 1 2 1 total 0.032739 0.002224
8 2 1 1 3 1 total 0.120780 0.008205
9 2 1 1 4 1 total 0.302780 0.020570
10 2 1 1 5 1 total 0.849490 0.057711
11 2 1 1 6 1 total 2.853000 0.193821
18 2 2 1 1 1 total 0.013336 0.000528
19 2 2 1 2 1 total 0.032739 0.001296
20 2 2 1 3 1 total 0.120780 0.004781
21 2 2 1 4 1 total 0.302780 0.011986
22 2 2 1 5 1 total 0.849490 0.033628
23 2 2 1 6 1 total 2.853000 0.112940
mesh 1 delayedgroup group in group out nuclide mean std. dev.
x y z
0 1 1 1 1 1 1 total 0.000000 0.000000
1 1 1 1 2 1 1 total 0.000055 0.000055
2 1 1 1 3 1 1 total 0.000055 0.000034
3 1 1 1 4 1 1 total 0.000052 0.000052
4 1 1 1 5 1 1 total 0.000029 0.000029
5 1 1 1 6 1 1 total 0.000000 0.000000
12 1 2 1 1 1 1 total 0.000000 0.000000
13 1 2 1 2 1 1 total 0.000058 0.000036
14 1 2 1 3 1 1 total 0.000000 0.000000
15 1 2 1 4 1 1 total 0.000149 0.000048
16 1 2 1 5 1 1 total 0.000057 0.000035
17 1 2 1 6 1 1 total 0.000000 0.000000
6 2 1 1 1 1 1 total 0.000000 0.000000
7 2 1 1 2 1 1 total 0.000027 0.000027
8 2 1 1 3 1 1 total 0.000026 0.000026
9 2 1 1 4 1 1 total 0.000105 0.000051
10 2 1 1 5 1 1 total 0.000054 0.000054
11 2 1 1 6 1 1 total 0.000051 0.000031
18 2 2 1 1 1 1 total 0.000028 0.000028
19 2 2 1 2 1 1 total 0.000025 0.000025
20 2 2 1 3 1 1 total 0.000032 0.000032
21 2 2 1 4 1 1 total 0.000080 0.000033
22 2 2 1 5 1 1 total 0.000000 0.000000
23 2 2 1 6 1 1 total 0.000027 0.000027

View file

@ -2,42 +2,67 @@ import hashlib
import openmc
import openmc.mgxs
import pytest
from tests.testing_harness import PyAPITestHarness
@pytest.fixture
def model():
model = openmc.model.Model()
fuel = openmc.Material()
fuel.set_density('g/cm3', 10.0)
fuel.add_nuclide('U235', 1.0)
zr = openmc.Material()
zr.set_density('g/cm3', 1.0)
zr.add_nuclide('Zr90', 1.0)
model.materials.extend([fuel, zr])
box1 = openmc.model.rectangular_prism(10.0, 10.0)
box2 = openmc.model.rectangular_prism(20.0, 20.0, boundary_type='reflective')
top = openmc.ZPlane(z0=10.0, boundary_type='vacuum')
bottom = openmc.ZPlane(z0=-10.0, boundary_type='vacuum')
cell1 = openmc.Cell(fill=fuel, region=box1 & +bottom & -top)
cell2 = openmc.Cell(fill=zr, region=~box1 & box2 & +bottom & -top)
model.geometry = openmc.Geometry([cell1, cell2])
model.settings.batches = 5
model.settings.inactive = 0
model.settings.particles = 1000
# Initialize a one-group structure
energy_groups = openmc.mgxs.EnergyGroups([0, 20.e6])
# Initialize MGXS Library for a few cross section types
# for one material-filled cell in the geometry
model.mgxs_lib = openmc.mgxs.Library(model.geometry)
model.mgxs_lib.by_nuclide = False
# Test all MGXS types
model.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES
model.mgxs_lib.energy_groups = energy_groups
model.mgxs_lib.num_delayed_groups = 6
model.mgxs_lib.correction = None # Avoid warning about P0 correction
model.mgxs_lib.legendre_order = 3
model.mgxs_lib.domain_type = 'mesh'
# Instantiate a tally mesh
mesh = openmc.RegularMesh(mesh_id=1)
mesh.dimension = [2, 2]
mesh.lower_left = [-100., -100.]
mesh.width = [100., 100.]
model.mgxs_lib.domains = [mesh]
model.mgxs_lib.build_library()
# Add tallies
model.mgxs_lib.add_to_tallies_file(model.tallies, merge=False)
return model
class MGXSTestHarness(PyAPITestHarness):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize a one-group structure
energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 20.e6])
# Initialize MGXS Library for a few cross section types
# for one material-filled cell in the geometry
self.mgxs_lib = openmc.mgxs.Library(self._model.geometry)
self.mgxs_lib.by_nuclide = False
# Test all MGXS types
self.mgxs_lib.mgxs_types = openmc.mgxs.MGXS_TYPES + \
openmc.mgxs.MDGXS_TYPES
self.mgxs_lib.energy_groups = energy_groups
self.mgxs_lib.num_delayed_groups = 6
self.mgxs_lib.legendre_order = 3
self.mgxs_lib.domain_type = 'mesh'
# Instantiate a tally mesh
mesh = openmc.RegularMesh(mesh_id=1)
mesh.dimension = [2, 2]
mesh.lower_left = [-100., -100.]
mesh.width = [100., 100.]
self.mgxs_lib.domains = [mesh]
self.mgxs_lib.build_library()
# Add tallies
self.mgxs_lib.add_to_tallies_file(self._model.tallies, merge=False)
def _get_results(self, hash_output=False):
"""Digest info in the statepoint and return as a string."""
@ -45,13 +70,14 @@ class MGXSTestHarness(PyAPITestHarness):
sp = openmc.StatePoint(self._sp_name)
# Load the MGXS library from the statepoint
self.mgxs_lib.load_from_statepoint(sp)
mgxs_lib = self._model.mgxs_lib
mgxs_lib.load_from_statepoint(sp)
# Build a string from Pandas Dataframe for each 1-group MGXS
outstr = ''
for domain in self.mgxs_lib.domains:
for mgxs_type in self.mgxs_lib.mgxs_types:
mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type)
for domain in mgxs_lib.domains:
for mgxs_type in mgxs_lib.mgxs_types:
mgxs = mgxs_lib.get_mgxs(domain, mgxs_type)
df = mgxs.get_pandas_dataframe()
outstr += df.to_string() + '\n'
@ -64,6 +90,6 @@ class MGXSTestHarness(PyAPITestHarness):
return outstr
def test_mgxs_library_mesh():
harness = MGXSTestHarness('statepoint.10.h5')
def test_mgxs_library_mesh(model):
harness = MGXSTestHarness('statepoint.5.h5', model)
harness.main()

View file

@ -1,181 +0,0 @@
<?xml version="1.0"?>
<geometry>
<surface id="1" type="z-cylinder" coeffs="0. 0. 0.41" />
<surface id="2" type="z-cylinder" coeffs="0. 0. 0.475" />
<surface id="3" type="z-cylinder" coeffs="0. 0. 0.56" />
<surface id="4" type="z-cylinder" coeffs="0. 0. 0.62" />
<surface id="5" type="z-cylinder" coeffs="0. 0. 187.6" />
<surface id="6" type="z-cylinder" coeffs="0. 0. 209.0" />
<surface id="7" type="z-cylinder" coeffs="0. 0. 229.0" />
<surface id="8" type="z-cylinder" coeffs="0. 0. 249.0" boundary="vacuum" />
<surface id="31" type="z-plane" coeffs="-229.0" boundary="vacuum" />
<surface id="32" type="z-plane" coeffs="-199.0" />
<surface id="33" type="z-plane" coeffs="-193.0" />
<surface id="34" type="z-plane" coeffs="-183.0" />
<surface id="35" type="z-plane" coeffs="0.0" />
<surface id="36" type="z-plane" coeffs="183.0" />
<surface id="37" type="z-plane" coeffs="203.0" />
<surface id="38" type="z-plane" coeffs="215.0" />
<surface id="39" type="z-plane" coeffs="223.0" boundary="vacuum" />
<!-- All geometry on base universe -->
<cell id="1" fill="200" region=" -6 34 -35" /> <!-- Lower core -->
<cell id="2" fill="201" region=" -6 35 -36" /> <!-- Upper core -->
<cell id="3" material="8" region=" -7 31 -32" /> <!-- Lower core plate region -->
<cell id="4" material="9" region=" -5 32 -33" /> <!-- Bottom nozzle region -->
<cell id="5" material="12" region=" -5 33 -34" /> <!-- Bottom FA region -->
<cell id="6" material="11" region=" -5 36 -37" /> <!-- Top FA region -->
<cell id="7" material="10" region=" -5 37 -38" /> <!-- Top nozzle region -->
<cell id="8" material="7" region=" -7 38 -39" /> <!-- Upper plate region -->
<cell id="9" material="4" region="6 -7 32 -38" /> <!-- Downcomer -->
<cell id="10" material="5" region="7 -8 31 -39" /> <!-- RPV -->
<cell id="11" material="6" region="5 -6 32 -34" /> <!-- Bottom of radial reflector -->
<cell id="12" material="7" region="5 -6 36 -38" /> <!-- Top of radial reflector -->
<!-- Fuel pin, cladding, cold water -->
<cell id="21" universe="1" material="1" region="-1" />
<cell id="22" universe="1" material="2" region="1 -2" />
<cell id="23" universe="1" material="3" region="2" />
<!-- Instrumentation guide tube -->
<cell id="24" universe="2" material="3" region="-3" />
<cell id="25" universe="2" material="2" region="3 -4" />
<cell id="26" universe="2" material="3" region="4" />
<!-- Fuel pin, cladding, hot water -->
<cell id="27" universe="3" material="1" region="-1" />
<cell id="28" universe="3" material="2" region="1 -2" />
<cell id="29" universe="3" material="4" region="2" />
<!-- Instrumentation guide tube -->
<cell id="30" universe="4" material="4" region="-3" />
<cell id="31" universe="4" material="2" region="3 -4" />
<cell id="32" universe="4" material="4" region="4" />
<!-- cell for water assembly (cold) -->
<cell id="50" universe="5" material="4" region="34 -35" />
<!-- containing cell for fuel assembly -->
<cell id="60" universe="6" fill="100" region="34 -35" />
<!-- cell for water assembly (hot) -->
<cell id="70" universe="7" material="3" region="35 -36" />
<!-- containing cell for fuel assembly -->
<cell id="80" universe="8" fill="101" region="35 -36" />
<!-- Fuel Assembly (Lower Half) -->
<lattice id="100">
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<pitch>1.26 1.26</pitch>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
</universes>
</lattice>
<!-- Fuel Assembly (Upper Half) -->
<lattice id="101">
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<pitch>1.26 1.26</pitch>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
</universes>
</lattice>
<!-- Core Lattice (Lower Half) -->
<lattice id="200">
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<pitch>21.42 21.42</pitch>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
</universes>
</lattice>
<!-- Core Lattice (Upper Half) -->
<lattice id="201">
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<pitch>21.42 21.42</pitch>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
</universes>
</lattice>
</geometry>

View file

@ -0,0 +1,55 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell id="1" material="1" region="1 -2 3 -4 10 -9" universe="1" />
<cell id="2" material="2" region="~(1 -2 3 -4) (5 -6 7 -8) 10 -9" universe="1" />
<surface coeffs="-5.0" id="1" name="minimum x" type="x-plane" />
<surface coeffs="5.0" id="2" name="maximum x" type="x-plane" />
<surface coeffs="-5.0" id="3" name="minimum y" type="y-plane" />
<surface coeffs="5.0" id="4" name="maximum y" type="y-plane" />
<surface boundary="reflective" coeffs="-10.0" id="5" name="minimum x" type="x-plane" />
<surface boundary="reflective" coeffs="10.0" id="6" name="maximum x" type="x-plane" />
<surface boundary="reflective" coeffs="-10.0" id="7" name="minimum y" type="y-plane" />
<surface boundary="reflective" coeffs="10.0" id="8" name="maximum y" type="y-plane" />
<surface boundary="vacuum" coeffs="10.0" id="9" type="z-plane" />
<surface boundary="vacuum" coeffs="-10.0" id="10" type="z-plane" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1">
<density units="g/cm3" value="10.0" />
<nuclide ao="1.0" name="U235" />
</material>
<material id="2">
<density units="g/cm3" value="1.0" />
<nuclide ao="1.0" name="Zr90" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>1000</particles>
<batches>5</batches>
<inactive>0</inactive>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>
<mesh id="1">
<dimension>3 3 3</dimension>
<lower_left>-10.0 -10.0 -10.0</lower_left>
<upper_right>10.0 10.0 10.0</upper_right>
</mesh>
<filter id="1" type="meshsurface">
<bins>1</bins>
</filter>
<filter id="2" type="energy">
<bins>0.0 0.253 20000000.0</bins>
</filter>
<tally id="1">
<filters>1</filters>
<scores>current</scores>
</tally>
<tally id="2">
<filters>1 2</filters>
<scores>current</scores>
</tally>
</tallies>

View file

@ -1,270 +0,0 @@
<?xml version="1.0"?>
<materials>
<!-- Fuel composition -->
<material id="1">
<density value="10.062" units="g/cm3" />
<nuclide name="U234" ao="4.9476e-6" />
<nuclide name="U235" ao="4.8218e-4" />
<nuclide name="U236" ao="9.0402e-5" />
<nuclide name="U238" ao="2.1504e-2" />
<nuclide name="Np237" ao="7.3733e-6" />
<nuclide name="Pu238" ao="1.5148e-6" />
<nuclide name="Pu239" ao="1.3955e-4" />
<nuclide name="Pu240" ao="3.4405e-5" />
<nuclide name="Pu241" ao="2.1439e-5" />
<nuclide name="Pu242" ao="3.7422e-6" />
<nuclide name="Am241" ao="4.5041e-7" />
<nuclide name="Am242_m1" ao="9.2301e-9" />
<nuclide name="Am243" ao="4.7878e-7" />
<nuclide name="Cm242" ao="1.0485e-7" />
<nuclide name="Cm243" ao="1.4268e-9" />
<nuclide name="Cm244" ao="8.8756e-8" />
<nuclide name="Cm245" ao="3.5285e-9" />
<nuclide name="Mo95" ao="2.6497e-5" />
<nuclide name="Tc99" ao="3.2772e-5" />
<nuclide name="Ru101" ao="3.0742e-5" />
<nuclide name="Ru103" ao="2.3505e-6" />
<nuclide name="Ag109" ao="2.0009e-6" />
<nuclide name="Xe135" ao="1.0801e-8" />
<nuclide name="Cs133" ao="3.4612e-5" />
<nuclide name="Nd143" ao="2.6078e-5" />
<nuclide name="Nd145" ao="1.9898e-5" />
<nuclide name="Sm147" ao="1.6128e-6" />
<nuclide name="Sm149" ao="1.1627e-7" />
<nuclide name="Sm150" ao="7.1727e-6" />
<nuclide name="Sm151" ao="5.4947e-7" />
<nuclide name="Sm152" ao="3.0221e-6" />
<nuclide name="Eu153" ao="2.6209e-6" />
<nuclide name="Gd155" ao="1.5369e-9" />
<nuclide name="O16" ao="4.5737e-2" />
</material>
<!-- Cladding composition -->
<material id="2">
<density value="5.77" units="g/cm3" />
<nuclide name="Zr90" ao="0.5145" />
<nuclide name="Zr91" ao="0.1122" />
<nuclide name="Zr92" ao="0.1715" />
<nuclide name="Zr94" ao="0.1738" />
<nuclide name="Zr96" ao="0.0280" />
</material>
<!-- Cold borated water -->
<material id="3">
<density value="0.07416" units="atom/b-cm" />
<nuclide name="H1" ao="2.0" />
<nuclide name="O16" ao="1.0" />
<nuclide name="B10" ao="6.490e-4" />
<nuclide name="B11" ao="2.689e-3" />
<sab name="c_H_in_H2O" />
</material>
<!-- Hot borated water -->
<material id="4">
<density value="0.06614" units="atom/b-cm" />
<nuclide name="H1" ao="2.0" />
<nuclide name="O16" ao="1.0" />
<nuclide name="B10" ao="6.490e-4" />
<nuclide name="B11" ao="2.689e-3" />
<sab name="c_H_in_H2O" />
</material>
<!-- RPV Composition -->
<material id="5">
<density value="7.9" units="g/cm3" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Ni61" wo="0.0001183" />
<nuclide name="Ni62" wo="0.0003835" />
<nuclide name="Ni64" wo="0.0001008" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Mo92" wo="0.000849" />
<nuclide name="Mo94" wo="0.0005418" />
<nuclide name="Mo95" wo="0.0009438" />
<nuclide name="Mo96" wo="0.0010002" />
<nuclide name="Mo97" wo="0.0005796" />
<nuclide name="Mo98" wo="0.0014814" />
<nuclide name="Mo100" wo="0.0006042" />
<nuclide name="Si28" wo="0.00367464" />
<nuclide name="Si29" wo="0.00019336" />
<nuclide name="Si30" wo="0.000132" />
<nuclide name="Cr50" wo="0.00010435" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="Cr53" wo="0.00024185" />
<nuclide name="Cr54" wo="6.1325e-05" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
<nuclide name="Cu65" wo="0.0006304" />
</material>
<!-- Lower radial reflector -->
<material id="6">
<density value="4.32" units="g/cm3" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-5" />
<nuclide name="B11" wo="1.40499e-4" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Ni60" wo="0.022034425592" />
<nuclide name="Ni61" wo="0.000973510811" />
<nuclide name="Ni62" wo="0.003155886695" />
<nuclide name="Ni64" wo="0.000829500336" />
<nuclide name="Mn55" wo="0.0182870" />
<nuclide name="Si28" wo="0.00839976771" />
<nuclide name="Si29" wo="0.00044199679" />
<nuclide name="Si30" wo="0.0003017355" />
<nuclide name="Cr50" wo="0.007251360806" />
<nuclide name="Cr52" wo="0.145407678031" />
<nuclide name="Cr53" wo="0.016806340306" />
<nuclide name="Cr54" wo="0.004261520857" />
<sab name="c_H_in_H2O" />
</material>
<!-- Upper radial reflector / Top plate region -->
<material id="7">
<density value="4.28" units="g/cm3" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-5" />
<nuclide name="B11" wo="1.26481e-4" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Ni60" wo="0.022240333032" />
<nuclide name="Ni61" wo="0.000982608081" />
<nuclide name="Ni62" wo="0.003185377845" />
<nuclide name="Ni64" wo="0.000837251856" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Si28" wo="0.00847831314" />
<nuclide name="Si29" wo="0.00044612986" />
<nuclide name="Si30" wo="0.000304557" />
<nuclide name="Cr50" wo="0.00731912987" />
<nuclide name="Cr52" wo="0.146766614995" />
<nuclide name="Cr53" wo="0.01696340737" />
<nuclide name="Cr54" wo="0.004301347765" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom plate region -->
<material id="8">
<density value="7.184" units="g/cm3" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-6" />
<nuclide name="B11" wo="1.68974e-5" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Ni60" wo="0.023850159704" />
<nuclide name="Ni61" wo="0.001053732407" />
<nuclide name="Ni62" wo="0.003415945715" />
<nuclide name="Ni64" wo="0.000897854832" />
<nuclide name="Mn55" wo="0.0197940" />
<nuclide name="Si28" wo="0.00909197802" />
<nuclide name="Si29" wo="0.00047842098" />
<nuclide name="Si30" wo="0.000326601" />
<nuclide name="Cr50" wo="0.007848910646" />
<nuclide name="Cr52" wo="0.157390026871" />
<nuclide name="Cr53" wo="0.018191270146" />
<nuclide name="Cr54" wo="0.004612692337" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom nozzle region -->
<material id="9">
<density value="2.53" units="g/cm3" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-5" />
<nuclide name="B11" wo="3.59854e-4" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Ni60" wo="0.018811987544" />
<nuclide name="Ni61" wo="0.000831139127" />
<nuclide name="Ni62" wo="0.002694352115" />
<nuclide name="Ni64" wo="0.000708189552" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Si28" wo="0.007171335558" />
<nuclide name="Si29" wo="0.000377356542" />
<nuclide name="Si30" wo="0.0002576079" />
<nuclide name="Cr50" wo="0.006190885148" />
<nuclide name="Cr52" wo="0.124142524198" />
<nuclide name="Cr53" wo="0.014348496148" />
<nuclide name="Cr54" wo="0.003638294506" />
<sab name="c_H_in_H2O" />
</material>
<!-- Top nozzle region -->
<material id="10">
<density value="1.746" units="g/cm3" />
<nuclide name="H1" wo="0.0358870" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="1.15699e-4" />
<nuclide name="B11" wo="5.27075e-4" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Ni60" wo="0.0163554502" />
<nuclide name="Ni61" wo="0.000722605975" />
<nuclide name="Ni62" wo="0.002342513875" />
<nuclide name="Ni64" wo="0.0006157116" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Si28" wo="0.006234853554" />
<nuclide name="Si29" wo="0.000328078746" />
<nuclide name="Si30" wo="0.0002239677" />
<nuclide name="Cr50" wo="0.005382452306" />
<nuclide name="Cr52" wo="0.107931450781" />
<nuclide name="Cr53" wo="0.012474806806" />
<nuclide name="Cr54" wo="0.003163190107" />
<sab name="c_H_in_H2O" />
</material>
<!-- Top of Fuel Assemblies -->
<material id="11">
<density value="3.044" units="g/cm3" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-5" />
<nuclide name="B11" wo="2.39272e-4" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom of Fuel Assemblies -->
<material id="12">
<density value="1.762" units="g/cm3" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-5" />
<nuclide name="B11" wo="4.30120e-4" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
</material>
</materials>

File diff suppressed because it is too large Load diff

View file

@ -1,18 +0,0 @@
<?xml version="1.0"?>
<settings>
<run_mode>eigenvalue</run_mode>
<batches>10</batches>
<inactive>5</inactive>
<particles>100</particles>
<source>
<space type="box">
<parameters>
-160 -160 -183
160 160 183
</parameters>
</space>
</source>
</settings>

View file

@ -1,31 +0,0 @@
<?xml version="1.0"?>
<tallies>
<mesh id="1">
<type>regular</type>
<lower_left>-182.07 -182.07 -183.00</lower_left>
<upper_right>182.07 182.07 183.00</upper_right>
<dimension>17 17 17</dimension>
</mesh>
<filter id="1">
<type>meshsurface</type>
<bins>1</bins>
</filter>
<filter id="2">
<type>energy</type>
<bins>0. 0.253 20.0e6</bins>
</filter>
<tally id="1">
<filters>1</filters>
<scores>current</scores>
</tally>
<tally id="2">
<filters>1 2</filters>
<scores>current</scores>
</tally>
</tallies>

View file

@ -1,6 +1,53 @@
from tests.testing_harness import HashedTestHarness
import openmc
import pytest
from tests.testing_harness import PyAPITestHarness
def test_score_current():
harness = HashedTestHarness('statepoint.10.h5')
@pytest.fixture
def model():
model = openmc.model.Model()
fuel = openmc.Material()
fuel.set_density('g/cm3', 10.0)
fuel.add_nuclide('U235', 1.0)
zr = openmc.Material()
zr.set_density('g/cm3', 1.0)
zr.add_nuclide('Zr90', 1.0)
model.materials.extend([fuel, zr])
box1 = openmc.model.rectangular_prism(10.0, 10.0)
box2 = openmc.model.rectangular_prism(20.0, 20.0, boundary_type='reflective')
top = openmc.ZPlane(z0=10.0, boundary_type='vacuum')
bottom = openmc.ZPlane(z0=-10.0, boundary_type='vacuum')
cell1 = openmc.Cell(fill=fuel, region=box1 & +bottom & -top)
cell2 = openmc.Cell(fill=zr, region=~box1 & box2 & +bottom & -top)
model.geometry = openmc.Geometry([cell1, cell2])
model.settings.batches = 5
model.settings.inactive = 0
model.settings.particles = 1000
mesh = openmc.Mesh()
mesh.lower_left = (-10.0, -10.0, -10.0)
mesh.upper_right = (10.0, 10.0, 10.0)
mesh.dimension = (3, 3, 3)
mesh_surface_filter = openmc.MeshSurfaceFilter(mesh)
energy_filter = openmc.EnergyFilter([0.0, 0.253, 20.0e6])
tally1 = openmc.Tally()
tally1.filters = [mesh_surface_filter]
tally1.scores = ['current']
tally2 = openmc.Tally()
tally2.filters = [mesh_surface_filter, energy_filter]
tally2.scores = ['current']
model.tallies.extend([tally1, tally2])
return model
def test_score_current(model):
harness = PyAPITestHarness('statepoint.5.h5', model)
harness.main()

View file

@ -1,311 +1,45 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell fill="200" id="1" region="-6 34 -35" universe="0" />
<cell fill="201" id="2" region="-6 35 -36" universe="0" />
<cell id="3" material="8" region="-7 31 -32" universe="0" />
<cell id="4" material="9" region="-5 32 -33" universe="0" />
<cell id="5" material="12" region="-5 33 -34" universe="0" />
<cell id="6" material="11" region="-5 36 -37" universe="0" />
<cell id="7" material="10" region="-5 37 -38" universe="0" />
<cell id="8" material="7" region="-7 38 -39" universe="0" />
<cell id="9" material="9" region="6 -7 32 -38" universe="0" />
<cell id="10" material="5" region="7 -8 31 -39" universe="0" />
<cell id="11" material="6" region="5 -6 32 -34" universe="0" />
<cell id="12" material="7" region="5 -6 36 -38" universe="0" />
<cell id="21" material="1" region="-1" universe="1" />
<cell id="22" material="2" region="1 -2" universe="1" />
<cell id="23" material="3" region="2" universe="1" />
<cell id="24" material="3" region="-3" universe="2" />
<cell id="25" material="2" region="3 -4" universe="2" />
<cell id="26" material="3" region="4" universe="2" />
<cell id="27" material="1" region="-1" universe="3" />
<cell id="28" material="2" region="1 -2" universe="3" />
<cell id="29" material="4" region="2" universe="3" />
<cell id="30" material="4" region="-3" universe="4" />
<cell id="31" material="2" region="3 -4" universe="4" />
<cell id="32" material="4" region="4" universe="4" />
<cell id="50" material="3" region="34 -35" universe="5" />
<cell fill="100" id="60" region="34 -35" universe="6" />
<cell id="70" material="4" region="35 -36" universe="7" />
<cell fill="101" id="80" region="35 -36" universe="8" />
<lattice id="100" name="Fuel assembly (lower half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<cell id="1" material="1" region="-1" universe="1" />
<cell id="2" material="2" region="1" universe="1" />
<cell fill="2" id="3" region="2 -3 4 -5" universe="3" />
<lattice id="2">
<pitch>1.2 1.2</pitch>
<outer>1</outer>
<dimension>2 2</dimension>
<lower_left>-1.2 -1.2</lower_left>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 </universes>
1 1
1 1 </universes>
</lattice>
<lattice id="101" name="Fuel assembly (upper half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </universes>
</lattice>
<lattice id="200" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 </universes>
</lattice>
<lattice id="201" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 </universes>
</lattice>
<surface coeffs="0.0 0.0 0.41" id="1" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.475" id="2" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.56" id="3" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.62" id="4" type="z-cylinder" />
<surface coeffs="0.0 0.0 187.6" id="5" type="z-cylinder" />
<surface coeffs="0.0 0.0 209.0" id="6" type="z-cylinder" />
<surface coeffs="0.0 0.0 229.0" id="7" type="z-cylinder" />
<surface boundary="vacuum" coeffs="0.0 0.0 249.0" id="8" type="z-cylinder" />
<surface boundary="vacuum" coeffs="-229.0" id="31" type="z-plane" />
<surface coeffs="-199.0" id="32" type="z-plane" />
<surface coeffs="-193.0" id="33" type="z-plane" />
<surface coeffs="-183.0" id="34" type="z-plane" />
<surface coeffs="0.0" id="35" type="z-plane" />
<surface coeffs="183.0" id="36" type="z-plane" />
<surface coeffs="203.0" id="37" type="z-plane" />
<surface coeffs="215.0" id="38" type="z-plane" />
<surface boundary="vacuum" coeffs="223.0" id="39" type="z-plane" />
<surface coeffs="0.0 0.0 0.4" id="1" type="z-cylinder" />
<surface boundary="reflective" coeffs="-1.2" id="2" name="minimum x" type="x-plane" />
<surface boundary="reflective" coeffs="1.2" id="3" name="maximum x" type="x-plane" />
<surface boundary="reflective" coeffs="-1.2" id="4" name="minimum y" type="y-plane" />
<surface boundary="reflective" coeffs="1.2" id="5" name="maximum y" type="y-plane" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1" name="UOX fuel">
<density units="g/cm3" value="10.062" />
<nuclide ao="4.9476e-06" name="U234" />
<nuclide ao="0.00048218" name="U235" />
<nuclide ao="0.021504" name="U238" />
<nuclide ao="1.0801e-08" name="Xe135" />
<nuclide ao="0.045737" name="O16" />
<material depletable="true" id="1" name="UO2">
<density units="g/cm3" value="10.29769" />
<nuclide ao="4.4843e-06" name="U234" />
<nuclide ao="0.00055815" name="U235" />
<nuclide ao="0.022408" name="U238" />
<nuclide ao="0.045829" name="O16" />
</material>
<material id="2" name="Zircaloy">
<density units="g/cm3" value="5.77" />
<nuclide ao="0.5145" name="Zr90" />
<nuclide ao="0.1122" name="Zr91" />
<nuclide ao="0.1715" name="Zr92" />
<nuclide ao="0.1738" name="Zr94" />
<nuclide ao="0.028" name="Zr96" />
</material>
<material id="3" name="Cold borated water">
<density units="atom/b-cm" value="0.07416" />
<material id="2" name="light water">
<density units="g/cm3" value="1.0" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="4" name="Hot borated water">
<density units="atom/b-cm" value="0.06614" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="5" name="Reactor pressure vessel steel">
<density units="g/cm3" value="7.9" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
</material>
<material id="6" name="Lower radial reflector">
<density units="g/cm3" value="4.32" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-05" />
<nuclide name="B11" wo="0.000140499" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Mn55" wo="0.018287" />
<nuclide name="Cr52" wo="0.145407678031" />
<sab name="c_H_in_H2O" />
</material>
<material id="7" name="Upper radial reflector / Top plate region">
<density units="g/cm3" value="4.28" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-05" />
<nuclide name="B11" wo="0.000126481" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Cr52" wo="0.146766614995" />
<sab name="c_H_in_H2O" />
</material>
<material id="8" name="Bottom plate region">
<density units="g/cm3" value="7.184" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-06" />
<nuclide name="B11" wo="1.68974e-05" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Mn55" wo="0.019794" />
<nuclide name="Cr52" wo="0.157390026871" />
<sab name="c_H_in_H2O" />
</material>
<material id="9" name="Bottom nozzle region">
<density units="g/cm3" value="2.53" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-05" />
<nuclide name="B11" wo="0.000359854" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Cr52" wo="0.124142524198" />
<sab name="c_H_in_H2O" />
</material>
<material id="10" name="Top nozzle region">
<density units="g/cm3" value="1.746" />
<nuclide name="H1" wo="0.035887" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="0.000115699" />
<nuclide name="B11" wo="0.000527075" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Cr52" wo="0.107931450781" />
<sab name="c_H_in_H2O" />
</material>
<material id="11" name="Top of fuel assemblies">
<density units="g/cm3" value="3.044" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-05" />
<nuclide name="B11" wo="0.000239272" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<material id="12" name="Bottom of fuel assemblies">
<density units="g/cm3" value="1.762" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-05" />
<nuclide name="B11" wo="0.00043012" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<particles>1000</particles>
<batches>10</batches>
<inactive>5</inactive>
<source strength="1.0">
<space type="box">
<parameters>-160 -160 -183 160 160 183</parameters>
</space>
</source>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>
@ -313,7 +47,7 @@
<bins>0.0 0.253 1000.0 1000000.0 20000000.0</bins>
</filter>
<filter id="2" type="distribcell">
<bins>60</bins>
<bins>1</bins>
</filter>
<tally id="1" name="distribcell tally">
<filters>1 2</filters>

View file

@ -1 +1,97 @@
eac8fb56a8146b9e186ac9fb003753f4a0a18d4159d10e6fa51da4856baef66a10a0f5fb10c5727b51c6e44d81c147a8a7348ad9c9f7119a6ec33e0361082376
[[1.63731762e-05 5.08325999e-04]
[3.27547470e-01 1.77506218e-01]
[1.89164083e-02 7.22719366e-01]], [[1.64200315e-05 5.45231503e-04]
[3.24031537e-01 1.75537230e-01]
[1.87708717e-02 7.26768216e-01]], [[1.67487818e-05 5.03394672e-04]
[3.07780931e-01 1.67166322e-01]
[1.97449893e-02 7.06598738e-01]], [[1.63603106e-05 6.10423337e-04]
[3.32313666e-01 1.79982864e-01]
[1.90686364e-02 7.22662206e-01]][[4.65536263e-07 4.34762669e-05]
[9.14451087e-03 4.56766386e-03]
[7.87091351e-04 1.04610084e-02]], [[1.70217471e-07 3.74604055e-05]
[9.18903111e-03 4.56228307e-03]
[1.74179620e-04 9.17281345e-03]], [[2.49291594e-07 1.81470751e-05]
[8.34746285e-03 4.15219947e-03]
[3.57935129e-04 1.00438242e-02]], [[4.12850822e-07 3.98122204e-05]
[1.38191650e-02 6.82224745e-03]
[6.79096490e-04 9.85922061e-03]][[1.03849782e-06 8.14983256e-04]
[1.13114721e+00 5.60394847e-01]
[1.40550899e-06 5.11848857e-01]], [[1.99773314e-06 1.03955500e-03]
[1.42269343e-01 9.92372469e-02]
[3.30482612e-05 8.08235307e-01]], [[1.45630159e-05 2.22446467e-04]
[1.30357824e-02 2.93669452e-02]
[3.05346682e-04 1.10154874e+00]], [[4.83030533e-05 9.03907895e-05]
[5.22127114e-03 1.11935954e-02]
[7.61611053e-02 4.57115627e-01]][[1.87165262e-08 1.43906416e-05]
[2.05916324e-02 1.01675733e-02]
[2.50902573e-08 8.54377830e-03]], [[1.12098060e-07 7.06870145e-05]
[2.16279434e-03 1.42142705e-03]
[1.22851164e-05 1.41445724e-02]], [[2.08629342e-07 1.63602148e-06]
[1.08988258e-04 2.01647731e-04]
[7.14052741e-06 9.13467415e-03]], [[6.49497971e-07 1.17295883e-06]
[7.03193479e-05 1.45388818e-04]
[1.11307638e-03 5.92861613e-03]][[0.28708077 0.27231775]], [[0.283269 0.26846215]], [[0.26933717 0.25561967]], [[0.29146272 0.27665912]], [[0.03591854 0.2267151 ]], [[0.03618374 0.23663228]], [[0.03393119 0.22268261]], [[0.03627092 0.22248212]], [[0.00333501 0.28502144]], [[0.00339378 0.2823686 ]], [[0.0032646 0.27622413]], [[0.0033623 0.28752397]], [[0.02014593 0.11667962]], [[0.01997231 0.11538764]], [[0.02100971 0.11974205]], [[0.02030272 0.11659029]][[0.00908247 0.00614665]], [[0.00911888 0.00556208]], [[0.00831969 0.00596124]], [[0.01375328 0.00849244]], [[0.00106067 0.00719168]], [[0.00113262 0.00790992]], [[0.00067545 0.00732313]], [[0.00134675 0.00584628]], [[5.86657354e-05 4.85962742e-03]], [[3.78231391e-05 3.26052035e-03]], [[7.89746053e-05 5.03120906e-03]], [[2.86395600e-05 4.89110417e-03]], [[0.00078861 0.00414495]], [[0.00017413 0.00090648]], [[0.00035855 0.00190835]], [[0.00068051 0.0036777 ]][[2.07154706e-04]
[4.29264961e-01]
[1.29926403e-01]], [[2.04124023e-04]
[4.23635331e-01]
[1.27891698e-01]], [[1.94482255e-04]
[4.02735295e-01]
[1.22027057e-01]], [[2.10260769e-04]
[4.35906468e-01]
[1.32005105e-01]], [[0.00022426]
[0.06105851]
[0.20135086]], [[0.00026389]
[0.0612101 ]
[0.21134203]], [[0.00023084]
[0.05761498]
[0.19876799]], [[0.00032256]
[0.061623 ]
[0.19680747]], [[5.87610156e-05]
[1.06427230e-02]
[2.77654967e-01]], [[5.94899925e-05]
[1.06822132e-02]
[2.75020675e-01]], [[5.93176564e-05]
[1.03968293e-02]
[2.69032575e-01]], [[5.94408186e-05]
[1.06809621e-02]
[2.80145865e-01]], [[3.45195544e-05]
[4.08749343e-03]
[1.32703540e-01]], [[3.41476180e-05]
[4.04112643e-03]
[1.31284684e-01]], [[3.55075881e-05]
[4.20014745e-03]
[1.36516110e-01]], [[3.45190823e-05]
[4.08609920e-03]
[1.32772398e-01]][[6.53616088e-06]
[1.01396032e-02]
[4.17862796e-03]], [[6.14101518e-06]
[1.01647874e-02]
[3.28144648e-03]], [[6.21879601e-06]
[9.29002877e-03]
[4.29521996e-03]], [[9.37998012e-06]
[1.53282674e-02]
[5.13014723e-03]], [[4.29725320e-05]
[1.28419933e-03]
[7.15501363e-03]], [[3.69392134e-05]
[1.38678579e-03]
[7.86925329e-03]], [[1.70223774e-05]
[7.65771551e-04]
[7.31421975e-03]], [[3.86750728e-05]
[1.59354492e-03]
[5.78376198e-03]], [[4.00936601e-07]
[1.10265266e-04]
[4.85873047e-03]], [[1.02736776e-06]
[7.78918832e-05]
[3.25980910e-03]], [[8.71027724e-07]
[1.64820060e-04]
[5.02912867e-03]], [[8.63231446e-07]
[8.45518855e-05]
[4.89045708e-03]], [[9.39068799e-07]
[1.12928697e-04]
[4.21779516e-03]], [[1.94712273e-07]
[2.39886479e-05]
[9.22741200e-04]], [[4.30155635e-07]
[5.18679547e-05]
[1.94104652e-03]], [[8.32395987e-07]
[1.00319931e-04]
[3.73878581e-03]]

View file

@ -1,26 +1,61 @@
import hashlib
import openmc
import pytest
from tests.testing_harness import PyAPITestHarness
@pytest.fixture
def model():
model = openmc.model.Model()
fuel = openmc.Material(name='UO2')
fuel.set_density('g/cm3', 10.29769)
fuel.add_nuclide("U234", 4.4843e-6)
fuel.add_nuclide("U235", 5.5815e-4)
fuel.add_nuclide("U238", 2.2408e-2)
fuel.add_nuclide("O16", 4.5829e-2)
water = openmc.Material(name='light water')
water.add_nuclide('H1', 2.0)
water.add_nuclide('O16', 1.0)
water.set_density('g/cm3', 1.0)
water.add_s_alpha_beta('c_H_in_H2O')
model.materials.extend([fuel, water])
cyl = openmc.ZCylinder(r=0.4)
pin = openmc.model.pin([cyl], [fuel, water])
d = 1.2
lattice = openmc.RectLattice()
lattice.lower_left = (-d, -d)
lattice.pitch = (d, d)
lattice.outer = pin
lattice.universes = [
[pin, pin],
[pin, pin],
]
box = openmc.model.rectangular_prism(2*d, 2*d, boundary_type='reflective')
main_cell = openmc.Cell(fill=lattice, region=box)
model.geometry = openmc.Geometry([main_cell])
model.settings.batches = 10
model.settings.inactive = 5
model.settings.particles = 1000
energy_filter = openmc.EnergyFilter([0.0, 0.253, 1.0e3, 1.0e6, 20.0e6])
distrib_filter = openmc.DistribcellFilter(pin.cells[1])
tally = openmc.Tally(name='distribcell tally')
tally.filters = [energy_filter, distrib_filter]
tally.scores = ['nu-fission', 'total']
tally.nuclides = ['U234', 'U235', 'U238']
model.tallies.append(tally)
return model
class TallyAggregationTestHarness(PyAPITestHarness):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize the filters
energy_filter = openmc.EnergyFilter([0.0, 0.253, 1.0e3, 1.0e6, 20.0e6])
distrib_filter = openmc.DistribcellFilter(60)
# Initialized the tallies
tally = openmc.Tally(name='distribcell tally')
tally.filters = [energy_filter, distrib_filter]
tally.scores = ['nu-fission', 'total']
tally.nuclides = ['U234', 'U235', 'U238']
self._model.tallies.append(tally)
def _get_results(self, hash_output=True):
def _get_results(self, hash_output=False):
"""Digest info in the statepoint and return as a string."""
# Read the statepoint file.
@ -52,15 +87,9 @@ class TallyAggregationTestHarness(PyAPITestHarness):
outstr += ', '.join(map(str, tally_sum.mean))
outstr += ', '.join(map(str, tally_sum.std_dev))
# Hash the results if necessary
if hash_output:
sha512 = hashlib.sha512()
sha512.update(outstr.encode('utf-8'))
outstr = sha512.hexdigest()
return outstr
def test_tally_aggregation():
harness = TallyAggregationTestHarness('statepoint.10.h5')
def test_tally_aggregation(model):
harness = TallyAggregationTestHarness('statepoint.10.h5', model)
harness.main()

View file

@ -1,338 +1,55 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell fill="200" id="1" region="-6 34 -35" universe="0" />
<cell fill="201" id="2" region="-6 35 -36" universe="0" />
<cell id="3" material="8" region="-7 31 -32" universe="0" />
<cell id="4" material="9" region="-5 32 -33" universe="0" />
<cell id="5" material="12" region="-5 33 -34" universe="0" />
<cell id="6" material="11" region="-5 36 -37" universe="0" />
<cell id="7" material="10" region="-5 37 -38" universe="0" />
<cell id="8" material="7" region="-7 38 -39" universe="0" />
<cell id="9" material="9" region="6 -7 32 -38" universe="0" />
<cell id="10" material="5" region="7 -8 31 -39" universe="0" />
<cell id="11" material="6" region="5 -6 32 -34" universe="0" />
<cell id="12" material="7" region="5 -6 36 -38" universe="0" />
<cell id="21" material="1" region="-1" universe="1" />
<cell id="22" material="2" region="1 -2" universe="1" />
<cell id="23" material="3" region="2" universe="1" />
<cell id="24" material="3" region="-3" universe="2" />
<cell id="25" material="2" region="3 -4" universe="2" />
<cell id="26" material="3" region="4" universe="2" />
<cell id="27" material="1" region="-1" universe="3" />
<cell id="28" material="2" region="1 -2" universe="3" />
<cell id="29" material="4" region="2" universe="3" />
<cell id="30" material="4" region="-3" universe="4" />
<cell id="31" material="2" region="3 -4" universe="4" />
<cell id="32" material="4" region="4" universe="4" />
<cell id="50" material="3" region="34 -35" universe="5" />
<cell fill="100" id="60" region="34 -35" universe="6" />
<cell id="70" material="4" region="35 -36" universe="7" />
<cell fill="101" id="80" region="35 -36" universe="8" />
<lattice id="100" name="Fuel assembly (lower half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 </universes>
</lattice>
<lattice id="101" name="Fuel assembly (upper half)">
<pitch>1.26 1.26</pitch>
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 </universes>
</lattice>
<lattice id="200" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 </universes>
</lattice>
<lattice id="201" name="Core lattice (lower half)">
<pitch>21.42 21.42</pitch>
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 </universes>
</lattice>
<surface coeffs="0.0 0.0 0.41" id="1" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.475" id="2" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.56" id="3" type="z-cylinder" />
<surface coeffs="0.0 0.0 0.62" id="4" type="z-cylinder" />
<surface coeffs="0.0 0.0 187.6" id="5" type="z-cylinder" />
<surface coeffs="0.0 0.0 209.0" id="6" type="z-cylinder" />
<surface coeffs="0.0 0.0 229.0" id="7" type="z-cylinder" />
<surface boundary="vacuum" coeffs="0.0 0.0 249.0" id="8" type="z-cylinder" />
<surface boundary="vacuum" coeffs="-229.0" id="31" type="z-plane" />
<surface coeffs="-199.0" id="32" type="z-plane" />
<surface coeffs="-193.0" id="33" type="z-plane" />
<surface coeffs="-183.0" id="34" type="z-plane" />
<surface coeffs="0.0" id="35" type="z-plane" />
<surface coeffs="183.0" id="36" type="z-plane" />
<surface coeffs="203.0" id="37" type="z-plane" />
<surface coeffs="215.0" id="38" type="z-plane" />
<surface boundary="vacuum" coeffs="223.0" id="39" type="z-plane" />
<cell id="1" material="1" region="-1" universe="1" />
<cell id="2" material="2" region="1 -2" universe="1" />
<surface coeffs="0.0 0.0 5.0" id="1" type="z-cylinder" />
<surface boundary="vacuum" coeffs="0.0 0.0 10.0" id="2" type="z-cylinder" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1" name="UOX fuel">
<density units="g/cm3" value="10.062" />
<nuclide ao="4.9476e-06" name="U234" />
<nuclide ao="0.00048218" name="U235" />
<nuclide ao="0.021504" name="U238" />
<nuclide ao="1.0801e-08" name="Xe135" />
<nuclide ao="0.045737" name="O16" />
<material depletable="true" id="1">
<density units="g/cm3" value="10.0" />
<nuclide ao="1.0" name="U234" />
<nuclide ao="4.0" name="U235" />
<nuclide ao="95.0" name="U238" />
</material>
<material id="2" name="Zircaloy">
<density units="g/cm3" value="5.77" />
<nuclide ao="0.5145" name="Zr90" />
<nuclide ao="0.1122" name="Zr91" />
<nuclide ao="0.1715" name="Zr92" />
<nuclide ao="0.1738" name="Zr94" />
<nuclide ao="0.028" name="Zr96" />
</material>
<material id="3" name="Cold borated water">
<density units="atom/b-cm" value="0.07416" />
<material id="2" name="light water">
<density units="g/cm3" value="1.0" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="4" name="Hot borated water">
<density units="atom/b-cm" value="0.06614" />
<nuclide ao="2.0" name="H1" />
<nuclide ao="1.0" name="O16" />
<nuclide ao="0.000649" name="B10" />
<nuclide ao="0.002689" name="B11" />
<sab name="c_H_in_H2O" />
</material>
<material id="5" name="Reactor pressure vessel steel">
<density units="g/cm3" value="7.9" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
</material>
<material id="6" name="Lower radial reflector">
<density units="g/cm3" value="4.32" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-05" />
<nuclide name="B11" wo="0.000140499" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Mn55" wo="0.018287" />
<nuclide name="Cr52" wo="0.145407678031" />
<sab name="c_H_in_H2O" />
</material>
<material id="7" name="Upper radial reflector / Top plate region">
<density units="g/cm3" value="4.28" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-05" />
<nuclide name="B11" wo="0.000126481" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Cr52" wo="0.146766614995" />
<sab name="c_H_in_H2O" />
</material>
<material id="8" name="Bottom plate region">
<density units="g/cm3" value="7.184" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-06" />
<nuclide name="B11" wo="1.68974e-05" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Mn55" wo="0.019794" />
<nuclide name="Cr52" wo="0.157390026871" />
<sab name="c_H_in_H2O" />
</material>
<material id="9" name="Bottom nozzle region">
<density units="g/cm3" value="2.53" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-05" />
<nuclide name="B11" wo="0.000359854" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Cr52" wo="0.124142524198" />
<sab name="c_H_in_H2O" />
</material>
<material id="10" name="Top nozzle region">
<density units="g/cm3" value="1.746" />
<nuclide name="H1" wo="0.035887" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="0.000115699" />
<nuclide name="B11" wo="0.000527075" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Cr52" wo="0.107931450781" />
<sab name="c_H_in_H2O" />
</material>
<material id="11" name="Top of fuel assemblies">
<density units="g/cm3" value="3.044" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-05" />
<nuclide name="B11" wo="0.000239272" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<material id="12" name="Bottom of fuel assemblies">
<density units="g/cm3" value="1.762" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-05" />
<nuclide name="B11" wo="0.00043012" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<batches>10</batches>
<inactive>5</inactive>
<source strength="1.0">
<space type="box">
<parameters>-160 -160 -183 160 160 183</parameters>
</space>
</source>
<particles>1000</particles>
<batches>5</batches>
<inactive>0</inactive>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>
<mesh id="1">
<dimension>2 2 2</dimension>
<lower_left>-160.0 -160.0 -183.0</lower_left>
<upper_right>160.0 160.0 183.0</upper_right>
<dimension>2 2</dimension>
<lower_left>-10.0 -10.0</lower_left>
<upper_right>10.0 10.0</upper_right>
</mesh>
<filter id="2" type="material">
<bins>1 3</bins>
<bins>1 2</bins>
</filter>
<filter id="1" type="energy">
<bins>0.0 2.53e-07 0.001 1.0 20.0</bins>
<bins>0.0 10.0 20000000.0</bins>
</filter>
<filter id="3" type="distribcell">
<bins>60</bins>
</filter>
<filter id="4" type="mesh">
<filter id="3" type="mesh">
<bins>1</bins>
</filter>
<tally id="1" name="tally 1">
<filters>2 1 3</filters>
<filters>2 1</filters>
<nuclides>U234 U235</nuclides>
<scores>nu-fission total</scores>
</tally>
<tally id="2" name="tally 2">
<filters>1 4</filters>
<filters>1 3</filters>
<nuclides>U238 U235</nuclides>
<scores>total fission</scores>
</tally>

View file

@ -1,139 +1,49 @@
[[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
...
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]][[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
...
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]][[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
...
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]][[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
...
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]][[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
...
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]]
[2.87610e-07 1.60278e-13 2.54988e-04 1.42099e-10 2.33002e-07 1.83973e-07
2.06574e-04 1.63105e-04 7.77662e-03 4.33372e-09 4.02417e-03 2.24257e-09
6.30008e-03 4.97439e-03 3.26010e-03 2.57410e-03 2.52614e-07 1.57719e-13
2.23961e-04 1.39830e-10 2.43493e-07 1.93615e-07 2.15874e-04 1.71654e-04
6.83035e-03 4.26453e-09 3.53450e-03 2.20677e-09 6.58373e-03 5.23510e-03
3.40688e-03 2.70901e-03 2.72019e-07 1.63161e-13 2.41165e-04 1.44654e-10
2.44531e-07 1.94194e-07 2.16795e-04 1.72167e-04 7.35506e-03 4.41166e-09
3.80602e-03 2.28290e-09 6.61180e-03 5.25075e-03 3.42141e-03 2.71710e-03
2.41472e-07 1.50936e-13 2.14083e-04 1.33816e-10 2.24252e-07 1.77892e-07
1.98816e-04 1.57715e-04 6.52910e-03 4.08113e-09 3.37861e-03 2.11186e-09
6.06350e-03 4.80998e-03 3.13768e-03 2.48902e-03 2.48914e-03 4.48016e-05
1.13508e-02 2.04302e-04 1.19934e-04 2.60981e-05 5.46915e-04 1.19011e-04
2.77675e-02 4.99783e-04 4.93334e-02 8.87945e-04 1.33792e-03 2.91137e-04
2.37703e-03 5.17251e-04 2.49083e-03 4.43597e-05 1.13585e-02 2.02286e-04
1.21668e-04 2.66359e-05 5.54821e-04 1.21463e-04 2.77864e-02 4.94854e-04
4.93670e-02 8.79187e-04 1.35726e-03 2.97136e-04 2.41139e-03 5.27909e-04
2.28387e-03 4.25108e-05 1.04148e-02 1.93855e-04 1.16292e-04 2.67442e-05
5.30307e-04 1.21957e-04 2.54776e-02 4.74228e-04 4.52651e-02 8.42543e-04
1.29729e-03 2.98344e-04 2.30485e-03 5.30056e-04 2.25849e-03 4.37806e-05
1.02990e-02 1.99646e-04 1.16539e-04 2.71633e-05 5.31435e-04 1.23868e-04
2.51945e-02 4.88393e-04 4.47620e-02 8.67709e-04 1.30005e-03 3.03020e-04
2.30975e-03 5.38363e-04][2.87610e-07 1.60278e-13 2.54988e-04 1.42099e-10 2.33002e-07 1.83973e-07
2.06574e-04 1.63105e-04 7.77662e-03 4.33372e-09 4.02417e-03 2.24257e-09
6.30008e-03 4.97439e-03 3.26010e-03 2.57410e-03 2.52614e-07 1.57719e-13
2.23961e-04 1.39830e-10 2.43493e-07 1.93615e-07 2.15874e-04 1.71654e-04
6.83035e-03 4.26453e-09 3.53450e-03 2.20677e-09 6.58373e-03 5.23510e-03
3.40688e-03 2.70901e-03 2.72019e-07 1.63161e-13 2.41165e-04 1.44654e-10
2.44531e-07 1.94194e-07 2.16795e-04 1.72167e-04 7.35506e-03 4.41166e-09
3.80602e-03 2.28290e-09 6.61180e-03 5.25075e-03 3.42141e-03 2.71710e-03
2.41472e-07 1.50936e-13 2.14083e-04 1.33816e-10 2.24252e-07 1.77892e-07
1.98816e-04 1.57715e-04 6.52910e-03 4.08113e-09 3.37861e-03 2.11186e-09
6.06350e-03 4.80998e-03 3.13768e-03 2.48902e-03 2.48914e-03 4.48016e-05
1.13508e-02 2.04302e-04 1.19934e-04 2.60981e-05 5.46915e-04 1.19011e-04
2.77675e-02 4.99783e-04 4.93334e-02 8.87945e-04 1.33792e-03 2.91137e-04
2.37703e-03 5.17251e-04 2.49083e-03 4.43597e-05 1.13585e-02 2.02286e-04
1.21668e-04 2.66359e-05 5.54821e-04 1.21463e-04 2.77864e-02 4.94854e-04
4.93670e-02 8.79187e-04 1.35726e-03 2.97136e-04 2.41139e-03 5.27909e-04
2.28387e-03 4.25108e-05 1.04148e-02 1.93855e-04 1.16292e-04 2.67442e-05
5.30307e-04 1.21957e-04 2.54776e-02 4.74228e-04 4.52651e-02 8.42543e-04
1.29729e-03 2.98344e-04 2.30485e-03 5.30056e-04 2.25849e-03 4.37806e-05
1.02990e-02 1.99646e-04 1.16539e-04 2.71633e-05 5.31435e-04 1.23868e-04
2.51945e-02 4.88393e-04 4.47620e-02 8.67709e-04 1.30005e-03 3.03020e-04
2.30975e-03 5.38363e-04][0.0063 0.00497 0.00326 0.00257 0.00658 0.00524 0.00341 0.00271 0.00661
0.00525 0.00342 0.00272 0.00606 0.00481 0.00314 0.00249 0.00134 0.00029
0.00238 0.00052 0.00136 0.0003 0.00241 0.00053 0.0013 0.0003 0.0023
0.00053 0.0013 0.0003 0.00231 0.00054][0.00025 0.00021 0.00402 0.00326 0.00022 0.00022 0.00353 0.00341 0.00024
0.00022 0.00381 0.00342 0.00021 0.0002 0.00338 0.00314 0.01135 0.00055
0.04933 0.00238 0.01136 0.00055 0.04937 0.00241 0.01041 0.00053 0.04527
0.0023 0.0103 0.00053 0.04476 0.00231][0.00326 0.00341 0.00342 0.00314 0.00238 0.00241 0.0023 0.00231]

View file

@ -1,39 +1,61 @@
import hashlib
import numpy as np
import openmc
import pytest
from tests.testing_harness import PyAPITestHarness
@pytest.fixture
def model():
model = openmc.model.Model()
fuel = openmc.Material()
fuel.set_density('g/cm3', 10.0)
fuel.add_nuclide('U234', 1.0)
fuel.add_nuclide('U235', 4.0)
fuel.add_nuclide('U238', 95.0)
water = openmc.Material(name='light water')
water.add_nuclide('H1', 2.0)
water.add_nuclide('O16', 1.0)
water.set_density('g/cm3', 1.0)
water.add_s_alpha_beta('c_H_in_H2O')
model.materials.extend([fuel, water])
cyl1 = openmc.ZCylinder(r=5.0)
cyl2 = openmc.ZCylinder(r=10.0, boundary_type='vacuum')
cell1 = openmc.Cell(fill=fuel, region=-cyl1)
cell2 = openmc.Cell(fill=water, region=+cyl1 & -cyl2)
model.geometry = openmc.Geometry([cell1, cell2])
model.settings.batches = 5
model.settings.inactive = 0
model.settings.particles = 1000
mesh = openmc.RegularMesh()
mesh.dimension = (2, 2)
mesh.lower_left = (-10.0, -10.0)
mesh.upper_right = (10.0, 10.0)
energy_filter = openmc.EnergyFilter((0.0, 10.0, 20.0e6))
material_filter = openmc.MaterialFilter((fuel, water))
mesh_filter = openmc.MeshFilter(mesh)
tally = openmc.Tally(name='tally 1')
tally.filters = [material_filter, energy_filter]
tally.scores = ['nu-fission', 'total']
tally.nuclides = ['U234', 'U235']
model.tallies.append(tally)
tally = openmc.Tally(name='tally 2')
tally.filters = [energy_filter, mesh_filter]
tally.scores = ['total', 'fission']
tally.nuclides = ['U238', 'U235']
model.tallies.append(tally)
return model
class TallyArithmeticTestHarness(PyAPITestHarness):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Initialize Mesh
mesh = openmc.RegularMesh(mesh_id=1)
mesh.dimension = [2, 2, 2]
mesh.lower_left = [-160.0, -160.0, -183.0]
mesh.upper_right = [160.0, 160.0, 183.0]
# Initialize the filters
energy_filter = openmc.EnergyFilter((0.0, 0.253e-6, 1.0e-3, 1.0, 20.0))
material_filter = openmc.MaterialFilter((1, 3))
distrib_filter = openmc.DistribcellFilter(60)
mesh_filter = openmc.MeshFilter(mesh)
# Initialized the tallies
tally = openmc.Tally(name='tally 1')
tally.filters = [material_filter, energy_filter, distrib_filter]
tally.scores = ['nu-fission', 'total']
tally.nuclides = ['U234', 'U235']
self._model.tallies.append(tally)
tally = openmc.Tally(name='tally 2')
tally.filters = [energy_filter, mesh_filter]
tally.scores = ['total', 'fission']
tally.nuclides = ['U238', 'U235']
self._model.tallies.append(tally)
def _get_results(self, hash_output=False):
"""Digest info in the statepoint and return as a string."""
@ -45,27 +67,29 @@ class TallyArithmeticTestHarness(PyAPITestHarness):
tally_2 = sp.get_tally(name='tally 2')
# Perform all the tally arithmetic operations and output results
outstr = ''
tally_3 = tally_1 * tally_2
outstr += str(tally_3.mean)
output = []
with np.printoptions(precision=5, threshold=np.inf):
mean = (tally_1 * tally_2).mean
output.append(str(mean[np.nonzero(mean)]))
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'tensor',
'tensor')
outstr += str(tally_3.mean)
mean = tally_1.hybrid_product(
tally_2, '*', 'entrywise', 'tensor', 'tensor').mean
output.append(str(mean[np.nonzero(mean)]))
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'entrywise',
'tensor')
outstr += str(tally_3.mean)
mean = tally_1.hybrid_product(
tally_2, '*', 'entrywise', 'entrywise', 'tensor').mean
output.append(str(mean[np.nonzero(mean)]))
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'tensor',
'entrywise')
outstr += str(tally_3.mean)
mean = tally_1.hybrid_product(
tally_2, '*', 'entrywise', 'tensor', 'entrywise').mean
output.append(str(mean[np.nonzero(mean)]))
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'entrywise',
'entrywise')
outstr += str(tally_3.mean)
mean = tally_1.hybrid_product(
tally_2, '*', 'entrywise', 'entrywise', 'entrywise').mean
output.append(str(mean[np.nonzero(mean)]))
# Hash the results if necessary
outstr = ''.join(output)
if hash_output:
sha512 = hashlib.sha512()
sha512.update(outstr.encode('utf-8'))
@ -74,6 +98,6 @@ class TallyArithmeticTestHarness(PyAPITestHarness):
return outstr
def test_tally_arithmetic():
harness = TallyArithmeticTestHarness('statepoint.10.h5')
def test_tally_arithmetic(model):
harness = TallyArithmeticTestHarness('statepoint.5.h5', model)
harness.main()

View file

@ -1,181 +1,9 @@
<?xml version="1.0"?>
<geometry>
<surface id="1" type="z-cylinder" coeffs="0. 0. 0.41" />
<surface id="2" type="z-cylinder" coeffs="0. 0. 0.475" />
<surface id="3" type="z-cylinder" coeffs="0. 0. 0.56" />
<surface id="4" type="z-cylinder" coeffs="0. 0. 0.62" />
<surface id="5" type="z-cylinder" coeffs="0. 0. 187.6" />
<surface id="6" type="z-cylinder" coeffs="0. 0. 209.0" />
<surface id="7" type="z-cylinder" coeffs="0. 0. 229.0" />
<surface id="8" type="z-cylinder" coeffs="0. 0. 249.0" boundary="vacuum" />
<surface id="31" type="z-plane" coeffs="-229.0" boundary="vacuum" />
<surface id="32" type="z-plane" coeffs="-199.0" />
<surface id="33" type="z-plane" coeffs="-193.0" />
<surface id="34" type="z-plane" coeffs="-183.0" />
<surface id="35" type="z-plane" coeffs="0.0" />
<surface id="36" type="z-plane" coeffs="183.0" />
<surface id="37" type="z-plane" coeffs="203.0" />
<surface id="38" type="z-plane" coeffs="215.0" />
<surface id="39" type="z-plane" coeffs="223.0" boundary="vacuum" />
<!-- All geometry on base universe -->
<cell id="1" fill="200" region=" -6 34 -35" /> <!-- Lower core -->
<cell id="2" fill="201" region=" -6 35 -36" /> <!-- Upper core -->
<cell id="3" material="8" region=" -7 31 -32" /> <!-- Lower core plate region -->
<cell id="4" material="9" region=" -5 32 -33" /> <!-- Bottom nozzle region -->
<cell id="5" material="12" region=" -5 33 -34" /> <!-- Bottom FA region -->
<cell id="6" material="11" region=" -5 36 -37" /> <!-- Top FA region -->
<cell id="7" material="10" region=" -5 37 -38" /> <!-- Top nozzle region -->
<cell id="8" material="7" region=" -7 38 -39" /> <!-- Upper plate region -->
<cell id="9" material="4" region="6 -7 32 -38" /> <!-- Downcomer -->
<cell id="10" material="5" region="7 -8 31 -39" /> <!-- RPV -->
<cell id="11" material="6" region="5 -6 32 -34" /> <!-- Bottom of radial reflector -->
<cell id="12" material="7" region="5 -6 36 -38" /> <!-- Top of radial reflector -->
<!-- Fuel pin, cladding, cold water -->
<cell id="21" universe="1" material="1" region="-1" />
<cell id="22" universe="1" material="2" region="1 -2" />
<cell id="23" universe="1" material="3" region="2" />
<!-- Instrumentation guide tube -->
<cell id="24" universe="2" material="3" region="-3" />
<cell id="25" universe="2" material="2" region="3 -4" />
<cell id="26" universe="2" material="3" region="4" />
<!-- Fuel pin, cladding, hot water -->
<cell id="27" universe="3" material="1" region="-1" />
<cell id="28" universe="3" material="2" region="1 -2" />
<cell id="29" universe="3" material="4" region="2" />
<!-- Instrumentation guide tube -->
<cell id="30" universe="4" material="4" region="-3" />
<cell id="31" universe="4" material="2" region="3 -4" />
<cell id="32" universe="4" material="4" region="4" />
<!-- cell for water assembly (cold) -->
<cell id="50" universe="5" material="4" region="34 -35" />
<!-- containing cell for fuel assembly -->
<cell id="60" universe="6" fill="100" region="34 -35" />
<!-- cell for water assembly (hot) -->
<cell id="70" universe="7" material="3" region="35 -36" />
<!-- containing cell for fuel assembly -->
<cell id="80" universe="8" fill="101" region="35 -36" />
<!-- Fuel Assembly (Lower Half) -->
<lattice id="100">
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<pitch>1.26 1.26</pitch>
<universes>
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 2 1 1 2 1 1 2 1 1 2 1 1 2 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 2 1 1 2 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
</universes>
</lattice>
<!-- Fuel Assembly (Upper Half) -->
<lattice id="101">
<dimension>17 17</dimension>
<lower_left>-10.71 -10.71</lower_left>
<pitch>1.26 1.26</pitch>
<universes>
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 4 3 3 4 3 3 4 3 3 4 3 3 4 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 4 3 3 3 3 3 3 3 3 3 4 3 3 3
3 3 3 3 3 4 3 3 4 3 3 4 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
</universes>
</lattice>
<!-- Core Lattice (Lower Half) -->
<lattice id="200">
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<pitch>21.42 21.42</pitch>
<universes>
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5
5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5
5 5 5 5 5 6 6 6 6 6 6 6 6 6 6 6 5 5 5 5 5
5 5 5 5 5 5 5 6 6 6 6 6 6 6 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5
</universes>
</lattice>
<!-- Core Lattice (Upper Half) -->
<lattice id="201">
<dimension>21 21</dimension>
<lower_left>-224.91 -224.91</lower_left>
<pitch>21.42 21.42</pitch>
<universes>
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7
7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7
7 7 7 7 7 8 8 8 8 8 8 8 8 8 8 8 7 7 7 7 7
7 7 7 7 7 7 7 8 8 8 8 8 8 8 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7
</universes>
</lattice>
<surface id="1" type="z-cylinder" coeffs="0. 0. 5.0" />
<surface id="2" type="z-cylinder" coeffs="0. 0. 10.0" />
<surface id="3" type="z-cylinder" coeffs="0. 0. 15.0" boundary="vacuum" />
<cell id="1" material="1" region="-1" />
<cell id="2" material="2" region="1 -2" />
<cell id="3" material="3" region="2 -3" />
</geometry>

View file

@ -1,270 +1,15 @@
<?xml version="1.0"?>
<materials>
<!-- Fuel composition -->
<material id="1">
<density value="10.062" units="g/cm3" />
<nuclide name="U234" ao="4.9476e-6" />
<nuclide name="U235" ao="4.8218e-4" />
<nuclide name="U236" ao="9.0402e-5" />
<nuclide name="U238" ao="2.1504e-2" />
<nuclide name="Np237" ao="7.3733e-6" />
<nuclide name="Pu238" ao="1.5148e-6" />
<nuclide name="Pu239" ao="1.3955e-4" />
<nuclide name="Pu240" ao="3.4405e-5" />
<nuclide name="Pu241" ao="2.1439e-5" />
<nuclide name="Pu242" ao="3.7422e-6" />
<nuclide name="Am241" ao="4.5041e-7" />
<nuclide name="Am242_m1" ao="9.2301e-9" />
<nuclide name="Am243" ao="4.7878e-7" />
<nuclide name="Cm242" ao="1.0485e-7" />
<nuclide name="Cm243" ao="1.4268e-9" />
<nuclide name="Cm244" ao="8.8756e-8" />
<nuclide name="Cm245" ao="3.5285e-9" />
<nuclide name="Mo95" ao="2.6497e-5" />
<nuclide name="Tc99" ao="3.2772e-5" />
<nuclide name="Ru101" ao="3.0742e-5" />
<nuclide name="Ru103" ao="2.3505e-6" />
<nuclide name="Ag109" ao="2.0009e-6" />
<nuclide name="Xe135" ao="1.0801e-8" />
<nuclide name="Cs133" ao="3.4612e-5" />
<nuclide name="Nd143" ao="2.6078e-5" />
<nuclide name="Nd145" ao="1.9898e-5" />
<nuclide name="Sm147" ao="1.6128e-6" />
<nuclide name="Sm149" ao="1.1627e-7" />
<nuclide name="Sm150" ao="7.1727e-6" />
<nuclide name="Sm151" ao="5.4947e-7" />
<nuclide name="Sm152" ao="3.0221e-6" />
<nuclide name="Eu153" ao="2.6209e-6" />
<nuclide name="Gd155" ao="1.5369e-9" />
<nuclide name="O16" ao="4.5737e-2" />
<density value="10.0" units="g/cm3" />
<nuclide name="U235" ao="1.0" />
</material>
<!-- Cladding composition -->
<material id="2">
<density value="5.77" units="g/cm3" />
<nuclide name="Zr90" ao="0.5145" />
<nuclide name="Zr91" ao="0.1122" />
<nuclide name="Zr92" ao="0.1715" />
<nuclide name="Zr94" ao="0.1738" />
<nuclide name="Zr96" ao="0.0280" />
<density value="0.01" units="g/cm3" />
<nuclide name="He4" ao="1.0" />
</material>
<!-- Cold borated water -->
<material id="3">
<density value="0.07416" units="atom/b-cm" />
<nuclide name="H1" ao="2.0" />
<nuclide name="O16" ao="1.0" />
<nuclide name="B10" ao="6.490e-4" />
<nuclide name="B11" ao="2.689e-3" />
<sab name="c_H_in_H2O" />
<density value="5.77" units="g/cm3" />
<nuclide name="Zr90" ao="1.0" />
</material>
<!-- Hot borated water -->
<material id="4">
<density value="0.06614" units="atom/b-cm" />
<nuclide name="H1" ao="2.0" />
<nuclide name="O16" ao="1.0" />
<nuclide name="B10" ao="6.490e-4" />
<nuclide name="B11" ao="2.689e-3" />
<sab name="c_H_in_H2O" />
</material>
<!-- RPV Composition -->
<material id="5">
<density value="7.9" units="g/cm3" />
<nuclide name="Fe54" wo="0.05437098" />
<nuclide name="Fe56" wo="0.88500663" />
<nuclide name="Fe57" wo="0.0208008" />
<nuclide name="Fe58" wo="0.00282159" />
<nuclide name="Ni58" wo="0.0067198" />
<nuclide name="Ni60" wo="0.0026776" />
<nuclide name="Ni61" wo="0.0001183" />
<nuclide name="Ni62" wo="0.0003835" />
<nuclide name="Ni64" wo="0.0001008" />
<nuclide name="Mn55" wo="0.01" />
<nuclide name="Mo92" wo="0.000849" />
<nuclide name="Mo94" wo="0.0005418" />
<nuclide name="Mo95" wo="0.0009438" />
<nuclide name="Mo96" wo="0.0010002" />
<nuclide name="Mo97" wo="0.0005796" />
<nuclide name="Mo98" wo="0.0014814" />
<nuclide name="Mo100" wo="0.0006042" />
<nuclide name="Si28" wo="0.00367464" />
<nuclide name="Si29" wo="0.00019336" />
<nuclide name="Si30" wo="0.000132" />
<nuclide name="Cr50" wo="0.00010435" />
<nuclide name="Cr52" wo="0.002092475" />
<nuclide name="Cr53" wo="0.00024185" />
<nuclide name="Cr54" wo="6.1325e-05" />
<nuclide name="C0" wo="0.0025" />
<nuclide name="Cu63" wo="0.0013696" />
<nuclide name="Cu65" wo="0.0006304" />
</material>
<!-- Lower radial reflector -->
<material id="6">
<density value="4.32" units="g/cm3" />
<nuclide name="H1" wo="0.0095661" />
<nuclide name="O16" wo="0.0759107" />
<nuclide name="B10" wo="3.08409e-5" />
<nuclide name="B11" wo="1.40499e-4" />
<nuclide name="Fe54" wo="0.035620772088" />
<nuclide name="Fe56" wo="0.579805982228" />
<nuclide name="Fe57" wo="0.01362750048" />
<nuclide name="Fe58" wo="0.001848545204" />
<nuclide name="Ni58" wo="0.055298376566" />
<nuclide name="Ni60" wo="0.022034425592" />
<nuclide name="Ni61" wo="0.000973510811" />
<nuclide name="Ni62" wo="0.003155886695" />
<nuclide name="Ni64" wo="0.000829500336" />
<nuclide name="Mn55" wo="0.0182870" />
<nuclide name="Si28" wo="0.00839976771" />
<nuclide name="Si29" wo="0.00044199679" />
<nuclide name="Si30" wo="0.0003017355" />
<nuclide name="Cr50" wo="0.007251360806" />
<nuclide name="Cr52" wo="0.145407678031" />
<nuclide name="Cr53" wo="0.016806340306" />
<nuclide name="Cr54" wo="0.004261520857" />
<sab name="c_H_in_H2O" />
</material>
<!-- Upper radial reflector / Top plate region -->
<material id="7">
<density value="4.28" units="g/cm3" />
<nuclide name="H1" wo="0.0086117" />
<nuclide name="O16" wo="0.0683369" />
<nuclide name="B10" wo="2.77638e-5" />
<nuclide name="B11" wo="1.26481e-4" />
<nuclide name="Fe54" wo="0.035953677186" />
<nuclide name="Fe56" wo="0.585224740891" />
<nuclide name="Fe57" wo="0.01375486056" />
<nuclide name="Fe58" wo="0.001865821363" />
<nuclide name="Ni58" wo="0.055815129186" />
<nuclide name="Ni60" wo="0.022240333032" />
<nuclide name="Ni61" wo="0.000982608081" />
<nuclide name="Ni62" wo="0.003185377845" />
<nuclide name="Ni64" wo="0.000837251856" />
<nuclide name="Mn55" wo="0.0184579" />
<nuclide name="Si28" wo="0.00847831314" />
<nuclide name="Si29" wo="0.00044612986" />
<nuclide name="Si30" wo="0.000304557" />
<nuclide name="Cr50" wo="0.00731912987" />
<nuclide name="Cr52" wo="0.146766614995" />
<nuclide name="Cr53" wo="0.01696340737" />
<nuclide name="Cr54" wo="0.004301347765" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom plate region -->
<material id="8">
<density value="7.184" units="g/cm3" />
<nuclide name="H1" wo="0.0011505" />
<nuclide name="O16" wo="0.0091296" />
<nuclide name="B10" wo="3.70915e-6" />
<nuclide name="B11" wo="1.68974e-5" />
<nuclide name="Fe54" wo="0.03855611055" />
<nuclide name="Fe56" wo="0.627585036425" />
<nuclide name="Fe57" wo="0.014750478" />
<nuclide name="Fe58" wo="0.002000875025" />
<nuclide name="Ni58" wo="0.059855207342" />
<nuclide name="Ni60" wo="0.023850159704" />
<nuclide name="Ni61" wo="0.001053732407" />
<nuclide name="Ni62" wo="0.003415945715" />
<nuclide name="Ni64" wo="0.000897854832" />
<nuclide name="Mn55" wo="0.0197940" />
<nuclide name="Si28" wo="0.00909197802" />
<nuclide name="Si29" wo="0.00047842098" />
<nuclide name="Si30" wo="0.000326601" />
<nuclide name="Cr50" wo="0.007848910646" />
<nuclide name="Cr52" wo="0.157390026871" />
<nuclide name="Cr53" wo="0.018191270146" />
<nuclide name="Cr54" wo="0.004612692337" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom nozzle region -->
<material id="9">
<density value="2.53" units="g/cm3" />
<nuclide name="H1" wo="0.0245014" />
<nuclide name="O16" wo="0.1944274" />
<nuclide name="B10" wo="7.89917e-5" />
<nuclide name="B11" wo="3.59854e-4" />
<nuclide name="Fe54" wo="0.030411411144" />
<nuclide name="Fe56" wo="0.495012237964" />
<nuclide name="Fe57" wo="0.01163454624" />
<nuclide name="Fe58" wo="0.001578204652" />
<nuclide name="Ni58" wo="0.047211231662" />
<nuclide name="Ni60" wo="0.018811987544" />
<nuclide name="Ni61" wo="0.000831139127" />
<nuclide name="Ni62" wo="0.002694352115" />
<nuclide name="Ni64" wo="0.000708189552" />
<nuclide name="Mn55" wo="0.0156126" />
<nuclide name="Si28" wo="0.007171335558" />
<nuclide name="Si29" wo="0.000377356542" />
<nuclide name="Si30" wo="0.0002576079" />
<nuclide name="Cr50" wo="0.006190885148" />
<nuclide name="Cr52" wo="0.124142524198" />
<nuclide name="Cr53" wo="0.014348496148" />
<nuclide name="Cr54" wo="0.003638294506" />
<sab name="c_H_in_H2O" />
</material>
<!-- Top nozzle region -->
<material id="10">
<density value="1.746" units="g/cm3" />
<nuclide name="H1" wo="0.0358870" />
<nuclide name="O16" wo="0.2847761" />
<nuclide name="B10" wo="1.15699e-4" />
<nuclide name="B11" wo="5.27075e-4" />
<nuclide name="Fe54" wo="0.02644016154" />
<nuclide name="Fe56" wo="0.43037146399" />
<nuclide name="Fe57" wo="0.0101152584" />
<nuclide name="Fe58" wo="0.00137211607" />
<nuclide name="Ni58" wo="0.04104621835" />
<nuclide name="Ni60" wo="0.0163554502" />
<nuclide name="Ni61" wo="0.000722605975" />
<nuclide name="Ni62" wo="0.002342513875" />
<nuclide name="Ni64" wo="0.0006157116" />
<nuclide name="Mn55" wo="0.0135739" />
<nuclide name="Si28" wo="0.006234853554" />
<nuclide name="Si29" wo="0.000328078746" />
<nuclide name="Si30" wo="0.0002239677" />
<nuclide name="Cr50" wo="0.005382452306" />
<nuclide name="Cr52" wo="0.107931450781" />
<nuclide name="Cr53" wo="0.012474806806" />
<nuclide name="Cr54" wo="0.003163190107" />
<sab name="c_H_in_H2O" />
</material>
<!-- Top of Fuel Assemblies -->
<material id="11">
<density value="3.044" units="g/cm3" />
<nuclide name="H1" wo="0.0162913" />
<nuclide name="O16" wo="0.1292776" />
<nuclide name="B10" wo="5.25228e-5" />
<nuclide name="B11" wo="2.39272e-4" />
<nuclide name="Zr90" wo="0.43313403903" />
<nuclide name="Zr91" wo="0.09549277374" />
<nuclide name="Zr92" wo="0.14759527104" />
<nuclide name="Zr94" wo="0.15280552077" />
<nuclide name="Zr96" wo="0.02511169542" />
<sab name="c_H_in_H2O" />
</material>
<!-- Bottom of Fuel Assemblies -->
<material id="12">
<density value="1.762" units="g/cm3" />
<nuclide name="H1" wo="0.0292856" />
<nuclide name="O16" wo="0.2323919" />
<nuclide name="B10" wo="9.44159e-5" />
<nuclide name="B11" wo="4.30120e-4" />
<nuclide name="Zr90" wo="0.3741373658" />
<nuclide name="Zr91" wo="0.0824858164" />
<nuclide name="Zr92" wo="0.1274914944" />
<nuclide name="Zr94" wo="0.1319920622" />
<nuclide name="Zr96" wo="0.0216912612" />
<sab name="c_H_in_H2O" />
</material>
</materials>

View file

@ -1,11 +1,11 @@
k-combined:
9.581522E-01 4.261828E-02
6.161485E-01 2.229530E-02
tally 1:
1.529084E+01
4.769011E+01
7.433231E+00
1.122269E+01
tally 2:
3.198905E+00
2.114128E+00
2.545046E-01
1.340485E-02
tally 3:
4.510603E+01
4.183089E+02
1.136947E+01
2.646408E+01

View file

@ -1,18 +1,12 @@
<?xml version="1.0"?>
<settings>
<run_mode>eigenvalue</run_mode>
<batches>10</batches>
<inactive>5</inactive>
<particles>100</particles>
<source>
<space type="box">
<parameters>
-160 -160 -183
160 160 183
</parameters>
<space type="point">
<parameters>0.0 0.0 0.0</parameters>
</space>
</source>
</settings>

View file

@ -5,17 +5,17 @@
<filter id="1">
<type>cell</type>
<bins>21</bins>
<bins>1</bins>
</filter>
<filter id="2">
<type>cell</type>
<bins>22</bins>
<bins>2</bins>
</filter>
<filter id="3">
<type>cell</type>
<bins>23</bins>
<bins>3</bins>
</filter>
<tally id="1">

View file

@ -1,40 +0,0 @@
<?xml version="1.0"?>
<geometry>
<!-- pu-met-fast-019 -->
<surface id="1" type="sphere" coeffs="0. 0. 0. 1.4" />
<surface id="3" type="sphere" coeffs="0. 0. 0. 5.35" />
<surface id="4" type="sphere" coeffs="0. 0. 1.05 5.35" />
<surface id="5" type="z-cylinder" coeffs="0. 0. 5.50" />
<surface id="6" type="z-cylinder" coeffs="0. 0. 1.1" />
<surface id="7" type="sphere" coeffs="0. 0. 0. 11." />
<surface id="8" type="sphere" coeffs="0. 0. 1.05 11." />
<surface id="9" type="sphere" coeffs="0. 0. 0. 11.15" />
<surface id="10" type="z-plane" coeffs="0." />
<surface id="11" type="z-plane" coeffs="1." />
<surface id="12" type="z-plane" coeffs="1.20" />
<surface id="13" type="z-cylinder" coeffs="0. 0. 9.7" />
<surface id="14" type="z-cylinder" coeffs="0. 0. 2.5" />
<surface id="15" type="z-cylinder" coeffs="0. 0. 14." boundary="vacuum" />
<surface id="16" type="z-plane" coeffs="-0.15" />
<surface id="17" type="z-plane" coeffs="-14.15" boundary="vacuum" />
<surface id="18" type="z-plane" coeffs="14." boundary="vacuum" />
<cell id="1" material="void" region="-1" /> <!-- cavity -->
<cell id="2" material="1" region=" 1 -3" /> <!-- Pu Core -->
<cell id="3" material="void" region=" 3 -4 12" />
<cell id="4" material="void" region=" 3 -5 11 -12" />
<cell id="5" material="2" region=" 3 -7 -16" /> <!-- Bottom Reflector -->
<cell id="6" material="2" region=" 4 6 -8 12" /> <!-- top reflector -->
<cell id="7" material="void" region=" 3 10 -11 -15" />
<cell id="8" material="3" region=" 5 11 -12 -15" /> <!-- diaphragm -->
<cell id="9" material="void" region=" 7 -10 13 -15 17" />
<cell id="10" material="void" region=" 8 12 -15 -18" />
<cell id="11" material="4" region=" 7 -9 -13 -10" /> <!-- copper cup -->
<cell id="12" material="3" region=" 9 -10 -14 17" /> <!-- shaft -->
<cell id="13" material="void" region=" 9 -10 -13 14 17" />
<cell id="14" material="void" region=" 3 -7 -10 16" />
<cell id="15" material="void" region=" 4 -6 -8 12" /> <!-- polar hole in Top Reflector -->
</geometry>

View file

@ -0,0 +1,132 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell id="1" material="1" region="-1" universe="1" />
<cell id="2" material="void" region="1 -2" universe="1" />
<cell id="3" material="1" region="2 -3" universe="1" />
<cell id="4" material="void" region="3 -4" universe="1" />
<cell id="5" material="1" region="4 -5" universe="1" />
<cell id="6" material="void" region="5 -6" universe="1" />
<cell id="7" material="1" region="6 -7" universe="1" />
<cell id="8" material="void" region="7 -8" universe="1" />
<cell id="9" material="1" region="8 -9" universe="1" />
<cell id="10" material="void" region="9 -10" universe="1" />
<cell id="11" material="1" region="10 -11" universe="1" />
<cell id="12" material="void" region="11 -12" universe="1" />
<cell id="13" material="1" region="12 -13" universe="1" />
<cell id="14" material="void" region="13 -14" universe="1" />
<cell id="15" material="1" region="14 -15" universe="1" />
<cell id="16" material="void" region="15 -16" universe="1" />
<cell id="17" material="1" region="16 -17" universe="1" />
<cell id="18" material="void" region="17 -18" universe="1" />
<cell id="19" material="1" region="18 -19" universe="1" />
<cell id="20" material="void" region="19 -20" universe="1" />
<cell id="21" material="1" region="20 -21" universe="1" />
<cell id="22" material="void" region="21 -22" universe="1" />
<cell id="23" material="1" region="22 -23" universe="1" />
<cell id="24" material="void" region="23 -24" universe="1" />
<cell id="25" material="1" region="24 -25" universe="1" />
<cell id="26" material="void" region="25 -26" universe="1" />
<cell id="27" material="1" region="26 -27" universe="1" />
<cell id="28" material="void" region="27 -28" universe="1" />
<cell id="29" material="1" region="28 -29" universe="1" />
<cell id="30" material="void" region="29 -30" universe="1" />
<cell id="31" material="1" region="30 -31" universe="1" />
<cell id="32" material="void" region="31 -32" universe="1" />
<cell id="33" material="1" region="32 -33" universe="1" />
<cell id="34" material="void" region="33 -34" universe="1" />
<cell id="35" material="1" region="34 -35" universe="1" />
<cell id="36" material="void" region="35 -36" universe="1" />
<cell id="37" material="1" region="36 -37" universe="1" />
<cell id="38" material="void" region="37 -38" universe="1" />
<cell id="39" material="1" region="38 -39" universe="1" />
<cell id="40" material="void" region="39 -40" universe="1" />
<cell id="41" material="1" region="40 -41" universe="1" />
<cell id="42" material="void" region="41 -42" universe="1" />
<cell id="43" material="1" region="42 -43" universe="1" />
<cell id="44" material="void" region="43 -44" universe="1" />
<cell id="45" material="1" region="44 -45" universe="1" />
<cell id="46" material="void" region="45 -46" universe="1" />
<cell id="47" material="1" region="46 -47" universe="1" />
<cell id="48" material="void" region="47 -48" universe="1" />
<cell id="49" material="1" region="48 -49" universe="1" />
<cell id="50" material="void" region="49 -50" universe="1" />
<cell id="51" material="1" region="50" universe="1" />
<surface coeffs="0.0 0.0 0.0 1.0" id="1" type="sphere" />
<surface coeffs="0.0 0.0 0.0 3.020408163265306" id="2" type="sphere" />
<surface coeffs="0.0 0.0 0.0 5.040816326530612" id="3" type="sphere" />
<surface coeffs="0.0 0.0 0.0 7.061224489795918" id="4" type="sphere" />
<surface coeffs="0.0 0.0 0.0 9.081632653061224" id="5" type="sphere" />
<surface coeffs="0.0 0.0 0.0 11.102040816326529" id="6" type="sphere" />
<surface coeffs="0.0 0.0 0.0 13.122448979591836" id="7" type="sphere" />
<surface coeffs="0.0 0.0 0.0 15.142857142857142" id="8" type="sphere" />
<surface coeffs="0.0 0.0 0.0 17.163265306122447" id="9" type="sphere" />
<surface coeffs="0.0 0.0 0.0 19.183673469387752" id="10" type="sphere" />
<surface coeffs="0.0 0.0 0.0 21.204081632653057" id="11" type="sphere" />
<surface coeffs="0.0 0.0 0.0 23.224489795918366" id="12" type="sphere" />
<surface coeffs="0.0 0.0 0.0 25.24489795918367" id="13" type="sphere" />
<surface coeffs="0.0 0.0 0.0 27.265306122448976" id="14" type="sphere" />
<surface coeffs="0.0 0.0 0.0 29.285714285714285" id="15" type="sphere" />
<surface coeffs="0.0 0.0 0.0 31.30612244897959" id="16" type="sphere" />
<surface coeffs="0.0 0.0 0.0 33.326530612244895" id="17" type="sphere" />
<surface coeffs="0.0 0.0 0.0 35.3469387755102" id="18" type="sphere" />
<surface coeffs="0.0 0.0 0.0 37.367346938775505" id="19" type="sphere" />
<surface coeffs="0.0 0.0 0.0 39.38775510204081" id="20" type="sphere" />
<surface coeffs="0.0 0.0 0.0 41.408163265306115" id="21" type="sphere" />
<surface coeffs="0.0 0.0 0.0 43.42857142857142" id="22" type="sphere" />
<surface coeffs="0.0 0.0 0.0 45.44897959183673" id="23" type="sphere" />
<surface coeffs="0.0 0.0 0.0 47.469387755102034" id="24" type="sphere" />
<surface coeffs="0.0 0.0 0.0 49.48979591836734" id="25" type="sphere" />
<surface coeffs="0.0 0.0 0.0 51.51020408163265" id="26" type="sphere" />
<surface coeffs="0.0 0.0 0.0 53.53061224489795" id="27" type="sphere" />
<surface coeffs="0.0 0.0 0.0 55.55102040816326" id="28" type="sphere" />
<surface coeffs="0.0 0.0 0.0 57.57142857142857" id="29" type="sphere" />
<surface coeffs="0.0 0.0 0.0 59.59183673469387" id="30" type="sphere" />
<surface coeffs="0.0 0.0 0.0 61.61224489795918" id="31" type="sphere" />
<surface coeffs="0.0 0.0 0.0 63.63265306122448" id="32" type="sphere" />
<surface coeffs="0.0 0.0 0.0 65.65306122448979" id="33" type="sphere" />
<surface coeffs="0.0 0.0 0.0 67.67346938775509" id="34" type="sphere" />
<surface coeffs="0.0 0.0 0.0 69.6938775510204" id="35" type="sphere" />
<surface coeffs="0.0 0.0 0.0 71.71428571428571" id="36" type="sphere" />
<surface coeffs="0.0 0.0 0.0 73.73469387755101" id="37" type="sphere" />
<surface coeffs="0.0 0.0 0.0 75.75510204081633" id="38" type="sphere" />
<surface coeffs="0.0 0.0 0.0 77.77551020408163" id="39" type="sphere" />
<surface coeffs="0.0 0.0 0.0 79.79591836734693" id="40" type="sphere" />
<surface coeffs="0.0 0.0 0.0 81.81632653061223" id="41" type="sphere" />
<surface coeffs="0.0 0.0 0.0 83.83673469387755" id="42" type="sphere" />
<surface coeffs="0.0 0.0 0.0 85.85714285714285" id="43" type="sphere" />
<surface coeffs="0.0 0.0 0.0 87.87755102040815" id="44" type="sphere" />
<surface coeffs="0.0 0.0 0.0 89.89795918367346" id="45" type="sphere" />
<surface coeffs="0.0 0.0 0.0 91.91836734693877" id="46" type="sphere" />
<surface coeffs="0.0 0.0 0.0 93.93877551020407" id="47" type="sphere" />
<surface coeffs="0.0 0.0 0.0 95.95918367346938" id="48" type="sphere" />
<surface coeffs="0.0 0.0 0.0 97.97959183673468" id="49" type="sphere" />
<surface boundary="vacuum" coeffs="0.0 0.0 0.0 100.0" id="50" type="sphere" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material id="1">
<density units="g/cm3" value="7.14" />
<nuclide ao="1.0" name="Zn64" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>fixed source</run_mode>
<particles>1000</particles>
<batches>3</batches>
<source strength="1.0">
<space type="point">
<parameters>0.0 0.0 0.0</parameters>
</space>
</source>
</settings>
<?xml version='1.0' encoding='utf-8'?>
<tallies>
<filter id="1" type="cell">
<bins>1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51</bins>
</filter>
<tally id="1">
<filters>1</filters>
<scores>total</scores>
</tally>
</tallies>

View file

@ -1,61 +0,0 @@
<?xml version="1.0"?>
<materials>
<!-- pu-met-fast-019 -->
<!-- Plutonium -->
<material id="1">
<density value="15.4757" units="g/cm3" />
<nuclide name="Pu239" ao="3.3930e-02" />
<nuclide name="Pu240" ao="3.5043e-03" />
<nuclide name="Pu241" ao="3.9189e-04" />
<nuclide name="Ga69" ao="1.3287e-03" />
<nuclide name="Ga71" ao="8.8181e-04" />
<nuclide name="Ni58" ao="9.6649e-04" />
<nuclide name="Ni60" ao="3.7229e-04" />
<nuclide name="Ni61" ao="1.6183e-05" />
<nuclide name="Ni62" ao="5.1599e-05" />
<nuclide name="Ni64" ao="1.3141e-05" />
<nuclide name="C0" ao="3.0246e-03" />
<!-- <nuclide name="W180" ao="8.8920e-08" /> -->
<nuclide name="W182" ao="1.9725e-05" />
<nuclide name="W183" ao="1.0604e-05" />
<nuclide name="W184" ao="2.2704e-05" />
<nuclide name="W186" ao="2.1067e-05" />
<nuclide name="Fe54" ao="1.9011e-05" />
<nuclide name="Fe56" ao="2.9843e-04" />
<nuclide name="Fe57" ao="6.8920e-06" />
<nuclide name="Fe58" ao="9.1720e-07" />
</material>
<!-- Reflector -->
<material id="2">
<density value="1.8169" units="g/cm3" />
<nuclide name="Be9" ao="1.2081e-01" />
<nuclide name="O16" ao="8.2033e-05" />
<nuclide name="O17" ao="3.1184e-08" />
<nuclide name="C0" ao="1.0020e-04" />
<nuclide name="Fe54" ao="2.9774e-06" />
<nuclide name="Fe56" ao="4.6739e-05" />
<nuclide name="Fe57" ao="1.0794e-06" />
<nuclide name="Fe58" ao="1.4365e-07" />
<sab name="c_Be" />
</material>
<!-- Steel Diaphragm and Steel Shaft -->
<material id="3">
<density value="7.5278" units="g/cm3" />
<nuclide name="Fe54" ao="4.7446e-03" />
<nuclide name="Fe56" ao="7.4480e-02" />
<nuclide name="Fe57" ao="1.7201e-03" />
<nuclide name="Fe58" ao="2.2891e-04" />
</material>
<!-- Copper Cup -->
<material id="4">
<density value="8.6913" units="g/cm3" />
<nuclide name="Cu63" ao="5.6972e-02" />
<nuclide name="Cu65" ao="2.5393e-02" />
</material>
</materials>

View file

@ -1,2 +1,103 @@
k-combined:
9.612556E-01 1.990135E-02
tally 1:
8.636087E-01
2.486134E-01
0.000000E+00
0.000000E+00
2.848447E+00
2.704761E+00
0.000000E+00
0.000000E+00
3.944691E+00
5.195294E+00
0.000000E+00
0.000000E+00
4.822264E+00
7.764351E+00
0.000000E+00
0.000000E+00
5.295627E+00
9.359046E+00
0.000000E+00
0.000000E+00
5.331702E+00
9.480054E+00
0.000000E+00
0.000000E+00
5.598029E+00
1.044833E+01
0.000000E+00
0.000000E+00
5.803138E+00
1.124136E+01
0.000000E+00
0.000000E+00
5.768440E+00
1.110547E+01
0.000000E+00
0.000000E+00
5.554687E+00
1.029492E+01
0.000000E+00
0.000000E+00
5.503880E+00
1.011832E+01
0.000000E+00
0.000000E+00
5.059080E+00
8.564408E+00
0.000000E+00
0.000000E+00
4.718153E+00
7.431929E+00
0.000000E+00
0.000000E+00
4.575826E+00
6.980348E+00
0.000000E+00
0.000000E+00
4.283929E+00
6.120164E+00
0.000000E+00
0.000000E+00
3.997971E+00
5.330979E+00
0.000000E+00
0.000000E+00
3.735927E+00
4.653022E+00
0.000000E+00
0.000000E+00
3.302545E+00
3.645387E+00
0.000000E+00
0.000000E+00
3.082630E+00
3.203343E+00
0.000000E+00
0.000000E+00
2.775434E+00
2.569844E+00
0.000000E+00
0.000000E+00
2.518170E+00
2.134420E+00
0.000000E+00
0.000000E+00
2.233921E+00
1.666795E+00
0.000000E+00
0.000000E+00
1.829991E+00
1.118883E+00
0.000000E+00
0.000000E+00
1.420528E+00
6.755061E-01
0.000000E+00
0.000000E+00
9.856494E-01
3.253539E-01
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00

View file

@ -1,16 +0,0 @@
<?xml version="1.0"?>
<settings>
<run_mode>eigenvalue</run_mode>
<batches>10</batches>
<inactive>5</inactive>
<particles>100</particles>
<source>
<space>
<type>point</type>
<parameters>0.0 0.0 0.0</parameters>
</space>
</source>
</settings>

View file

@ -1,6 +1,39 @@
from tests.testing_harness import TestHarness
import numpy as np
import openmc
import pytest
from tests.testing_harness import PyAPITestHarness
@pytest.fixture
def model():
model = openmc.model.Model()
zn = openmc.Material()
zn.set_density('g/cm3', 7.14)
zn.add_nuclide('Zn64', 1.0)
model.materials.append(zn)
radii = np.linspace(1.0, 100.0)
surfs = [openmc.Sphere(r=r) for r in radii]
surfs[-1].boundary_type = 'vacuum'
cells = [openmc.Cell(fill=(zn if i % 2 == 0 else None), region=region)
for i, region in enumerate(openmc.model.subdivide(surfs))]
model.geometry = openmc.Geometry(cells)
model.settings.run_mode = 'fixed source'
model.settings.batches = 3
model.settings.particles = 1000
model.settings.source = openmc.Source(space=openmc.stats.Point())
cell_filter = openmc.CellFilter(cells)
tally = openmc.Tally()
tally.filters = [cell_filter]
tally.scores = ['total']
model.tallies.append(tally)
return model
def test_void():
harness = TestHarness('statepoint.10.h5')
def test_void(model):
harness = PyAPITestHarness('statepoint.3.h5', model)
harness.main()

View file

@ -72,10 +72,12 @@ class TestHarness(object):
# Read the statepoint file.
statepoint = glob.glob(self._sp_name)[0]
with openmc.StatePoint(statepoint) as sp:
# Write out k-combined.
outstr = 'k-combined:\n'
form = '{0:12.6E} {1:12.6E}\n'
outstr += form.format(sp.k_combined.n, sp.k_combined.s)
outstr = ''
if sp.run_mode == 'eigenvalue':
# Write out k-combined.
outstr += 'k-combined:\n'
form = '{0:12.6E} {1:12.6E}\n'
outstr += form.format(sp.k_combined.n, sp.k_combined.s)
# Write out tally data.
for i, tally_ind in enumerate(sp.tallies):

View file

@ -1,6 +1,17 @@
import openmc
import pytest
from tests.regression_tests import config
@pytest.fixture(scope='module')
def mpi_intracomm():
if config['mpi']:
from mpi4py import MPI
return MPI.COMM_WORLD
else:
return None
@pytest.fixture(scope='module')
def uo2():

Some files were not shown because too many files have changed in this diff Show more