Skip to content

Commit

Permalink
Implementation of Shannon Entropy for Random Ray (#3030)
Browse files Browse the repository at this point in the history
Co-authored-by: Ethan Krammer <ethan@DESKTOP-MGFGK9N>
Co-authored-by: John Tramm <[email protected]>
  • Loading branch information
3 people committed Jun 27, 2024
1 parent 8ce81d1 commit a8171cb
Show file tree
Hide file tree
Showing 14 changed files with 282 additions and 29 deletions.
17 changes: 13 additions & 4 deletions docs/source/methods/eigenvalue.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,17 @@ in :ref:`fission-bank-algorithms`.
Source Convergence Issues
-------------------------

.. _methods-shannon-entropy:

Diagnosing Convergence with Shannon Entropy
-------------------------------------------

As discussed earlier, it is necessary to converge both :math:`k_{eff}` and the
source distribution before any tallies can begin. Moreover, the convergence rate
of the source distribution is in general slower than that of
:math:`k_{eff}`. One should thus examine not only the convergence of
:math:`k_{eff}` but also the convergence of the source distribution in order to
make decisions on when to start active batches.
of the source distribution is in general slower than that of :math:`k_{eff}`.
One should thus examine not only the convergence of :math:`k_{eff}` but also the
convergence of the source distribution in order to make decisions on when to
start active batches.

However, the representation of the source distribution makes it a bit more
difficult to analyze its convergence. Since :math:`k_{eff}` is a scalar
Expand Down Expand Up @@ -108,6 +110,13 @@ at plots of :math:`k_{eff}` and the Shannon entropy. A number of methods have
been proposed (see e.g. [Romano]_, [Ueki]_), but each of these is not without
problems.

Shannon entropy is calculated differently for the random ray solver, as
described :ref:`in the random ray theory section
<methods-shannon-entropy-random-ray>`. Additionally, as the Shannon entropy only
serves as a diagnostic tool for convergence of the fission source distribution,
there is currently no diagnostic to determine if the scattering source
distribution in random ray is converged.

---------------------------
Uniform Fission Site Method
---------------------------
Expand Down
36 changes: 36 additions & 0 deletions docs/source/methods/random_ray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,8 @@ which when partially simplified becomes:
Note that there are now four (seemingly identical) volume terms in this equation.

.. _methods-volume-dilemma:

~~~~~~~~~~~~~~
Volume Dilemma
~~~~~~~~~~~~~~
Expand Down Expand Up @@ -745,6 +747,7 @@ How are Tallies Handled?
Most tallies, filters, and scores that you would expect to work with a
multigroup solver like random ray should work. For example, you can define 3D
mesh tallies with energy filters and flux, fission, and nu-fission scores, etc.

There are some restrictions though. For starters, it is assumed that all filter
mesh boundaries will conform to physical surface boundaries (or lattice
boundaries) in the simulation geometry. It is acceptable for multiple cells
Expand All @@ -754,6 +757,39 @@ 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.

.. _methods-shannon-entropy-random-ray:

-----------------------------
Shannon Entropy in Random Ray
-----------------------------

As :math:`k_{eff}` is updated at each generation, the fission source at each FSR
is used to compute the Shannon entropy. This follows the :ref:`same procedure
for computing Shannon entropy in continuous-energy or multigroup Monte Carlo
simulations <methods-shannon-entropy>`, except that fission sources at FSRs are
considered, rather than fission sites of user-defined regular meshes. Thus, the
volume-weighted fission rate is considered instead, and the fraction of fission
sources is adjusted such that:

.. math::
:label: fraction-source-random-ray
S_i = \frac{\text{Fission source in FSR $i \times$ Volume of FSR
$i$}}{\text{Total fission source}} = \frac{Q_{i} V_{i}}{\sum_{i=1}^{i=N}
Q_{i} V_{i}}
The Shannon entropy is then computed normally as

.. math::
:label: shannon-entropy-random-ray
H = - \sum_{i=1}^N S_i \log_2 S_i
where :math:`N` is the number of FSRs. FSRs with no fission source (or,
occassionally, negative fission source, :ref:`due to the volume estimator
problem <methods-volume-dilemma>`) are skipped to avoid taking an undefined
logarithm in :eq:`shannon-entropy-random-ray`.

.. _usersguide_fixed_source_methods:

------------
Expand Down
11 changes: 11 additions & 0 deletions docs/source/usersguide/random_ray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ solver::
settings.batches = 1200
settings.inactive = 600

---------------
Shannon Entropy
---------------

Similar to Monte Carlo, :ref:`Shannon entropy
<methods-shannon-entropy-random-ray>` can be used to gauge whether the fission
source has fully developed. The Shannon entropy is calculated automatically
after each batch and is printed to the statepoint file. Unlike Monte Carlo, an
entropy mesh does not need to be defined, as the Shannon entropy is calculated
over FSRs using a volume-weighted approach.

-------------------------------
Inactive Ray Length (Dead Zone)
-------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/eigenvalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ void shannon_entropy()
double H = 0.0;
for (auto p_i : p) {
if (p_i > 0.0) {
H -= p_i * std::log(p_i) / std::log(2.0);
H -= p_i * std::log2(p_i);
}
}

Expand Down
38 changes: 34 additions & 4 deletions src/random_ray/flat_source_domain.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "openmc/random_ray/flat_source_domain.h"

#include "openmc/cell.h"
#include "openmc/eigenvalue.h"
#include "openmc/geometry.h"
#include "openmc/material.h"
#include "openmc/message_passing.h"
Expand Down Expand Up @@ -278,6 +279,9 @@ double FlatSourceDomain::compute_k_eff(double k_eff_old) const
const int t = 0;
const int a = 0;

// Vector for gathering fission source terms for Shannon entropy calculation
vector<float> p(n_source_regions_, 0.0f);

#pragma omp parallel for reduction(+ : fission_rate_old, fission_rate_new)
for (int sr = 0; sr < n_source_regions_; sr++) {

Expand All @@ -300,12 +304,38 @@ double FlatSourceDomain::compute_k_eff(double k_eff_old) const
sr_fission_source_new += nu_sigma_f * scalar_flux_new_[idx];
}

fission_rate_old += sr_fission_source_old * volume;
fission_rate_new += sr_fission_source_new * volume;
// Compute total fission rates in FSR
sr_fission_source_old *= volume;
sr_fission_source_new *= volume;

// Accumulate totals
fission_rate_old += sr_fission_source_old;
fission_rate_new += sr_fission_source_new;

// Store total fission rate in the FSR for Shannon calculation
p[sr] = sr_fission_source_new;
}

