Skip to content

Commit

Permalink
Merge 2d51ff1 into 5d2b352
Browse files Browse the repository at this point in the history
  • Loading branch information
jtramm committed Apr 30, 2024
2 parents 5d2b352 + 2d51ff1 commit f6280d7
Show file tree
Hide file tree
Showing 25 changed files with 2,746 additions and 421 deletions.
46 changes: 42 additions & 4 deletions docs/source/methods/random_ray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ Method of Characteristics
The Boltzmann neutron transport equation is a partial differential equation
(PDE) that describes the angular flux within a system. It is a balance equation,
with the streaming and absorption terms typically appearing on the left hand
side, which are balanced by the scattering source and fission source terms on
side, which are balanced by the scattering source, fission, and fixed source terms on
the right hand side.

.. math::
Expand Down Expand Up @@ -522,8 +522,8 @@ make their traversals, and summing these contributions up as in Equation
improve the estimate of the source and scalar flux over many iterations, given
that our initial starting source will just be a guess?

The source :math:`Q^{n}` for iteration :math:`n` can be inferred
from the scalar flux from the previous iteration :math:`n-1` as:
In an eigenvalue simulation, the source :math:`Q^{n}` for iteration :math:`n`
can be inferred from the scalar flux from the previous iteration :math:`n-1` as:

.. math::
:label: source_update
Expand All @@ -535,7 +535,7 @@ where :math:`Q^{n}(i, g)` is the total source (fission + scattering) in region
:math:`g` must be computed by summing over the contributions from all groups
:math:`g' \in G`.

In a similar manner, the eigenvalue for iteration :math:`n` can be computed as:
The eigenvalue for iteration :math:`n` can be computed as:

.. math::
:label: eigenvalue_update
Expand Down Expand Up @@ -576,6 +576,18 @@ and a similar substitution can be made to update Equation
estimate is used, such that the total fission source from the previous iteration
(:math:`n-1`) is also recomputed each iteration.

In a fixed source simulation, the fission source is replaced
by a user specified fixed source term :math:`Q_{fixed}(i,E)`, which is defined
for each FSR and energy group. This additional source term is applied at this
stage for generating the next iteration's source estimate as:

