From b22656e57f9469d25f14a203831bcdb390cd84db Mon Sep 17 00:00:00 2001 From: John Tramm Date: Thu, 15 Aug 2024 20:47:05 -0500 Subject: [PATCH] Fix random ray solver to correctly simulate fixed source problems with fissionable materials (#3106) Co-authored-by: Paul Romano --- openmc/examples.py | 2 +- src/random_ray/flat_source_domain.cpp | 40 ++--- .../__init__.py | 0 .../flat/inputs_true.dat | 140 +++++++++++++++ .../flat/results_true.dat | 169 ++++++++++++++++++ .../linear_xy/inputs_true.dat | 140 +++++++++++++++ .../linear_xy/results_true.dat | 169 ++++++++++++++++++ .../test.py | 133 ++++++++++++++ 8 files changed, 772 insertions(+), 21 deletions(-) create mode 100644 tests/regression_tests/random_ray_fixed_source_subcritical/__init__.py create mode 100644 tests/regression_tests/random_ray_fixed_source_subcritical/flat/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_fixed_source_subcritical/flat/results_true.dat create mode 100644 tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/inputs_true.dat create mode 100644 tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/results_true.dat create mode 100644 tests/regression_tests/random_ray_fixed_source_subcritical/test.py diff --git a/openmc/examples.py b/openmc/examples.py index 038c75ad2..538b6ea4a 100644 --- a/openmc/examples.py +++ b/openmc/examples.py @@ -804,7 +804,7 @@ def random_ray_lattice() -> openmc.Model: azimuthal_cells.append(azimuthal_cell) # Create a geometry with the azimuthal universes - pincell = openmc.Universe(cells=azimuthal_cells) + pincell = openmc.Universe(cells=azimuthal_cells, name='pincell') ######################################## # Define a moderator lattice universe diff --git a/src/random_ray/flat_source_domain.cpp b/src/random_ray/flat_source_domain.cpp index 8b6cda93f..584b3a7ed 100644 --- a/src/random_ray/flat_source_domain.cpp +++ b/src/random_ray/flat_source_domain.cpp @@ -158,31 +158,31 @@ void FlatSourceDomain::update_neutron_source(double k_eff) } } - if (settings::run_mode == RunMode::EIGENVALUE) { - // Add fission source if in eigenvalue mode + // Add fission source #pragma omp parallel for - for (int sr = 0; sr < n_source_regions_; sr++) { - int material = material_[sr]; + for (int sr = 0; sr < n_source_regions_; sr++) { + int material = material_[sr]; - for (int e_out = 0; e_out < negroups_; e_out++) { - float sigma_t = data::mg.macro_xs_[material].get_xs( - MgxsType::TOTAL, e_out, nullptr, nullptr, nullptr, t, a); - float fission_source = 0.0f; + for (int e_out = 0; e_out < negroups_; e_out++) { + float sigma_t = data::mg.macro_xs_[material].get_xs( + MgxsType::TOTAL, e_out, nullptr, nullptr, nullptr, t, a); + float fission_source = 0.0f; - for (int e_in = 0; e_in < negroups_; e_in++) { - float scalar_flux = scalar_flux_old_[sr * negroups_ + e_in]; - float nu_sigma_f = data::mg.macro_xs_[material].get_xs( - MgxsType::NU_FISSION, e_in, nullptr, nullptr, nullptr, t, a); - float chi = data::mg.macro_xs_[material].get_xs( - MgxsType::CHI_PROMPT, e_in, &e_out, nullptr, nullptr, t, a); - fission_source += nu_sigma_f * scalar_flux * chi; - } - source_[sr * negroups_ + e_out] += - fission_source * inverse_k_eff / sigma_t; + for (int e_in = 0; e_in < negroups_; e_in++) { + float scalar_flux = scalar_flux_old_[sr * negroups_ + e_in]; + float nu_sigma_f = data::mg.macro_xs_[material].get_xs( + MgxsType::NU_FISSION, e_in, nullptr, nullptr, nullptr, t, a); + float chi = data::mg.macro_xs_[material].get_xs( + MgxsType::CHI_PROMPT, e_in, &e_out, nullptr, nullptr, t, a); + fission_source += nu_sigma_f * scalar_flux * chi; } + source_[sr * negroups_ + e_out] += + fission_source * inverse_k_eff / sigma_t; } - } else { -// Add external source if in fixed source mode + } + + // Add external source if in fixed source mode + if (settings::run_mode == RunMode::FIXED_SOURCE) { #pragma omp parallel for for (int se = 0; se < n_source_elements_; se++) { source_[se] += external_source_[se]; diff --git a/tests/regression_tests/random_ray_fixed_source_subcritical/__init__.py b/tests/regression_tests/random_ray_fixed_source_subcritical/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/regression_tests/random_ray_fixed_source_subcritical/flat/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_subcritical/flat/inputs_true.dat new file mode 100644 index 000000000..0bf4cfdc9 --- /dev/null +++ b/tests/regression_tests/random_ray_fixed_source_subcritical/flat/inputs_true.dat @@ -0,0 +1,140 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.126 0.126 + 10 10 + -0.63 -0.63 + +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 + + + 0.126 0.126 + 10 10 + -0.63 -0.63 + +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 9 + + + 1.26 1.26 + 2 2 + -1.26 -1.26 + +2 12 +12 13 + + + + + + + + + + + + + + + + + + + + + fixed source + 30 + 125 + 100 + + + 1.134 -1.26 -1.0 1.26 -1.134 1.0 + + + 2e-05 0.0735 20.0 200.0 2000.0 750000.0 2000000.0 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 + + + universe + 9 + + + multi-group + + 40.0 + 40.0 + + + -1.26 -1.26 -1 1.26 1.26 1 + + + False + flat + + + + + 2 2 + -1.26 -1.26 + 1.26 1.26 + + + 1 + + + 1e-05 0.0635 10.0 100.0 1000.0 500000.0 1000000.0 20000000.0 + + + 1 2 + flux fission nu-fission + analog + + + diff --git a/tests/regression_tests/random_ray_fixed_source_subcritical/flat/results_true.dat b/tests/regression_tests/random_ray_fixed_source_subcritical/flat/results_true.dat new file mode 100644 index 000000000..e9d2a733d --- /dev/null +++ b/tests/regression_tests/random_ray_fixed_source_subcritical/flat/results_true.dat @@ -0,0 +1,169 @@ +tally 1: +1.582116E+02 +1.005480E+03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.897563E+01 +1.396228E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.038901E+01 +1.667203E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.465551E+01 +2.438101E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.260230E+01 +1.110141E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.438906E+01 +3.579643E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.698287E+01 +1.314208E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.002152E+02 +1.608182E+03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.374897E+01 +2.181176E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.636086E+01 +2.787512E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +3.000395E+01 +3.611990E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.824715E+01 +1.360847E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.621963E+01 +3.714397E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.954480E+01 +1.436984E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.067903E+02 +4.585529E+02 +1.257560E+01 +6.364831E+00 +3.060650E+01 +3.770132E+01 +4.983480E+01 +9.972910E+01 +2.349541E+00 +2.217300E-01 +5.718312E+00 +1.313392E+00 +1.965462E+01 +1.548888E+01 +2.011494E-01 +1.622334E-03 +4.895573E-01 +9.609705E-03 +2.318671E+01 +2.155841E+01 +2.445032E-01 +2.397352E-03 +5.950720E-01 +1.420043E-02 +5.322867E+01 +1.136138E+02 +1.968847E-01 +1.554358E-03 +4.791838E-01 +9.207284E-03 +1.191175E+02 +5.692803E+02 +5.806982E-02 +1.354810E-04 +1.436897E-01 +8.295235E-04 +8.022963E+01 +2.589171E+02 +3.465139E-01 +4.882327E-03 +9.638109E-01 +3.777193E-02 +1.555305E+02 +9.711601E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.836421E+01 +1.367538E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.042089E+01 +1.673401E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.477708E+01 +2.463124E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.317851E+01 +1.134205E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.634473E+01 +3.724422E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.879813E+01 +1.396454E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 diff --git a/tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/inputs_true.dat b/tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/inputs_true.dat new file mode 100644 index 000000000..f7572a072 --- /dev/null +++ b/tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/inputs_true.dat @@ -0,0 +1,140 @@ + + + + mgxs.h5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.126 0.126 + 10 10 + -0.63 -0.63 + +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 + + + 0.126 0.126 + 10 10 + -0.63 -0.63 + +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 8 +8 8 8 8 8 8 8 8 8 9 + + + 1.26 1.26 + 2 2 + -1.26 -1.26 + +2 12 +12 13 + + + + + + + + + + + + + + + + + + + + + fixed source + 30 + 125 + 100 + + + 1.134 -1.26 -1.0 1.26 -1.134 1.0 + + + 2e-05 0.0735 20.0 200.0 2000.0 750000.0 2000000.0 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 0.14285714285714285 + + + universe + 9 + + + multi-group + + 40.0 + 40.0 + + + -1.26 -1.26 -1 1.26 1.26 1 + + + False + linear_xy + + + + + 2 2 + -1.26 -1.26 + 1.26 1.26 + + + 1 + + + 1e-05 0.0635 10.0 100.0 1000.0 500000.0 1000000.0 20000000.0 + + + 1 2 + flux fission nu-fission + analog + + + diff --git a/tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/results_true.dat b/tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/results_true.dat new file mode 100644 index 000000000..90be5c569 --- /dev/null +++ b/tests/regression_tests/random_ray_fixed_source_subcritical/linear_xy/results_true.dat @@ -0,0 +1,169 @@ +tally 1: +1.573422E+02 +9.945961E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.868035E+01 +1.382578E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.028997E+01 +1.651549E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.453137E+01 +2.414255E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.232506E+01 +1.098683E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.385720E+01 +3.539613E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.664229E+01 +1.298333E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.001324E+02 +1.606858E+03 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +7.358736E+01 +2.171786E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.625416E+01 +2.765491E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.987675E+01 +3.582038E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.797311E+01 +1.348247E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.573509E+01 +3.677339E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.926615E+01 +1.423707E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +1.060513E+02 +4.521166E+02 +1.247077E+01 +6.257701E+00 +3.035137E+01 +3.706675E+01 +4.962504E+01 +9.887387E+01 +2.338861E+00 +2.196709E-01 +5.692320E+00 +1.301195E+00 +1.957564E+01 +1.536441E+01 +2.003053E-01 +1.608650E-03 +4.875030E-01 +9.528647E-03 +2.309275E+01 +2.138375E+01 +2.434816E-01 +2.377213E-03 +5.925856E-01 +1.408114E-02 +5.300741E+01 +1.126617E+02 +1.960322E-01 +1.540737E-03 +4.771089E-01 +9.126597E-03 +1.184809E+02 +5.630856E+02 +5.774249E-02 +1.339082E-04 +1.428798E-01 +8.198938E-04 +7.971031E+01 +2.554943E+02 +3.441954E-01 +4.814135E-03 +9.573621E-01 +3.724437E-02 +1.549617E+02 +9.639834E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.808547E+01 +1.354629E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.029953E+01 +1.654123E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +2.462331E+01 +2.433425E+01 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.283851E+01 +1.120036E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +9.572799E+01 +3.677288E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 +5.842566E+01 +1.378719E+02 +0.000000E+00 +0.000000E+00 +0.000000E+00 +0.000000E+00 diff --git a/tests/regression_tests/random_ray_fixed_source_subcritical/test.py b/tests/regression_tests/random_ray_fixed_source_subcritical/test.py new file mode 100644 index 000000000..6c2c569c6 --- /dev/null +++ b/tests/regression_tests/random_ray_fixed_source_subcritical/test.py @@ -0,0 +1,133 @@ +import os + +import openmc +from openmc.examples import random_ray_lattice +from openmc.utility_funcs import change_directory +import pytest + +from tests.testing_harness import TolerantPyAPITestHarness + + +class MGXSTestHarness(TolerantPyAPITestHarness): + def _cleanup(self): + super()._cleanup() + f = 'mgxs.h5' + if os.path.exists(f): + os.remove(f) + + +@pytest.mark.parametrize("shape", ["flat", "linear_xy"]) +def test_random_ray_source(shape): + with change_directory(shape): + openmc.reset_auto_ids() + + # The general strategy is to reuse the random_ray_lattice model, + # but redfine some of the geometry to make it a good + # subcritical multiplication problem. We then also add in + # a fixed source term. + + model = random_ray_lattice() + + # Begin by updating the random ray settings for fixed source + settings = model.settings + settings.random_ray['source_shape'] = shape + settings.run_mode = 'fixed source' + settings.particles = 30 + settings.random_ray['distance_active'] = 40.0 + settings.random_ray['distance_inactive'] = 40.0 + settings.random_ray['volume_normalized_flux_tallies'] = False + + # This problem needs about 2k iterations to converge, + # but for regression testing we only need a few hundred + # to ensure things are working as expected. With + # only 100 inactive batches, tallies will still be off + # by 3x or more. For validation against MGMC, be sure + # to increase the batch counts. + settings.batches = 125 + settings.inactive = 100 + + ######################################## + # Define the alternative geometry + + pitch = 1.26 + + for material in model.materials: + if material.name == 'Water': + water = material + + # The new geometry replaces two of the fuel pins with + # moderator, reducing k-eff to around 0.84. We also + # add a special universe in the corner of one of the moderator + # regions to use as a domain constraint for the source + moderator_infinite = openmc.Cell(fill=water, name='moderator infinite') + mu = openmc.Universe(cells=[moderator_infinite]) + + moderator_infinite2 = openmc.Cell(fill=water, name='moderator infinite 2') + mu2 = openmc.Universe(cells=[moderator_infinite2]) + + n_sub = 10 + + lattice = openmc.RectLattice() + lattice.lower_left = [-pitch/2.0, -pitch/2.0] + lattice.pitch = [pitch/n_sub, pitch/n_sub] + lattice.universes = [[mu] * n_sub for _ in range(n_sub)] + + lattice2 = openmc.RectLattice() + lattice2.lower_left = [-pitch/2.0, -pitch/2.0] + lattice2.pitch = [pitch/n_sub, pitch/n_sub] + lattice2.universes = [[mu] * n_sub for _ in range(n_sub)] + lattice2.universes[n_sub-1][n_sub-1] = mu2 + + mod_lattice_cell = openmc.Cell(fill=lattice) + mod_lattice_uni = openmc.Universe(cells=[mod_lattice_cell]) + + mod_lattice_cell2 = openmc.Cell(fill=lattice2) + mod_lattice_uni2 = openmc.Universe(cells=[mod_lattice_cell2]) + + lattice2x2 = openmc.RectLattice() + lattice2x2.lower_left = [-pitch, -pitch] + lattice2x2.pitch = [pitch, pitch] + + universes = model.geometry.get_all_universes() + for universe in universes.values(): + if universe.name == 'pincell': + pincell = universe + + lattice2x2.universes = [ + [pincell, mod_lattice_uni], + [mod_lattice_uni, mod_lattice_uni2] + ] + + box = openmc.model.RectangularPrism( + pitch*2, pitch*2, boundary_type='reflective') + + assembly = openmc.Cell(fill=lattice2x2, region=-box, name='assembly') + + root = openmc.Universe(name='root universe', cells=[assembly]) + model.geometry = openmc.Geometry(root) + + ######################################## + # Define the fixed source term + + s = 1.0 / 7.0 + strengths = [s, s, s, s, s, s, s] + midpoints = [2.0e-5, 0.0735, 20.0, 2.0e2, 2.0e3, 0.75e6, 2.0e6] + energy_distribution = openmc.stats.Discrete(x=midpoints, p=strengths) + + lower_left_src = [pitch - pitch/10.0, -pitch, -1.0] + upper_right_src = [pitch, -pitch + pitch/10.0, 1.0] + spatial_distribution = openmc.stats.Box( + lower_left_src, upper_right_src, only_fissionable=False) + + settings.source = openmc.IndependentSource( + space=spatial_distribution, + energy=energy_distribution, + constraints={'domains': [mu2]}, + strength=1.0 + ) + + ######################################## + # Run test + + harness = MGXSTestHarness('statepoint.125.h5', model) + harness.main()