double k_eff_new = k_eff_old * (fission_rate_new / fission_rate_old);

double H = 0.0;
// defining an inverse sum for better performance
double inverse_sum = 1 / fission_rate_new;

#pragma omp parallel for reduction(+ : H)
for (int sr = 0; sr < n_source_regions_; sr++) {
// Only if FSR has non-negative and non-zero fission source
if (p[sr] > 0.0f) {
// Normalize to total weight of bank sites. p_i for better performance
float p_i = p[sr] * inverse_sum;
// Sum values to obtain Shannon entropy.
H -= p_i * std::log2(p_i);
}
}

// Adds entropy value to shared entropy vector in openmc namespace.
simulation::entropy.push_back(H);

return k_eff_new;
}

Expand Down Expand Up @@ -525,8 +555,8 @@ void FlatSourceDomain::random_ray_tally()
#pragma omp atomic
tally.results_(task.filter_idx, task.score_idx, TallyResult::VALUE) +=
score;
} // end tally task loop
} // end energy group loop
}
}

// For flux tallies, the total volume of the spatial region is needed
// for normalizing the flux. We store this volume in a separate tensor.
Expand Down
45 changes: 26 additions & 19 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,30 +627,37 @@ void read_settings_xml(pugi::xml_node root)
}
}

// Shannon Entropy mesh
if (check_for_node(root, "entropy_mesh")) {
int temp = std::stoi(get_node_value(root, "entropy_mesh"));
if (model::mesh_map.find(temp) == model::mesh_map.end()) {
fatal_error(fmt::format(
"Mesh {} specified for Shannon entropy does not exist.", temp));
// Shannon entropy
if (solver_type == SolverType::RANDOM_RAY) {
if (check_for_node(root, "entropy_mesh")) {
fatal_error("Random ray uses FSRs to compute the Shannon entropy. "
"No user-defined entropy mesh is supported.");
}
entropy_on = true;
} else if (solver_type == SolverType::MONTE_CARLO) {
if (check_for_node(root, "entropy_mesh")) {
int temp = std::stoi(get_node_value(root, "entropy_mesh"));
if (model::mesh_map.find(temp) == model::mesh_map.end()) {
fatal_error(fmt::format(
"Mesh {} specified for Shannon entropy does not exist.", temp));
}

auto* m =
dynamic_cast<RegularMesh*>(model::meshes[model::mesh_map.at(temp)].get());
if (!m)
fatal_error("Only regular meshes can be used as an entropy mesh");
simulation::entropy_mesh = m;
auto* m = dynamic_cast<RegularMesh*>(
model::meshes[model::mesh_map.at(temp)].get());
if (!m)
fatal_error("Only regular meshes can be used as an entropy mesh");
simulation::entropy_mesh = m;

// Turn on Shannon entropy calculation
entropy_on = true;
// Turn on Shannon entropy calculation
entropy_on = true;

} else if (check_for_node(root, "entropy")) {
fatal_error(
"Specifying a Shannon entropy mesh via the <entropy> element "
"is deprecated. Please create a mesh using <mesh> and then reference "
"it by specifying its ID in an <entropy_mesh> element.");
} else if (check_for_node(root, "entropy")) {
fatal_error(
"Specifying a Shannon entropy mesh via the <entropy> element "
"is deprecated. Please create a mesh using <mesh> and then reference "
"it by specifying its ID in an <entropy_mesh> element.");
}
}

// Uniform fission source weighting mesh
if (check_for_node(root, "ufs_mesh")) {
auto temp = std::stoi(get_node_value(root, "ufs_mesh"));
Expand Down
3 changes: 2 additions & 1 deletion src/simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,8 @@ void finalize_generation()
if (settings::run_mode == RunMode::EIGENVALUE) {

// Calculate shannon entropy
if (settings::entropy_on)
if (settings::entropy_on &&
settings::solver_type == SolverType::MONTE_CARLO)
shannon_entropy();

// Collect results and statistics
Expand Down
Empty file.
88 changes: 88 additions & 0 deletions tests/regression_tests/random_ray_entropy/geometry.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?xml version='1.0' encoding='UTF-8'?>
<geometry>
<cell id="1" material="1" universe="1"/>
<cell fill="2" id="2" name="assembly" region="-2 1 -4 3 -6 5" universe="3"/>
<lattice id="2">
<pitch>12.5 12.5 12.5</pitch>
<dimension>8 8 8</dimension>
<lower_left>0.0 0.0 0.0</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 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1

1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1
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>
<surface boundary="reflective" coeffs="0.0" id="1" type="x-plane"/>
<surface boundary="reflective" coeffs="100.0" id="2" type="x-plane"/>
<surface boundary="reflective" coeffs="0.0" id="3" type="y-plane"/>
<surface boundary="reflective" coeffs="100.0" id="4" type="y-plane"/>
<surface boundary="reflective" coeffs="0.0" id="5" type="z-plane"/>
<surface boundary="reflective" coeffs="100.0" id="6" type="z-plane"/>
</geometry>
8 changes: 8 additions & 0 deletions tests/regression_tests/random_ray_entropy/materials.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version='1.0' encoding='utf-8'?>
<materials>
<cross_sections>mgxs.h5</cross_sections>
<material id="1" name="Core Material">
<density units="macro" value="1.0"/>
<macroscopic name="CoreMaterial"/>
</material>
</materials>
Binary file added tests/regression_tests/random_ray_entropy/mgxs.h5
Binary file not shown.
13 changes: 13 additions & 0 deletions tests/regression_tests/random_ray_entropy/results_true.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
k-combined:
1.000000E+00 0.000000E+00
entropy:
8.863421E+00
8.933584E+00
8.960553E+00
8.967921E+00
8.976016E+00
8.981856E+00
8.983670E+00
8.986584E+00
8.987732E+00
8.988186E+00
17 changes: 17 additions & 0 deletions tests/regression_tests/random_ray_entropy/settings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version='1.0' encoding='UTF-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>100</particles>
<batches>10</batches>
<inactive>5</inactive>
<energy_mode>multi-group</energy_mode>
<random_ray>
<source particle="neutron" strength="1.0" type="independent">
<space type="box">
<parameters>0.0 0.0 0.0 100.0 100.0 100.0</parameters>
</space>
</source>
<distance_inactive>40.0</distance_inactive>
<distance_active>400.0</distance_active>
</random_ray>
</settings>
Loading

0 comments on commit a8171cb

Please sign in to comment.