.. math::
:label: fixed_source_update
Q^{n}(i, g) = Q_{fixed}(i,g) + \sum\limits^{G}_{g'} \Sigma_{s}(i,g,g') \phi^{n-1}(g')
and no eigenvalue is computed.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ray Starting Conditions and Inactive Length
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -742,6 +754,32 @@ behavior if a single simulation cell is able to score to multiple filter mesh
cells. In the future, the capability to fully support mesh tallies may be added
to OpenMC, but for now this restriction needs to be respected.

.. _usersguide_fixed_source_methods:

------------
Fixed Source
------------

The random ray solver in OpenMC can be used for both eigenvalue and fixed source
problems. There are a few key differences between fixed source transport with
random ray and Monte Carlo, however.

- **Source definition:** In Monte Carlo, it is relatively easy to define various
source distributions, including point sources, surface sources, volume
sources, and even custom user sources -- all with varying angular and spatial
statistical distributions. In random ray, the natural way to include a fixed
source term is by adding a fixed (flat) contribution to specific flat source
regions. Thus, in the OpenMC implementation of random ray, particle sources
are restricted to being volumetric and isotropic, although different energy
spectrums are supported. Fixed sources can be applied to specific materials,
cells, or universes.

- **Inactive batches:** In Monte Carlo, use of a fixed source implies that all
batches are active batches, as there is no longer a need to develop a fission
source distribution. However, in random ray mode, there is still need to
develop the scattering source by way of inactive batches before beginning
active batches.

---------------------------
Fundamental Sources of Bias
---------------------------
Expand Down
154 changes: 150 additions & 4 deletions docs/source/usersguide/random_ray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ Carlo, **inactive batches are required for both eigenvalue and fixed source
solves in random ray mode** due to this additional need to converge the
scattering source.

.. warning::
Unlike Monte Carlo, the random ray solver still requires usage of inactive
batches when in fixed source mode so as to develop the scattering source.

The additional burden of converging the scattering source generally results in a
higher requirement for the number of inactive batches---often by an order of
magnitude or more. For instance, it may be reasonable to only use 50 inactive
batches for a light water reactor simulation with Monte Carlo, but random ray
might require 500 or more inactive batches. Similar to Monte Carlo,
:ref:`Shannon entropy <usersguide_entropy>` can be used to gauge whether the
combined scattering and fission source has fully developed.
might require 500 or more inactive batches.

Similar to Monte Carlo, active batches are used in the random ray solver mode to
accumulate and converge statistics on unknown quantities (i.e., the random ray
Expand Down Expand Up @@ -248,6 +250,8 @@ a larger value until the "low ray density" messages go away.
ray lengths are sufficiently long to allow for transport to occur between
source and target regions of interest.

.. _usersguide_ray_source:

----------
Ray Source
----------
Expand Down Expand Up @@ -411,12 +415,76 @@ in the `OpenMC Jupyter notebook collection
separate materials can be defined each with a separate multigroup dataset
corresponding to a given temperature.

---------------------------------
Fixed Source and Eigenvalue Modes
---------------------------------

Both fixed source and eigenvalue modes are supported with the random ray solver
in OpenMC. Modes can be selected as described in the :ref:`run modes section
<usersguide_run_modes>`. In both modes, a ray source must be provided to let
OpenMC know where to sample ray starting locations from, as discussed in the
:ref:`ray source section <usersguide_ray_source>`. In fixed source mode, at
least one regular source must be provided as well which represents the physical
particle fixed source. As discussed in the :ref:`fixed source methodology
section <usersguide_fixed_source_methods>`, the types of fixed sources supported
in the random ray solver mode are much more limited as compared to what is
possible with the Monte Carlo solver.

Currently, all of the following conditions must be met for the source to be
valid in random ray mode:

- One or more domain ids must be specified that indicate which cells, universes,
or materials the source applies to. This implicitly limits the source type to
being volumetric. This is specified via the ``domains`` field of the
:class:`openmc.IndependentSource` Python class.
- The source must be isotropic (default for a source)
- The source must use a discrete (i.e., multigroup) energy distribution. The
discrete energy distribution is input by defining a
:class:`openmc.stats.Discrete` Python class, and passed as the ``energy``
field of the :class:`openmc.IndependentSource` Python class.

Any other spatial distribution information contained in a particle source will
be ignored. Only the specified cell, material, or universe domains will be used
to define the spatial location of the source, as the source will be applied
during a pre-processing stage of OpenMC to all source regions that are contained
within the inputted domains for the source.

When defining a :class:`openmc.stats.Discrete` object, note that the ``x`` field
will correspond to the discrete energy points, and the ``p`` field will
correspond to the discrete probabilities. It is recommended to select energy
points that fall within energy groups rather than on boundaries between the
groups. I.e., if the problem contains two energy groups (with bin edges of
1.0e-5, 1.0e-1, 1.0e7), then a good selection for the ``x`` field might be
points of 1.0e-2 and 1.0e1.

::
# Define geometry, etc.
...
source_cell = openmc.Cell(fill=source_mat, name='cell where fixed source will be')
...
# Define physical neutron fixed source
energy_points = [1.0e-2, 1.0e1]
strengths = [0.25, 0.75]
energy_distribution = openmc.stats.Discrete(x=energy_points,p=strengths)
neutron_source = openmc.IndependentSource(energy=energy_distribution, domains=[source_cell], strength=1.0)

# Add fixed source and ray sampling source to settings file
settings.source = [neutron_source]

---------------------------------------
Putting it All Together: Example Inputs
---------------------------------------

An example of a settings definition for random ray is given below::
~~~~~~~~~~~~~~~~~~
Eigenvalue Example
~~~~~~~~~~~~~~~~~~

An example of a settings definition for an eigenvalue random ray simulation is
given below:

::
# Geometry and MGXS material definition of 2x2 lattice (not shown)
pitch = 1.26
group_edges = [1e-5, 0.0635, 10.0, 1.0e2, 1.0e3, 0.5e6, 1.0e6, 20.0e6]
Expand Down Expand Up @@ -478,3 +546,81 @@ Monte Carlo run (see the :ref:`geometry <usersguide_geometry>` and

There is also a complete example of a pincell available in the
``openmc/examples/pincell_random_ray`` folder.

~~~~~~~~~~~~~~~~~~~~
Fixed Source Example
~~~~~~~~~~~~~~~~~~~~

An example of a settings definition for a fixed source random ray simulation is
given below:

::

# Geometry and MGXS material definition of 2x2 lattice (not shown)
pitch = 1.26
source_cell = openmc.Cell(fill=source_mat, name='cell where fixed source will be')
ebins = [1e-5, 1e-1, 20.0e6]
...

# Instantiate a settings object for a random ray solve
settings = openmc.Settings()
settings.energy_mode = "multi-group"
settings.batches = 1200
settings.inactive = 600
settings.particles = 2000
settings.run_mode = 'fixed source'
settings.random_ray['distance_inactive'] = 40.0
settings.random_ray['distance_active'] = 400.0

# Create an initial uniform spatial source distribution for sampling rays
lower_left = (-pitch, -pitch, -pitch)
upper_right = ( pitch, pitch, pitch)
uniform_dist = openmc.stats.Box(lower_left, upper_right)
settings.random_ray['ray_source'] = openmc.IndependentSource(space=uniform_dist)

# Define physical neutron fixed source
energy_points = [1.0e-2, 1.0e1]
strengths = [0.25, 0.75]
energy_distribution = openmc.stats.Discrete(x=energy_points,p=strengths)
neutron_source = openmc.IndependentSource(energy=energy_distribution, domains=[source_cell], strength=1.0)

# Add fixed source and ray sampling source to settings file
settings.source = [neutron_source]

settings.export_to_xml()

# Define tallies

# Create a mesh filter
mesh = openmc.RegularMesh()
mesh.dimension = (2, 2)
mesh.lower_left = (-pitch/2, -pitch/2)
mesh.upper_right = (pitch/2, pitch/2)
mesh_filter = openmc.MeshFilter(mesh)

# Create a multigroup energy filter
energy_filter = openmc.EnergyFilter(ebins)

# Create tally using our two filters and add scores
tally = openmc.Tally()
tally.filters = [mesh_filter, energy_filter]
tally.scores = ['flux']

# Instantiate a Tallies collection and export to XML
tallies = openmc.Tallies([tally])
tallies.export_to_xml()

# Create voxel plot
plot = openmc.Plot()
plot.origin = [0, 0, 0]
plot.width = [2*pitch, 2*pitch, 1]
plot.pixels = [1000, 1000, 1]
plot.type = 'voxel'

# Instantiate a Plots collection and export to XML
plot_file = openmc.Plots([plot])
plot_file.export_to_xml()

All other inputs (e.g., geometry, material) will be unchanged from a typical
Monte Carlo run (see the :ref:`geometry <usersguide_geometry>` and
:ref:`multigroup materials <create_mgxs>` user guides for more information).
3 changes: 3 additions & 0 deletions include/openmc/mgxs_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class MgxsInterface {
// Get the kT values which are used in the OpenMC model
vector<vector<double>> get_mat_kTs();

// Get the group index corresponding to a continuous energy
int get_group_index(double e);

int num_energy_groups_;
int num_delayed_groups_;
vector<std::string> xs_names_; // available names in HDF5 file
Expand Down

0 comments on commit f6280d7

Please sign in to comment.